院生エンジニアのにっき

  • Change style to Blue
  • Change style to Red
  • Change style to Green
  • Change style to Pink

正規表現ミスによるSQLインジェクション   2008-01-05

現在なぜPHPアプリにセキュリティホールが多いのか?:第5回 まだまだ残っているSQLインジェクション|gihyo.jp … 技術評論社を読んでいるのですが、正規表現の間違いによるSQLインジェクションのいい例がありましたので紹介を。

私はわからなかったのですが、ユーザからのパラメータに対する数値チェックで以下の二つのPHPコードにおける脆弱性についてでした。

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

回答はこちらにあります。

一見するとうっかり書いてしまいそうなコードですね。普段は簡単なので

  1. if (is_numeric($_GET['id'])) {
  2.         $id = $_GET['id'];
  3. }
  4. $res = pq_query('SELECT * FROM product WHERE ID = '.$id);

としています。is_numericだと小数点を含む数値文字列("1.1"など)もtrueですが、速度的にも問題はないかと思います。まぁこの話はSQLインジェクションの話なので。。

SQLインジェクションやXSS(クロスサイトスクリプティング)、とても良い連載だと思うので、Webアプリを作成する初・中級者は是非読んでおくといい連載だと思います。

ただ、まだユーザからの入力値をなんの処理もせずにそのまま使うエンジニアがいるってのは信じたくない事実ですね。。。

P.S is_numericとpreg_matchの速度比較

is_numericだと

  1. $time_start = microtime(true);
  2. ///////////////////////////
  3. for($i = 0;$i<1000000;$i++){
  4.         is_numeric("1000");
  5. }
  6. ///////////////////////////
  7. $time_end = microtime(true);
  8. $time = $time_end - $time_start;
  9. echo "{$time}秒かかりました。";

preg_matchだと

  1. $time_start = microtime(true);
  2. ///////////////////////////
  3. for($i = 0;$i<1000000;$i++){
  4.         preg_match('/^[0-9]+$/D', "1000");
  5. }
  6. ///////////////////////////
  7. $time_end = microtime(true);
  8. $time = $time_end - $time_start;
  9. echo "{$time}秒かかりました。";

で、結果は

  • is_numeric:0.545043945312秒
  • preg_match:1.53285002708秒

とis_numericの方が約3倍早かったです。まぁ当然といえば当然の結果ですが。。


コメントを書く