CGI のセキュリティ

前へ << パーミッションと実行権限 CGI プログラムのデバッグ >> 次へ

open と system の罠

CGI プログラムと言えばセキュリティ。セキュリティと言えば CGI プログラム。CGI というのは、世界中の人がプログラムを実行できるわけですから、 そこにセキュリティホールがあれば、そのホストの安全性が低下します。
foreach ( split (/&/,$ENV{QUERY_STRING}) ){
    ($key,$value) = split('=',$_);
    $value =~ tr/+/ /;
    $value =~ s/%([0-9a-fA-F][0-9a-fA-F])/pack("C",hex($1))/eg;
    $FORM{$key} = $value;
}
open(IN,"$FORM{file}");
例えば、このスクリプト、環境変数 QUERY_STRING を解析し、 ハッシュ %FORM に代入しているだけですが、セキュリティホールがあります。 わかりますか?

普通、

hoge.cgi?file=sample.txt
という引数を渡せば、 sample.txt の内容を出力する、というような使い方をします。 ところが、悪意を持ったクラッカーが
hoge.cgi?file=%2Fbin%2Fcat+%2Fetc%2Fpasswd%7C
という引数だとどうなるでしょうか。tr/+/ / して、URL デコードした結果、 $FORM{file} = '/bin/cat /etc/passwd|' となってしまいます。 最後の `|' に注目して下さい。open の引数として最後に `|' が付いた文字列を渡すと、 コマンドとして実行して、その結果を受け取ります。結局
open(IN,"/bin/cat /etc/passwd|");
が実行され、ブラウザ上に /etc/passwd の結果が出力されてしまうのです。 /etc/passwd の内容が自由に閲覧できるということも重大な問題ですが、 それ以上に

ユーザを信用するな

環境変数を信用するな

cookie を信用するな

cookie も同様です。どんな cookie を送ってくるかなんてブラウザの自由、 ユーザの自由です。 本来は WWW サーバがブラウザに cookie を送り、 ブラウザが再度訪問したときに前回受け取った値を WWW サーバに送り返します。

だからといって cookie に不正な文字が入っていないなどと考えてはいけません。 ブラウザから送られてくる cookie に不正な文字が入っていないか、かならず チェックしましょう。

前へ << パーミッションと実行権限 CGI プログラムのデバッグ >> 次へ