pwneglyph logo
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.CUSTOMREQUEST or a header builder.

Vulnerable Pattern

  • XML-controlled method, header, or path fields passed into pycurl.CUSTOMREQUEST, setopt, or similar low-level request APIs.
  • Internal SSRF components letting the attacker influence both target and method string.

Exploit Flow

  1. Confirm entity decoding using harmless test headers or request-line modifications.
  2. 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&#13;&#10;Host: 127.0.0.1&#13;&#10;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