[PR]小規模ECサイトに最適なWAF、SiteGuard Lite

徳丸浩の日記


2011年01月04日

_escapeshellcmdの危険な実例

 先日の日記PHPのescapeshellcmdの危険性ではPHPのescapeshellcmd関数の危険性について指摘しましたが、脆弱となる実例を挙げていなかったので、「本当に危険なのか」と半信半疑の方もおられると思います。そこで、同関数が危険となる実例を考えたので報告します。

grepを使って、サーバー内を検索するスクリプトを考えます。

<?php
  header('Content-Type: text/html; charset=UTF-8');
?>
<html>
<body><pre>
<?php
  $key = @$_GET['key'];
  $out = shell_exec('grep --no-filename "' . escapeshellcmd($key) . '" /var/data/*');
  echo htmlspecialchars($out, ENT_COMPAT, 'UTF-8');
?>
</pre></body>
</html>

このスクリプトは、外部からのキーワードを/var/data/内のファイル群から検索して表示するものです。PHPのshell_execute関数を用いて、実行結果を文字列として返し、htmlspecialcharsでHTMLエスケープしています。検索キーはescapeshellcmdでエスケープした結果をダブルクォートで囲っています。

一見、なんの問題もないスクリプトに見えます。まずは正常系の結果です。key=bookで実行してみます。

book:村上春樹
book:芥川龍之介
book:シェークスピア

bookを含む行が表示されました。

次に攻撃です。key=:"+"/etc/passwd として実行してみます。以下の結果となります。

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
…略

/etc/passwdの内容が表示されました。エスケープしているのに、なぜこの結果になるのでしょうか。

それは、escapeshellcmdが「' および " は、対になっていない場合にのみエスケープされます。」という仕様のためです。このため、grepの起動文字列は次のようになっています。

grep --no-filename ":" "/etc/passwd" "/var/data/*"

/etc/passwdの各行にはコロンが含まれていますから、これで/etc/passwdの全行が表示されます。適当な文字がなければ「$」(行末にマッチ)などを指定してもいいですね。

あるいは、PHPのソースを表示することもできます。key=$"+"/var/www/html/grep.php と指定すると、以下の表示になります。

<?php
  header('Content-Type: text/html; charset=UTF-8');
?>
<html>
<body><pre>
<?php
  $key = @$_GET['key'];

この検索プログラム自体のソースが表示されました。スクリプトのソースが見えれば、他の脆弱性を探すのも楽ちんですよね。

escapeshellcmdの「' および " は、対になっていない場合にのみエスケープされます。」という仕様により、1つのパラメータが2つのパラメータに分かれてしまうことが問題です。これはescapeshellcmdの脆弱性というよりは、仕様の不備と言うしかないでしょうね。マニュアルに書いてある通りの動作が問題な訳ですから。というわけで、escapeshellcmdよりはescapeshellargを使えということと、そもそもOSコマンドを呼ばないなどのもっと良い方法を検討しましょう、というお話です。



[PR]小規模ECサイトに最適なWAF、SiteGuard Lite

ockeghem(徳丸浩)の日記はこちら
HASHコンサルティング株式会社

最近の記事

最近のツッコミ

  1. かめ (11-29)
  2. いーさん (09-27)
  3. こういち (07-13)
Google