Lion Cipher Lab

Exploit and fix email header injection in a contact form

Why it matters

An email is not a magic object — it is just a block of plain text in a format called RFC 5322, where the top part is HEADERS (To:, From:, Subject:, Bcc:, one per line) and a blank line separates them from the BODY. The one detail that makes this a security topic is how those lines are separated: by a CARRIAGE RETURN followed by a LINE FEED, the two invisible control characters written \r\n (CRLF). So the moment a program builds an email by pasting untrusted user input into that text — for example `Subject: ` + whatever a visitor typed into a contact form — the visitor can type a \r\n of their…

What you'll learn

Steps in this lab

  1. The vocabulary: an email is plain text, and \r\n is what separates its lines
  2. Set up: Python, aiosmtpd, and a clean lab folder
  3. Build the local SMTP sink (it records recipients and the raw message — nothing leaves your machine)
  4. Build the VULNERABLE contact form (it hand-assembles the header block from user input)
  5. Measure the baseline: one clean submission, one recipient
  6. Exploit it: inject \r\nBcc: and watch recipients go from 1 to 3
  7. Why the tempting fix is incomplete — strip \n but not \r
  8. Fix it right — EmailMessage builds the headers, and reject CR/LF at the boundary
  9. Measure the fix: the identical payload is rejected, recipients back to 1
  10. What you did — the judgment, the honest negatives, and the reflex to keep

Open the full interactive lab →