以前、ブログ記事「PHPのescapeshellcmdの危険性」にて、escapeshellcmd関数の「余計なお世話」によって危険性が生まれていることを指摘しましたが、その後大垣さんによって修正案が提示され、結局「それはマニュアルの間違い」ということで決着が着いたようです。ところが、この議論とは別のところで、escapeshellcmdはPHP5.4.0で挙動が少し変わっていることが分かりました。廣川さんが、大垣さんのパッチ案を少し修正してbugs.php.netに提案。PHP5.4.0リリース。大垣さんと廣川さんのパッチ提案に対して、lbarnaudさんが、「いやいや、escapeshellcmdはコマンド全体をエスケープするもので、提案のような使い方は想定してないよ、マニュアルの例も間違いだ」と指摘します。歴史的に見て、この指摘は正しいように思いました。ないと、escapeshellcmdとescapeshellargという別の関数が存在する理由が説明できません。PHPには、コマンド全体をエスケープするescapeshellcmdが存在したが、それだとコマンドの引数を追加する攻撃が出来てしまうので、escapeshellargという関数が後から追加されたのでしょう。いうことで、escapeshellcmdは修正せず、マニュアルの方を修正するということで決着がつきました。詳細は、bugs.php.netの方を参照下さい。マニュアルは既に修正されています。ところが・・・PHP5.4.0でescapeshellcmdの仕様が変わっていたこのエントリは、上記の顛末を報告するつもりで書き始めたのですが、念のためPHPの様々なバージョンでescapeshellcmdの挙動を確認したところ、PHP5.4.0でこの関数の仕様が変わっていたことが分かりました。サンプルスクリプトは以下です。削除されます」という動作に変わっています。その結果、echoの表示も、複数の空白が一つにまとめられています。マニュアルには、この仕様は記載されていないようですし、変更履歴にも載っていません。この修正も余計なお世話としか思えませんが、私の結論は変わりません。いうことで、先のエントリの結論を再掲します。余計なお世話としか言いようがありません。この仕様では、恐ろしくてescapeshellcmdは使えませんし、マニュアルにここまではっきり書いてある仕様を今さら変えられないでしょう。escapeshellcmdはお蔵入りするしかないと思います。escapeshellargの方はまともな仕様と思われますので、escapeshellargで代替してください。そもそもOSコマンドを呼ぶのがよいかとか、もっと良い方法はないのかという疑問が出てきます。それは、本が出てからのお楽しみ、ということで。廣川さんに確認したところ、上記はPHP5.4.0のバグだそうで、PHP5.4.1で元の仕様に戻るだろうということです。PHP5.4.0でescapeshellcmdを使用する際はご注意ください。廣川さん、確認ありがとうございました。[PR]Webサイトのセキュリティ強化策についての相談は、HASHコンサルティング株式会社まで。「安全なWebアプリケーションの作り方」DRMフリーのPDFによる電子版もあります。