Full Report
Apache Batik is a library used for parsing Scalable Vector Graphics (SVG) and transforming them into other formats. Even crazier, the documentation mentioned executing JavaScript, loading and executing Java classes and many other things. This felt like a SSRF goldmine to the attacker, with several previous vulnerabilities indicating this. A common use case is taking in an image or URL to an image to transform it using Apache Batik. The tool has many built in protections in place for scripting and other things. For ScriptSecurity, there are several different settings from no scripts to allowing scripts from loading remotely. In the security controls, there is the concept of origin within a URI. In particular, local SVG files can load scripts but not remote scripts. If we can bypass this control, we can do some horrible things! The parsing to ensure this works properly had a bug in it though. First, the script URL and the document URL get the host removed from it. Next, there is a check to see if the two hosts are the same. The getHost uses the standard Java function, which is known to behave strangely with non-HTTP protocols. The host for a local file (file:///some_file.txt) will always return NULL. Things like an external file and HTTP will properly return the host, making the check succeed. However, jar or Java Archives will also return NULL! Since the domains are now the same, the security protections no longer work as intended. The obvious attack vector is SSRF, but we can do more. Apache Batik supports remote class loading for with Java bindings. By including a remote class in our SVG to execute a JAR file, we can execute some Java code. Using this, it is pretty trivial to execute arbitrary code on the system. An additional way, if remote JAR loading is not allowed but scripts are, is abusing the ECMAScript engine. In particular, accessing the Java runtime from ECMAScript gets trivial code execution, by design. The official security guide for the ECMAScript standard is securing the application with a Java Security manager which is probably never used. Overall, parsing differentials are absolutely fascinating! It's super interesting seeing how this default and unexpected mechanism in Java caused such a big problem. However, the capabilities of these Apache products are just too powerful.
Analysis Summary
# Vulnerability: Apache Batik Security Control Bypass Leading to SSRF and RCE
## CVE Details
- CVE ID: ZDI-22-1328 (SSRF related) and ZDI-22-1327 (Script Security related)
- CVSS Score: Not explicitly provided for the summary, but the impact suggests **High** severity.
- CWE: CWE-400 (Uncontrolled Resource Consumption) or related to SSRF/RCE flaws.
## Affected Systems
- Products: Apache Batik
- Versions: Prior to version 1.15
- Configurations: Applicable when using default security modes like `DefaultScriptSecurity` or `DefaultExternalResourceSecurity`. RCE via remote JAR loading required non-default configurations.
## Vulnerability Description
The vulnerability stems from a parsing differential when comparing the hostnames of the document URI (`docURL`) and the requested resource/script URI (`scriptURL`) within Apache Batik's default security controls (`DefaultScriptSecurity` and `DefaultExternalResourceSecurity`).
The security check incorrectly compares hosts after removing the host component from both URIs using standard Java `getHost()`. This method returns `NULL` for certain protocols, notably `file://` URIs (local files) and `jar://` URIs (Java Archives).
If an attacker can craft an SVG that references a local resource (e.g., `file:///local_file.svg`) while attempting to load a remote resource using a protocol like `jar://` (for remote class loading) or another protocol whose host resolves to `NULL` when processed by `getHost()`, the comparison logic incorrectly deems the hosts as identical ("the same origin"). This successfully bypasses the security protections intended to block remote resource loading when the initial SVG is loaded locally (e.g., via `InputStream` or `file://`).
This bypass facilitates:
1. **SSRF:** Performing arbitrary GET requests or triggering NTLM challenges via protocols like `jar://` or UNC paths.
2. **Remote Code Execution (RCE):** If configured to allow remote JAR loading, the SSRF bypass allows execution of remote Java classes. RCE is also possible by abusing the ECMAScript engine to access the Java runtime if script execution is enabled.
## Exploitation
- Status: PoC available (demonstrated via video link in the source material).
- Complexity: Low (Bypass relies on specific URI handling differences in Java's `getHost()` function).
- Attack Vector: Network (for SSRF/remote class loading) or Adjacent/Local (if the entry point is a local file read).
## Impact
- Confidentiality: High (Potential for RCE leading to data exfiltration).
- Integrity: High (Potential for RCE leading to system modification).
- Availability: High (Potential for RCE leading to denial of service or system compromise).
## Remediation
### Patches
- Upgrade Apache Batik to **version 1.15 or later**.
### Workarounds
- Apply the strictest security controls possible, specifically **disabling script execution entirely** (`NoLoadScriptSecurity`) if Batik is used in an untrusted environment.
- Avoid using Batik or ensure that input SVG processing is handled by an environment where **security managers are enforced** (though the article notes this is often unused).
## Detection
- **Indicators of Compromise (IoCs):** Look for requests originating from the Batik processing host to internal or unauthenticated external resources, especially those using non-HTTP/HTTPS protocols like `jar://` or UNC paths if those are unexpected in the context.
- **Detection Methods and Tools:** Monitor security logs for attempts to load resources using protocols like `jar:` or attempting to connect to unusual network destinations during SVG processing. Review application configurations to ensure they are not relying on default security settings post-1.15.
## References
- Vendor Advisory: ZDI-22-1327, ZDI-22-1328
- Relevant links: hxxps://www.zerodayinitiative.com/blog/2022/10/31/vulnerabilities-in-apache-batik-default-security-controls-ssrf-and-rce-through-remote-class-loading