今回の脆弱性
CVE-2016-10033
PHPMailer5.2.18より下のバージョンで発生します。
フォームからメールアドレスを受け付けて自前バリデーションせずにPHPMailerのFromにセットしている場合に発生する可能性。
任意のPHPコードをサーバに設置できるため、外部からWebシェルなどが設置されるなど、影響は大きいです。
影響が大きいため、PHPMailerを使っているCMSなど(WordPress, Drupal, 1CRM, SugarCRM, Yii,Joomla!)も含めてバージョンアップが必要です。PHPMailerはメール送信ライブラリのため、知らない間にプラグインなどで利用されている可能性もあります。
WordPressの場合はwp-includes/class-phpmailer.php
ですかね。
2016年12月28日の時点で、このチケットで議論されているようです。
すぐにアップデートできない人は、
$params = sprintf('-f%s', $this->Sender);
となっている箇所を、
$params = sprintf('-f%s', escapeshellarg($this->Sender));
にしておくと良いかも。(自己責任で)
影響範囲
PHPMailer5.2.18より下のバージョンで、メール送信にSendmailを使っている場合、下記の条件になります。
- PCREが入っている場合
- すべてのPHPバージョンで影響
- PCREが入っていない場合
- PHP5.2より下のバージョンで影響
- PHP5.2より下のバージョンで影響
PoCでは、以下のようにPCREが入ってないことが条件になってますが、それはこのPoCの条件であって他のパターンではPCREが入ってても抜けてしまいます。
- PHPMailer < 5.2.18
- Compile PHP without PCRE.
- PHP version must be inferior to 5.2.0.
例えばこんなコードで検証すればPCREが入ったPHP5.2以上の環境でもメールアドレスのバリデーションは通ってしまいます。
<?php
require 'PHPMailerAutoload.php';
//$address = 'ichikaway@gmail.com';
$address = '"attacker\" -oQ/tmp/ -X/var/www/cache/phpcode.php some"@email.com';
var_dump(PHPMailer::validateAddress($address)); // true
悲しいことに、PCREが入っているほうがPHPの対象範囲が広くなってしまいます・・・
PCREが入っておらず、PHP5.2以上の場合はPHPのfilter_var()でメールアドレスチェックが行われるため救われます。PCREの正規表現よりもfiter_var()を優先すれば良いのに・・・
コードはこのあたりをみればバリデーションの適用条件がわかると思います。
https://github.com/PHPMailer/PHPMailer/blob/master/class.phpmailer.php#L1068
最新版のパッチ
パッチはこれです。
この箇所で、escapeshellarg()を使って引数として利用される文字列をエスケープしています。