第32回 PHPセキュリティ月間
前回もArthur Gerkis氏が投稿したPHPにおけるコード実行を解説した文書を紹介しました。今回はその続きです。
- MOPS Submission 07: Our Dynamic PHP - Obvious and not so obvious PHP code injection and evaluation
- http://
www. php-security. org/ 2010/ 05/ 20/ mops-submission-07-our-dynamic-php/ index. html
動的コード
動的コードでのコード実行には
動的変数
ブラウザからの入力をグローバル変数として初期化するregister_
<?php
foreach ($_GET as $key => $value) {
$$key = $value;
}
// ... some code
if (logged_in() || $authenticated) {
// ... administration area
}
?>
このコードに対して
http://www.example.com/index.php?authenticated=true
とアクセスすると、
PHP 4.
動的な関数
PHPには変数の中に保存された文字列を関数名として呼び出す、
<?php
$dyn_func = $_GET['dyn_func'];
$argument = $_GET['argument'];
$dyn_func($argument);
?>
このスクリプトに次のURLでアクセスすると、
http://www.example.com/index.php?dyn_func=system&argument=uname
次はcreate_
<?php
$foobar = "system('ls')";
$dyn_func = create_function('$foobar', "echo $foobar;");
$dyn_func('');
?>
このコードを実行するとsystem関数でlsコマンドが実行されます。create_
<?php
eval("function lambda_n() { echo system('ls'); }");
lambda_n();
?>
このように動作することはPHPマニュアルのcreate_
<?php
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo "新しい匿名関数: $newfunc\n";
echo $newfunc(2, M_E) . "\n";
// 出力
// 新しい匿名関数: lambda_1
// ln(2) + ln(2.718281828459) = 1.6931471805599
?>
{}構文
PHPは変数とテキストを分けるための{$var_
<?php
$var_name = '変数';
echo "これは日本語のテキストに{$var_name}を埋め込んでいます";
?>
日本語のように単語の区切りが無いテキストに変数を埋め込むためには必須の構文です。この構文を利用すると変わったコード実行が可能になります。
<?php
$var = "I was innocent until ${`ls`} appeared here";
?>
このコードを実行すると`ls`をPHPスクリプト中で実行したようにlsコマンドを実行します。PHPがこのような動作するのは${}の中に入っている文字列をPHPのコードとして評価しているからです。${`ls`}はlsを実行した結果を変数名として利用しようとします。
これを利用すると、
<?php
$foobar = 'phpinfo';
${'foobar'}();
?>
この脆弱性だけではセキュリティ上の脅威となりませんが、
コード実行可能だが稀なケース
ob_
<?php
$foobar = 'system';
ob_start($foobar);
echo 'uname';
ob_end_flush();
?>
$foobarと出力バッファの内容を制御できる場合はコード実行攻撃を行えます。
assert関数はeval関数と同様の動作をするので簡単に攻撃可能ですが、
<?php
$foobar = 'system("uname")';
assert($foobar);
?>
配列関数の多くがコールバック関数をサポートしています。脆弱性となるケースは稀ですがコールバック関数を利用してコード実行が可能です。
<?php
$evil_callback = 'phpinfo()';
$some_array = array(0, 1, 2, 3);
$new_array = array_map($evil_callback, $some_array);
?>
$evil_
XML関数やSTREAM関数もコールバック関数を利用可能であるため配列関数と同様の手法で攻撃される可能性があります。
ob_start()
preg_replace()
preg_replace_callback()
array_map()
usort(), uasort(), uksort()
array_filter()
array_reduce()
array_diff_uassoc(), array_diff_ukey()
array_udiff(), array_udiff_assoc(), array_udiff_uassoc()
array_intersect_assoc(), array_intersect_uassoc()
array_uintersect(), array_uintersect_assoc(), array_uintersect_uassoc()
array_walk(), array_walk_recursive()
xml_set_character_data_handler()
xml_set_default_handler()
xml_set_element_handler()
xml_set_end_namespace_decl_handler()
xml_set_external_entity_ref_handler()
xml_set_notation_decl_handler()
xml_set_processing_instruction_handler()
xml_set_start_namespace_decl_handler()
xml_set_unparsed_entity_decl_handler()
stream_filter_register()
set_error_handler()
set_exception_handler()
register_shutdown_function()
register_tick_function()
その他の手法
次のPoCは実際には動作しませんが、
<?php
class Example {
var $var = '';
function __destruct() {
eval($this->var);
}
}
unserialize($_GET['saved_code']);
?>
この攻撃を成功させるには攻撃用のクラス定義を読み込ませるか、
MOPBでStefan Esser氏はunserialize関数のメモリエラーを利用した攻撃方法を紹介すると同時に、
複数のデータやオブジェクトや配列を文字列として保存できるシリアライズ機能は便利ですがリスクが存在することも知っておくとよいでしょう。
Gerkis氏が参考文献としたURLの一覧
- http://
www. hardened-php. net/ suhosin/
Suhosin, advanced protection system for PHP - http://
projects. webappsec. org/ Remote-File-Inclusion
explanation of RFI - http://
tools. ietf. org/ html/ rfc2397
The “data” URL scheme - http://
www. php. net/ manual/ en/ wrappers. data. php
Data (RFC 2397), PHP manual - http://
www. ush. it/ 2008/ 08/ 18/ lfi2rce-local-file-inclusion-to-remote-code-execution-advanced-exploitation-proc-shortcuts/
how LFI can lead to RCE - http://
www. exploit-db. com/ papers/ 260
how LFI can lead to RCE (2) - http://
www. sektioneins. com/ en/ advisories/ index. html
まとめ
Gerkis氏は、
安全なソースコードを書くためにはホワイトリスト型の対策でユーザ入力を検査すべきで、
開発者にとって便利な機能はセキュリティリスクとなることがよくあります。セキュリティとは利便性とのトレードオフの関係にあるので当然です。動的言語は非常に便利な反面、
次回はMOPSで紹介された静的にソースコードを分析する脆弱性スキャナ