OSコマンドインジェクションがあるのに500 Internal Server Errorが出てしまう場合の対処

OSコマンドインジェクションの脆弱性がありそうなのに500 Internal Server Errorから抜け出せないケースがあります。これは昔ながらのPerlによるCGIでよく目にします。

なぜ500 Internal Server Errorが出てしまうのか?その原因を知っていれば解決方法が簡単であることに気づくはずです。

脆弱性の仕組み

PerlでOSコマンドインジェクションが発生しやすいのはopen関数です。Perlのopen関数はファイル名の先頭もしくは末尾にパイプ「|」を挿入するとコマンドとして実行されます。

たとえば以下のようなURLがあるとして

https://example.com/foo.cgi?filename=foo.csv

こんな風にアクセスするとOSコマンドが実行されることがあります。

https://example.com/foo.cgi?filename=|whoami

非常にシンプルで古典的な脆弱性ながら、この種のOSコマンドインジェクションの脆弱性をもったWebサイトは今でも少なからず存在しています。

なぜ500 Internal Server Errorが出るのか?対策は?

多くの場合、そのままコマンドの実行結果が表示されるのですが稀に500 Internal Server Errorが出ることがあります。

原因はHTTPヘッダーにContent-typeがないからです。つまりHTTPヘッダーの「Content-type: text/html」を送信する前にopen関数でOSコマンドが実行されると500 Internal Server Errorが出ます。

ではどうすれば良いのか?簡単です。自分でContent-typeを送信してやれば良いだけです。つまり、次のようにします。

https://example.com/foo.cgi?filename=|echo "Content-type: text/html";echo;whoami

ヘッダーとボディの間には空行が必要なのでechoで空行を送信している点に注意してください。

まとめ

500 Internal Server Errorを解決できずに諦めてしまった経験がある方は参考にして頂ければ幸いです。最近はPHPやPython、RubyやNode.jsが主流でPerl CGIを目にする機会は減っていますが、今でもPerl CGIのOSコマンドインジェクションを抱えたWebサイトが少なからず存在しています。

この記事は役に立ちましたか?

もし参考になりましたら、下記のボタンで教えてください。