MOPB-34-2007:PHP mail() Header Injection Through Subject and To Parameters

(Last Updated On: 2018年8月16日)

Stefanさんの承諾を得て日本語訳を公開しています。このブログの「the Month of PHP Bugs」カテゴリでMOPBの翻訳ページを一覧できます。分かりやすいように意訳できる部分は意訳します。厳密に原文の通り訳していないので正確性を重視される方は原文をご覧ください。

■クレジット
発見者:Stefan Esser
攻撃コード:Stefan Esser

■PoCまたは攻撃コード
必要なし

■リファレンス
なし

■サマリ
mail()関数はメールヘッダインジェクションを防ぐ為にSubjectとToに含まれるLFやCRなど制御文字をスペースに変換しています。しかし、次の行に続くメールヘッダの折りたたみ(改行)には例外が設けられています。(訳注:今のMTA,UMAはヘッダが長くても問題なく処理出来るものがほどんとですが、RFCでは長いヘッダは折りたたむように規定されている)残念ながらこの折りたたみ処理には問題があり、メールヘッダインジェクションが可能になります。

■影響するバージョン
PHP 4.4.6以下、PHP 5.2.1以下

■詳細情報
mail()関数はメールヘッダの折りたたみ処理のために以下のようなコードを利用しています。可読性の為、マクロは展開してあります。

for(i = 0; subject_r[i]; i++) {
if (iscntrl((unsigned char) subject_r[i])) {

//SKIP_LONG_HEADER_SEP(subject_r, i);
if (str[pos] == ‘\r’ && str[pos + 1] == ‘\n’ && (str[pos + 2] == ‘ ‘ || str[pos + 2] == ‘\t’)) {
pos += 3;
while (str[pos] == ‘ ‘ || str[pos] == ‘\t’) {
pos++;
}
continue;
}

subject_r[i] = ‘ ‘;
}
}

SKIP_LONG_HEADER_SEPマクロの意図は折りたたみ済みのヘッダ行を検出し、CRとLFをスペースで上書きしないことです。残念ながらこの処理は明らかな不具合があります。折りたたみ処理の直後に制御文字がある場合(LFやCRなど)continueコマンドが間違ってループカウンタiをインクリメントさせるためスペースに置換されません。この為 \r\n\t\n のような単純な文字列で改行を挿入出来てしまいます。

このインジェクションはSubjectとTo引数のどちらでも可能です。テストの課程で、古いsendmailでは正常に処理しましたが、eximはヘッダに対するNLインジェクションに問題があるようです。
(訳注:HTTP Response Splitingでも同じように、CR/LFで改行なのですがCR,LF単体で改行として処理してしまうシステムも多くありました)

■PoC、攻撃コードまたは再現手順
簡単な脆弱性テストは以下のようなPHPスクリプトです。

<?php
mail(“test@domain(dot)com”, “Test\r\n \nAnother-Header: Blub”, “Message”);
?>

■備考
メールインジェクションに関する文書では通常は追加のヘッダパラメータによるヘッダインジェクションについてのみ解説しています。残念ながらこの脆弱性と前の脆弱性(訳注:MOPB-33-2007)は全てのmail()関数引数はメールインジェクション問題を発生させる疑いがあることを証明しています。

投稿者: yohgaki