なぜPHPアプリにセキュリティホールが多いのか?

第5回 まだまだ残っているSQLインジェクション

この記事を読むのに必要な時間:およそ 4 分

不完全なバリデーションの答え

preg_match

 if (preg_match('/^[0-9]+$/', $_GET['id'])) { 
 	$id = $_GET['id'];
 }
 $res = pq_query('SELECT * FROM product WHERE ID = '.$id);

は,$_GET['id']中の最初の1行目が数字だけで構成されているかチェックしています。2行目以降にどのような文字列が入っていても構いません。PostgreSQL/MySQLなどのDBMSもクエリ中の改行を許可しているので,SQLインジェクションが可能になります。正しいチェックは以下の通りです。

 if (preg_match('/^[0-9]+$/D', $_GET['id'])) { 
 	$id = $_GET['id'];
 }
 $res = pq_query('SELECT * FROM product WHERE ID = '.$id);

ereg

 if (ereg('^[0-9]+$', $_GET['id'])) {
 	$id = $_GET['id'];
 }
 $res = pq_query('SELECT * FROM product WHERE ID = '.$id);

ereg関数はバイナリセーフな関数でないので,\0までしか評価対象になりません。ereg関数はユーザ入力のバリデーションには利用してはならない関数です。\0等の特殊文字を別の文字に置換してからチェックすればereg関数を利用できます。しかし,ereg関数はpreg関数やmb_ereg関数に比べ非常に遅く,わざわざ面倒な処理を遅い関数で行う必然性はありません。

おまけ:mb_eregを利用した場合

 if (mb_ereg('^[0-9]+$', $_GET['id'])) {
 	$id = $_GET['id'];
 }
 $res = pq_query('SELECT * FROM product WHERE ID = '.$id);

PHPマニュアルにもオプションの解説などが記載されていないので,このケースは多少わかり辛いです。

mb_regexのデフォルトオプションは⁠pr⁠が設定されています。⁠p⁠オプションはmb_regexが利用しているoniguruma正規表現ライブラリの以下のオプションを有効にします。

ONIG_OPTION_SINGLELINE
‘^⁠⁠\A’,⁠$⁠⁠\z’,⁠\Z⁠⁠\z’
ONIG_OPTION_MULTILINE
‘.⁠が改行にマッチする

\Aは文字列の先頭(行頭でないことに注意)⁠\zは文字列の最後(行の最後でないことに注意)が設定されます。⁠r⁠オプションはRubyスタイルの正規表現文法を利用する場合に設定するオプションです(参考:http://www.geocities.jp/kosako3/oniguruma/doc/RE.ja.txt)⁠

mb_eregを利用した場合はデフォルト状態で期待どおりに処理され,安全にクエリが実行できます。とはいっても,今は安全でも将来PHPのバグ等で安全に実行できない状態にならないとは言い切れません。エスケープ処理またはプリペアードクエリを利用するだけで高いの安全性を確保できるので,どちらかのSQLインジェクション対策を取るべきです。

以前,データベースシステムのライブラリを利用した関数,pg_escape_stringやmysql_real_escape_stringを利用していても,文字エンコーディングを利用したSQLインジェクション攻撃には脆弱であることが発見されました。しかし,PostgreSQLとMySQLのアクセスライブラリは迅速にこれらの脆弱性に対処しました。pg_escape_string関数やmysql_real_escape_string関数を利用していればPHPスクリプトを修正することなく脆弱性に対処することが可能でした。このことからもデータベースライブラリが提供するエスケープ関数を利用することの重要性を理解できると思います。

著者プロフィール

大垣靖男(おおがきやすお)

University of Denver卒。同校にてコンピュータサイエンスとビジネスを学ぶ。株式会社シーエーシーを経て,エレクトロニック・サービス・イニシアチブ有限会社を設立。
オープンソース製品は比較的古くから利用し,Linuxは0.9xのころから利用している。オープンソースシステム開発への参加はエレクトロニック・サービス・イニシアチブ設立後から。PHPプロジェクトでは,PostgreSQLモジュールのメンテナンスを担当している。

URLhttp://blog.ohgaki.net/

著書