【実務・中級編】メールヘッダーインジェクションによるスパム送信とフィッシング – アプリケーションセキュリティ & 安全な開発防御ガイド

メールヘッダーインジェクション:その「改行」が世界を壊す

やあ、現場の最前線でコードと格闘している諸君。今日は「メールヘッダーインジェクション」について話そう。

「今どきそんな古い脆弱性?」と鼻で笑ったそこの君。それが一番危ない。この攻撃は、現代の複雑なクラウドアーキテクチャやマイクロサービス間でも、レガシーなSMTPライブラリや不適切なユーザー入力処理が残っている限り、いとも簡単にゲートをこじ開けてくる。

実際に僕のインシデント対応経験でも、この脆弱性を突かれて自社サーバーがスパムの踏み台にされ、IPレピュテーションが地に落ちて、全メールがGmailの迷惑メールフォルダに直行するようになったケースは一度や二度じゃない。今日は、この攻撃の真の恐怖と、現場で通用する「二度と穴を開けないための実装」を叩き込む。

—

1. 攻撃のメカニズム:CRLFがもたらす「意図せぬ制御」

メールヘッダーインジェクションの本質は、SMTPプロトコルの脆弱性ではなく、「ヘッダーと本文の境界」を改行コード(\r\n)で強制的に操作することにある。

多くのメール送信ライブラリは、内部的に以下のような形式でメールを構築する。

To: {ユーザー入力値}
Subject: お問い合わせの件
From: system@example.com

本文…

ここで、攻撃者が To フィールドに victim@target.com\r\nBcc: spam-target@attacker.com\r\nSubject: 詐欺サイトへようこそ と入力したらどうなるか?

SMTPサーバーに渡される文字列はこう書き換わる。

To: victim@target.com
Bcc: spam-target@attacker.com
Subject: 詐欺サイトへようこそ
Subject: お問い合わせの件
From: system@example.com

本文…

結果として、本来の宛先以外にスパムメールが密かに送信され、件名も乗っ取られる。これが「BCC追加」や「本文の改ざん」のカラクリだ。攻撃者はこれを使って、フィッシングサイトへの誘導や、自社サーバーの信用毀損を狙う。

—

2. 実務で「完全に」防ぐためのコード実装

インジェクションを防ぐ鉄則は、「ユーザー入力をヘッダー値に直結させない」ことだ。特に、改行コードが含まれていないか厳格にチェックする必要がある。

PHPでの対策実装(バリデーションの徹底)

PHPの mail() 関数を直接叩くような古い実装は避け、PHPMailer や Symfony Mailer などのモダンなライブラリを使うのが前提だ。しかし、もし既存コードを改修するなら、以下のようなガード節を必ず挟むこと。

function is_safe_header_value(string $value): bool {
// 改行コード(CR: \r, LF: \n)が含まれていないかチェック
// 含まれていれば攻撃とみなして弾く
if (preg_match(‘/[\r\n]/’, $value)) {
return false;
}
return true;
}

$user_email = $_POST[‘email’];

if (!is_safe_header_value($user_email)) {
// ログに記録し、攻撃をブロック
error_log(“不正なヘッダー入力の試行: ” . $user_email);
die(“Invalid input.”);
}

// 送信処理(ライブラリ使用時も必ずバリデーションを通す)

Python (smtplib) での対策例

Pythonでも同様だ。ライブラリ側でエスケープしてくれる場合もあるが、信頼しきってはいけない。

import re

def send_secure_email(to_address, subject, body):
# 改行コードの検知
if re.search(r'[\r\n]’, to_address) or re.search(r'[\r\n]’, subject):
raise ValueError(“Invalid header input detected.”)

# ここからSMTP送信処理へ(SMTPヘッダー構築時はライブラリのAPIを正しく使う)
# email.message.EmailMessage クラスを使用することを推奨

—

3. インフラ・環境レベルでの防御(多層防御)

コードレベルの修正に加え、インフラ側でも「もしコードに穴があっても被害を出さない」ためのガードを固める。

Nginx/WAFでのフィルタリング

WAF(AWS WAF等)を使っているなら、「CRLFを含むリクエストをブロックする」ルールを適用しろ。これはWebアプリケーションへの攻撃全般に有効な汎用的な防御策だ。

メールサーバー(Postfix等)の制限設定

SMTPサーバー側で、ヘッダー内の不正な改行を許容しない設定(厳格なRFC準拠)を行うこと。main.cf に以下のような制限を加えるのも有効だ。

Postfixの例:不正なヘッダーフォーマットを拒否
smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, reject_non_fqdn_recipient

—

最後に:なぜ「ライブラリ」を使うのか

現場のエンジニア諸君に最後に伝えておきたい。「独自のメール送信関数を作ろうとしないこと」。

メールプロトコルは非常に複雑で、エンコーディングや引用符の扱い一つでヘッダーインジェクションの余地が生まれる。PHPMailer や PythonのEmailMessage といった、長年世界中の開発者がバグを潰し続けてきたライブラリは、そうしたエッジケース(特殊な文字コードや制御文字)に対する防壁が標準で組み込まれている。

「自分で書いたほうが軽いから」という理由で独自のSMTP構築を行うのは、セキュリティの世界では「無防備な要塞を作る」ことと同義だ。

コードを修正したら、必ず \r\n を含めた入力値でテストすること。もし開発環境でメールが送信されたら、それは脆弱性が残っている証拠だ。自分の書いたコードが、いつか世界を混乱させる踏み台にならないよう、今一度、入力を疑う癖をつけてほしい。

現場からは以上だ。何かあればいつでも相談してくれ。

コメント

タイトルとURLをコピーしました