Note
web
python
crlf-injection
xml-entities
pycurl
latin1
ssrf
Decode numeric XML character references into literal CRLF and carry them through latin1 into a low-level request builder.
CRLF Injection via XML Entities + latin1 in pycurl.CUSTOMREQUEST
Numeric XML character references decode into literal \r\n bytes before the HTTP layer sees them. If
the app feeds that text directly to a request method or header builder, you can splice a second line
into the backend request. latin1 preserves byte values 0x0d/0x0a exactly, carrying CRLF through
where stricter normalizers would block it.
Why It Works
- Entity decoding happens first; the resulting raw CR/LF survives into
pycurl.CUSTOMREQUESTor a header builder.
Vulnerable Pattern
- XML-controlled
method, header, or path fields passed intopycurl.CUSTOMREQUEST,setopt, or similar low-level request APIs. - Internal SSRF components letting the attacker influence both target and method string.
Exploit Flow
- Confirm entity decoding using harmless test headers or request-line modifications.
- Once CRLF is preserved, inject a second header, alter
Host, or fully control the request line toward an internal service.
Variations
Header: x, body, or full request-line smuggling if the target API is low-level enough.
Common Blockers
- Libraries that validate methods strictly after decoding, or proxy layers that reject malformed internal requests.
PoC Sketch
<method>GET / HTTP/1.1 Host: 127.0.0.1 X-Test: 1</method>
Good Situations To Use It
- You already have XML-driven SSRF into
pycurl. - The method/header field is built from decoded entity text.
- latin1 (or a CRLF-preserving) encoding is in the path.
Sources
fcsc2026/web/bubulle_corp_2