[画像のクリックで拡大表示]

 「(PHPで書かれたアプリケーションには)アバウトなコードが多い」。エレクトロニック・サービス・イニシアチブの大垣靖男社長は,2006年8月19日に開催されたPHP関連イベント「PHPカンファレンス2006」の講演「危険なコード」で,PHPで書かれたアプリケーションに存在する危険なコードを指摘した。講演の中では,実際に存在するアプリケーションの名前を出し,そのソースコードからセキュリティ上危険な個所を挙げていった。「安全なコードを書くには悪い例も知っておかなければならない」というのが同氏の主張である。

 大垣氏はまず,「セキュリティのリスクはサブシステムとの境界の部分で発生する」と指摘した。サブシステムとは,データベース,メール・システム,ユーザーのWebブラウザといった外部のシステムのこと。「境界で入力時にきちんとバリデーション,出力時にきちんとエスケープ処理(フィルタリング)を行えば,かなりのセキュリティ・ホールは防げる」(大垣氏)。

 例として取り上げたアプリケーションは,オープンソース・ソフトウエアの配布に使われているSourceForge.netで,おおむねトップ30から50までの間にあるものから選んだという。「上位のアプリケーションを選ぶと,問題があるアプリケーションを探すのが大変かもしれない」(大垣氏)という理由からである。ソースコードはすべて8月13日時点でリリースされていたものを使用した。

 ただし,大垣氏は「すべてのアプリケーションを実際に動作させたわけではない」と語る。また「正式な検証作業」でもないという。ソースコードの一部しか読んでおらず,また,すべてのぜい弱性の可能性を検証しているわけではないからだ。「危険なコード=セキュリティ・ホール」ではない点にも注意が必要である。コードにぜい弱な部分があっても,その部分を攻撃できる経路がなければセキュリティ・ホールにはならない。この発表の目的はあくまで「危険なコーディングと安全なコーディングを知ること」である。加えて「よく使われているアプリケーションにも危険なものがある」ことを理解するという意味もある。「個人レベルで自己責任の範囲で使うならいいが,顧客のシステムでPHPアプリケーションを使う場合には,きちんとソースコードの中身を検証しなければまずいことがあるという点を理解してほしい」と同氏は強調した。

 なお,この記事ではソフトの名称は匿名とする。大垣氏の発表の目的が特定のアプリケーションに対する揚げ足取りではないこと,名前の挙がったアプリケーションさえ使わなければ安全だという誤解が生じる可能性があること,Webの記事は不特定多数が見ることができるため問題を実際に悪用される危険性があること,といった理由からである。

大量に見つかったSQLインジェクションの問題

 大垣氏が最初に取り上げたのは,あるイベントリ管理ソフトウエア。こうしたシステム管理者向けアプリケーションは,セキュリティ対策がずさんなことが比較的多いという。システム管理者が自分のために作っていることが多く,「データベースに対してフルアクセスできて当たり前」という感覚でコードを書いてしまうからだ。

 まず,未検証のユーザー入力値をそのままクエリーとして実行している部分があった。実際には,安全に実行できるようエスケープ処理が必要だ。そうでなければSQLインジェクションができてしまう。他の例では,POSTのキーの要素名をクエリーに利用していた。入力値だけでなくキーの要素名も検証の必要がある。また,POSTの値をそのままWebブラウザに返している部分もあった。この場合は,JavaScriptのコードを埋め込むことで実行できてしまう。セッションIDをブラウザで表示している部分は,古いPHPだと危険だという。中には,POSTの値をクエリーに利用し,しかもその結果をブラウザに表示している部分もあった。

 またPHPのコードを埋め込むために「<?」(ショートタグという)を利用していたのも問題だという。ショートタグはデフォルトでは有効だが,オンオフを切り替えられる。オフに設定していたサーバーでは,ソースコードが見えてしまうことになる。ショートタグではなく「<?PHP」というタグを使うのが鉄則だ。

 大垣氏によると,このアプリケーションは「潔くSQLインジェクション対策は一つもしていなかった」という。「管理者が使うもので,一般に公開するべきものではないのでSQLインジェクションできてもいい」と考えたか,「全く気にしていない」かどちらかではないか,というのが同氏の見解である。

 次に取り上げたのは,あるコンテンツ・マネジメント・システム。まず,index.phpでアプリケーションのホーム・ディレクトリを設定する部分に,環境変数によって設定されるCGI変数である「HTTP_HOST」を利用しているのが問題だという。HTTP_HOSTは(Webサーバーにもよるが)好き勝手な文字列を設定できてしまうためだ。「PHP_SELF」というサーバー変数を使っているのも問題。PHP_SELFにはPATH_INFOも含まれ,この部分に任意の文字列を入れることができる。JavaScriptのコードを入れることもできる。

 タグを削除するstrip_tagsという関数の使い方も間違っていた。strip_tagsはタグは削除するがタグの中の属性は削除しない。このため,属性の部分にJavaScriptを埋め込むと実行できてしまう。「この例だとクロスサイト・スクリプティングがやり放題」(大垣氏)。

 $_REQUESTという配列を使っているのもよくないという。$_REQUESTはできれば使わないほうがいいもの。Cookieを利用したDoS攻撃が可能になる場合があったり,CSRF(クロス・サイト・リクエスト・フォージェリ)攻撃が簡単になったりするからだ。

 また,ログイン機能の部分でPostgreSQLにアクセスする際に,str_replaceという関数で「’」と「¥」をエスケープしていた。「これはダメダメ」(大垣氏)。マルチバイト環境(特にシフトJIS)でこうした単純なエスケープをしてしまうと,SQLインジェクションが可能になるケースがあるからだ。データベースごとに専用のエスケープ関数が用意されているので,それを使うべきケースである。

 ほかには,Cookieの有効期限を365日に設定しているという問題もあった。「Cookieの有効期限は長くするほど危険性が増す。こんなに長いのは論外。数時間おきに新しいセッションIDを作るべき」と同氏は語る。Cookieにハッシュ値を入れるというセキュリティ的に意味がない部分もあったという。

 アドレス帳アプリケーションも取り上げた。やはりSQLインジェクションのぜい弱性が見られた。また,「.inc」という拡張子を使っているファイルがあるのも問題だという。サーバーの設定によってはPHPとして実行されない可能性があるからだ。「拡張子は『.php』に統一すべき」(大垣氏)。ほかに,addslashes関数によるエスケープを行っているという問題もあった。これはstr_replaceによるエスケープと同様の問題があるという。

 大垣氏はほかにも多くの例を用意していたが,結局,時間切れで全ては紹介しきれなかった。裏を返せば,ぜい弱なアプリケーションはそれだけ多いということだ。同氏は最後に「ぜい弱性が発生する原因とリスクを正しく理解することが一番大事」と語った。「こんな書き方がダメだ」という今回のプレゼンテーションだけを見て理解したつもりになってはだめだという。「原因と何が起こるかを理解していれば,安全なコードが書ける」というのが結論である。