from:http://blog.gosecure.ca/2016/04/27/binary-webshell-through-opcache-in-php-7/
PHP 7.0 がリリースされたとき、多くの PHP 開発者がいました。パフォーマンスの向上に非常に重点を置いています。 OPcache の導入後、PHP のパフォーマンスは実際に大幅に向上し、その後、多くの開発者が PHP アプリケーションのアクセラレータとして OPcache を使用し始めました。 OPcache は優れたパフォーマンスをもたらしますが、新たなセキュリティ リスクももたらします。次の内容は、PHP 7.0 で PHP コードを実行する OPcache について GoSecure ブログによって公開された技術ブログ投稿です。
この記事では、PHP7 のデフォルトの OPcache エンジンを使用して攻撃を実装する新しい方法を紹介します。この攻撃ベクトルを使用すると、攻撃者は「Web ディレクトリではファイルの読み取りと書き込みが禁止されている」という制限を回避したり、独自の悪意のあるコードを実行したりすることができます。
OPcache は、PHP 7.0 に組み込まれているキャッシュ エンジンです。 PHP スクリプト ファイルをバイトコードにコンパイルし、そのバイトコードをメモリに配置します。
PHP7 を使用して Web アプリケーションを高速化します
OPcache キャッシュ ファイル形式については、こちらを参照してください。
同時に、ファイルシステムにキャッシュファイルも提供します。 PHP.ini の設定は次のとおりです。キャッシュ ディレクトリを指定する必要があります。
opcache.file_cache=/tmp/opcache
指定されたディレクトリに、OPcache はコンパイルされた PHP スクリプト ファイルを保存し、これらのキャッシュ ファイルは Web ディレクトリと同じディレクトリ構造に配置されます。たとえば、コンパイルされた /var/www/index.php ファイルのキャッシュは、/tmp/opcache/[system_id]/var/www/index.php.bin に保存されます。
system_id は、現在の PHP バージョン番号、Zend 拡張バージョン番号、および各データ型サイズの MD5 ハッシュ値です。最新バージョンの Ubuntu (16.04) では、system_id は現在の Zend と PHP のバージョン番号から計算され、その値は 81d80d78c6ef96b89afaadc7ffc5d7ea です。このハッシュは、複数のインストール間でバイナリ キャッシュ ファイルの互換性を確保するために使用される可能性が高くなります。上記のディレクトリは、OPcache が初めてファイルをキャッシュするときに作成されます。
この記事の後半では、system_id が各 OPcache キャッシュ ファイルのファイル ヘッダーに格納されていることを確認します。
興味深いことに、Web サービスを実行しているユーザーは、OPcache キャッシュ ディレクトリ (/tmp/opcache/ など) 内のすべてのサブディレクトリとファイルに対する書き込み権限を持っています。
#!shell$ ls /tmp/opcache/drwx------ 4 www-data www-data 4096 Apr 26 09:16 81d80d78c6ef96b89afaadc7ffc5d7ea
ご覧のとおり、www-data ユーザーは OPcache キャッシュ ディレクトリへの書き込み権限を持っているため、OPcache キャッシュ ディレクトリ内の既存のキャッシュ ファイルをコンパイルされた Web シェルのキャッシュ ファイルに置き換えることでこれを実現できます。悪意のあるコードを実行する目的。
OPcache を使用してコードを実行するには、まず OPcache のキャッシュ ディレクトリ (/tmp/opcache/[ system_id] など) と Web ディレクトリ (/ など) を見つける必要があります。 var/www/)。
ターゲットサイトには phpinfo() 関数を実行するファイルがすでに存在すると仮定します。このファイルを通じて、OPcache キャッシュ ディレクトリ、Web ディレクトリ、および system_id の計算に必要ないくつかのフィールド値を取得できます。 phpinfo()を使用してsystem_idを計算できるスクリプトを書きました。
また、ターゲット サイトにはファイル アップロードの脆弱性が必要であることにも注意してください。 php.ini で opcache を構成するためのオプションが次のとおりであると仮定します。
opcache.validate_timestamp = 0 ; PHP 7 的默认值为 1opcache.file_cache_only = 1 ; PHP 7 的默认值为 0opcache.file_cache = /tmp/opcache
現時点では、アップロードの脆弱性を使用して Web ディレクトリにファイルをアップロードできますが、Web ディレクトリには読み取りおよび書き込みのアクセス許可がないことがわかります。 。現時点では、/tmp/opcache/[system_id]/var/www/index.php.bin を WebShell バイナリ キャッシュ ファイルに置き換えることで、WebShell を実行できます。
次のコードを使用して、Webシェル ファイルindex.phpをローカルに作成します:
#!php<?php system($_GET['cmd']); ?>
PHP.iniファイルのopcache.file_cacheを指定したいキャッシュディレクトリに設定します
PHPサーバーを実行します(php -S 127.0.0.1:8080)、次にリクエスト (wget 127.0.0.1:8080) をindex.phpに送信して、キャッシュエンジンをトリガーしてファイルをキャッシュします。
設定したキャッシュ ディレクトリを開きます。index.php.bin ファイルは、コンパイルされた WebShell バイナリ キャッシュ ファイルです。
index.php.bin ファイルヘッダーの system_id をターゲットサイトの system_id に変更します。ファイルヘッダーの署名部分の後には system_id の値が続きます。
アップロードの脆弱性を利用して、変更されたindex.php.binを/tmp/opcache/[system_id]/var/www/index.php.binにアップロードし、元のindex.php.binを上書きします
Index.php に戻って、WebShell を実行してください
この攻撃手法に対応して、このタイプの攻撃を防御するための php.ini の構成メソッドが少なくとも 2 つあります。
メモリ キャッシュ メソッドの優先順位がファイル キャッシュよりも高い場合、書き換えられた OPcache ファイル (Webシェル)は意志です実行されないこと。ただし、Web サーバーを再起動すると、この制限は回避できます。サーバーの再起動後、メモリ内のキャッシュは空になるため、OPcache は Web シェルを実行できるように、ファイル キャッシュ データを使用してメモリ キャッシュ データを埋めます。
しかし、この方法は役に立たず、サーバーを再起動する必要があります。サーバーを再起動せずにWebシェルを実行する方法はありますか?
後で、WordPress などのフレームワークには、リリースされたバージョンでもまだアクセスできる古いファイルが多数あることがわかりました。例: register-functions.php
これらのファイルは古いため、Web サーバーの実行中にこれらのファイルは読み込まれません。つまり、これらのファイルにはファイルまたはメモリ キャッシュのコンテンツがありません。この場合、Webシェルのバイナリ キャッシュ ファイルをregistration-functions.php.binとしてアップロードし、/wp-includes/registration-functions.phpへのアクセスをリクエストすると、OPcacheはアップロードしたregistration-functions.phpをロードします。 .bin キャッシュ ファイル。
サーバーがタイムスタンプ検証を有効にしている場合、OPcache はアクセスを要求された PHP ソース ファイルのタイムスタンプを、対応するキャッシュ ファイルのタイムスタンプと比較して検証します。 2 つのタイムスタンプが一致しない場合、キャッシュ ファイルは破棄され、新しいキャッシュ ファイルが生成されます。この制限を回避するには、攻撃者はターゲット ソース ファイルのタイムスタンプを知っている必要があります。上で述べたように、WordPress などのフレームワークでは、zip または tar パッケージを解凍しても、多くのソース ファイルのタイムスタンプは変わりません。
上の図に注目してください。registration-functions.php やRegistration.php など、一部のファイルは 2012 年以来一度も変更されていないことがわかります。したがって、これらのファイルは WordPress の複数のバージョンで同じです。タイムスタンプを知ることで、攻撃者は validate_timestamps 制限をバイパスし、キャッシュ ファイルを上書きし、Web シェルを実行することができます。バイナリ キャッシュ ファイルのタイムスタンプは 34 バイトのオフセットです。
OPcache この新しい攻撃ベクトルは、制限を回避するいくつかの攻撃方法を提供します。ただし、これは一般的な PHP の脆弱性ではありません。 PHP 7.0 の人気が高まるにつれ、アップロードの脆弱性を回避するためにコードを監査することが必要になります。そして、危険な可能性のある構成項目がないか確認してください。