SMTP Injection in Bug Bounty: Finding and Proving Mail Header Bugs
SMTP injection is old, but contact forms, invite flows, and "email this page" features still glue untrusted strings into raw mail headers. When the app builds a message with string concatenation instead of a library API, a CRLF in your input can add Bcc:, rewrite Subject:, or append a second message.
The finding is not "I put a newline somewhere." The finding is mail that left the program's infrastructure with headers or recipients you controlled.
Where the glue lives
Hunt any endpoint that takes an address, name, subject, or body and promises delivery. Password reset is usually library-safe; marketing forms and internal tooling are not. Look for:
- Contact us with a free-text "reply-to" or "your email"
- Share / invite teammates by address list
- Ticket systems that echo reporter email into outbound mail
- PDF or report generators that email a link to a user-supplied address
Intercept the request. If the field lands in a JSON body, still try CRLF encodings: %0d%0a, literal newlines if the parser keeps them, and Unicode line separators that some stacks normalize badly.
I've seen programs reject plain \n in JSON yet accept %0aBcc:you@attacker.tld after a double decode on the mail worker. Test both the public API and any async job that actually talks to the MTA.
Prove it with a mailbox you own
Never BCC random people. Use an address on a domain you control, plus a unique subject canary such as bf-smtp-4817.
A minimal injection shape for a name or email field:
test@example.com%0d%0aBcc:%20canary@yourdomain.tld
Or, when the app puts your input into the subject:
Hello%0d%0aBcc:%20canary@yourdomain.tld%0d%0aX-Bugflare:%20yes
Trigger once. Check your mailbox and the raw source. Confirm the injected header exists, the message came from the target's usual sending domain or IP, and your canary received a copy. Screenshot the raw headers. That is the proof.
If the form only reflects the newline in an HTML error and never sends mail, stop. No outbound message means no SMTP injection impact.
What triage argues about
Programs disagree on severity. Adding a Bcc to yourself on a public contact form is often medium: you demonstrated header control and silent carbon-copy. Turning that into phishing of other users needs clearer scope language and usually stays out of bounds unless the program allows limited phishing against your own second account.
Separate SMTP injection from open relays. An open relay accepts arbitrary RCPT TO from the internet. Injection hijacks an application-triggered send. Say which one you found.
Also separate display tricks from protocol breaks. A subject that looks like it contains From: admin in a web UI is not the same as a second SMTP DATA section. Read the raw message.
Fix language that helps
Recommend building messages through the mail library's structured fields (to, cc, subject as typed arguments), rejecting CR/LF in address and header inputs, and using authenticated submission with fixed envelope recipients where possible. DKIM and SPF do not stop header injection inside an already-authorized send; they only prove the message left the right place.
One clean send to your canary beats a wall of encoded newline variants with no delivery proof.