gihyo.jp » DEVELOPER STAGE » 連載 » なぜPHPアプリにセキュリティホールが多いのか? » 第5回 まだまだ残っているSQLインジェクション

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

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

正しいSQLインジェクション対策

正しいSQLインジェクション対策には2種類の方法があります。

  • すべての変数をエスケープする対策
  • すべてのクエリをプリペアードクエリとして実行する対策

すべての変数をエスケープする対策

この方法はすべてのデータベースに利用できる対策です。文字列,整数などデータ型に関わらず変数すべてを文字列としてエスケープすることにより,SQLインジェクションを100%防ぐことが可能となります。例えば,PostgreSQLのSQL文を生成する場合,以下のようにすべてのパラメータを文字列して処理・生成します。

$sql = "UPDATE user SET name = '".pg_escape_string($_POST['name'])."', age  = '".pg_escape_string($_POST['age'])."' WHERE id = '".pg_escape_string($_SESSION['USERID'])."';";

一部のドキュメントなどでは,addslashes関数を利用するなど,間違ったエスケープ方法を推奨しているケースがあるので注意しなければなりません。addslashes関数や置換関数(strtr, preg_repalce等)を使用した方法ではSQLインジェクションが可能になる場合があります。必ずデータベースインタフェースが提供しているエスケープ関数を利用するようにします(日本語などマルチバイト文字のエンコーディングの仕様が原因で,機械的な置換を行うとSQLインジェクションが可能となります。特にSJISは明示的にエンコーディングを意識してエスケープしないと,データベースサーバ側では意図したSQL文か攻撃用の文字列であるのかまったく区別ができません)。

テーブル名,フィールド名を動的に決定している場合,エスケープは役に立ちません。このようなクエリを生成することはあまりないと思いますが,もし動的にテーブル名,フィールド名などを決定している場合,あらかじめ定義している文字列と一致しているか確認します。ユーザ入力値のテーブル名やフィールド名をチェックなしに直接クエリに使用すると簡単に不正なSQL文を実行可能です。

すべてのクエリをプリペアードクエリとして実行する対策

プリペアードクエリとは,実行するクエリをあらかじめパースし,パラメータを渡すだけでクエリの実行を行えるようにするDBMSの機能です。すべてのDBMSがプリペアードクエリをサポートしていないので,プリペアードクエリをサポートしているDBMSを利用している場合にのみ使用できる対策です。プリペアードクエリに渡されるパラメータはすべて値として処理されます。このため,プリペアードクエリのみでクエリを実行するとSQLインジェクションは不可能になります。

$res = pg_query_params($conn, 'UPDATE user SET name = $1, age = $2 WHERE id = $3', array($_POST['name'], $_POST['age'], $_SESSION['USERID']));

どちらかというとプリペアードクエリを利用したほうが安全性が高く(エスケープする方法ではエスケープ漏れのリスクが高い),後でコード監査を行う場合も容易に監査できます。プリペアードクエリが利用可能な場合はプリペアードクエリを利用するほうがよいでしょう。

しかし,プリペアードクエリだからといって安心できない場合もあります。データベースアクセス抽象化ライブラリを利用する場合,プリペアードクエリのようなインターフェースをサポートしていても,実際はプリペアードクエリでない場合があります(PDO,Zend Frameworkなど)。このようなライブラリを利用している場合,ライブラリの不備や利用方法に誤りがあるとSQLインジェクションに脆弱となる場合があるので注意が必要です。

まとめ

SQLインジェクションはすべての変数をエスケープするか,すべてのクエリをプリペアードクエリとして実行すれば100%防げる脆弱性です。ソースコードからこの2種類の対策が完全に行われているかチェックするのは非常に容易です。XSS等のJavaScript関連の脆弱性に比べ,SQLインジェクション対策は単純かつ明快です。

著者プロフィール

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

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

URLhttp://blog.ohgaki.net/

著書

  • Webアプリセキュリティ対策入門〜あなたのサイトは大丈夫?

    Webアプリセキュリティ対策入門〜あなたのサイトは大丈夫?

  • [改訂版]PHPポケットリファレンス

    [改訂版]PHPポケットリファレンス

コメント

  • preg_match のバリデーション例

    preg_match の不完全なバリデーションの例の答えですが、以下の説明が間違っています。

    「$_GET['id']中の最初の1行目が数字だけで構成されているかチェックしています。2行目以降にどのような文字列が入っていても構いません。」

    私の調べた限りでは、2行目以降もチェックされます。
    D 修飾子を付けない場合、最後の文字が改行でもマッチするというだけです。

    つまり、preg_match('/^[0-9]+$/', $_GET['id']) では、"1\n" は TRUE ですが、"1\n;SELECT * FROM product" は FALSE です。

    preg_match() で調べる文字列に改行が含まれない場合、D 修飾子を付けた方が安全だとは思いますが、この問題では「バリデーションには明らかな間違いがある」とは言えないのではないでしょうか。

    この問題では、register_globals = On の環境で $id が上書きされて SQL インジェクションが発生するという可能性の方が高いように思います。

    Commented : #2  komura (2007/06/10, 11:03)

  • はじめまして。

    はじめまして。
    記事を拝見し、すこし思ったのですが
    > なぜPHPアプリにセキュリティホールが多いのか?
    に関しては、「まずいサンプルが多い」のが一番の原因じゃないでしょうか。
    本記事の場合、非常に要点を抑えておられるとは思うのですが、サンプルコードの

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

    は、せめて $id を初期化しておいてください。(もしくは、if ブロックの中で query発行をするか。)

    Commented : #1  通りすがり (2007/06/10, 07:15)

コメントの記入

パスサポ

多数の情報処理技術者試験対策書籍の発行実績を誇る技術評論社がお届けする,資格試験合格サイト「めざせ! 情報処理試験 パスサポ」が開設されました。

ピックアップ

サクセスストーリーに続く,快適サーバー運用管理のヒント!

データの増大,煩雑な管理,システムダウン,セキュリティなど,迫りくる課題からシステム管理者の負担を軽くするポイントを解説します。

gihyo.jp インフラエンジニア情報局

ネットワークやITにかかわるあらゆる業種で必要とされるインフラエンジニアに向けた技術情報や心構え,その魅力について多角的に紹介。

テストエンジニア ステーション

いま,ITに関わるあらゆる開発業務で注目されつつあるテスト系エンジニアをターゲットにしたコンテンツサイトを展開します。

一行クイックアンケート

gihyo.jpで取り上げてほしいネタは?

※検索はページ右上の検索ボックスをご利用ください。

その他の連載

もっと便利に!jQueryでラクラクサイト制作(実践サンプル付き)

本連載では,実践サンプルとともに,jQueryを上手に活用してサイト制作の品質向上・効率化を実現するための実践テクニックを解説します。

サクセスストーリーに続く,快適サーバー運用管理のヒント!

サーバーを自社で運用管理するのはもう限界…。データの増大,煩雑な管理,システムダウン,セキュリティなど,迫りくる課題からシステム管理者の負担を軽くするポイントを解説します。

続・先取り! Google Chrome Extensions

2010年1月のリリースが予定されているGoogle Chrome 4に搭載されるExtensionsについて,その詳細を先取りで解説します。最新情報から,ユーザースクリプトやテーマの作り方など関連情報もお届けします。

モダンPerlの世界へようこそ

この連載では,Perlの世代間ギャップに悩んでいる方に,いくらかの背景知識と,これだけは知っておいたほうがよいという最低限の慣用句をお届けします。

Hosting Department:ホスティングを活用するための基礎知識

本連載では,ホスティングサービスを活用する上で知っておきたい基礎知識を解説します。

Blogopolisから学ぶ計算幾何

計算幾何学は,図形に関するアルゴリズムを研究するコンピュータサイエンスの一分野です。本連載では,ビジュアルブログ検索エンジン「Blogopolis」で採用されている計算幾何のアプローチを例に取り上げながら,計算幾何の初歩を実践的に学習します。

Windows phoneアプリケーション開発入門

Windows Marcketplace for Mobileがサービス開始され,作成したアプリケーションを個人でも世界をターゲットに公開できる環境が整ってきました。これを機にWindows phoneアプリケーションの開発をしてみませんか?

いま,見ておきたいウェブサイト

この連載では,国内外の最新のウェブサイトを隔週更新で取り上げ,これら最新サイトの特徴や素晴らしい部分を,さまざまな角度から解説していきます。

連載一覧

gihyo.jp

  • DEVELOPER STAGE
  • ADMINISTRATOR STAGE
  • WEB+DESIGN STAGE
  • LIFESTYLE STAGE
  • SCIENCE STAGE
  • NEWS & REPORT

書籍案内

  • 新刊書籍
  • 書籍ジャンル一覧
  • 書籍シリーズ一覧
  • 新刊ピックアップ
  • ロングセラー
  • 電脳会議

定期刊行物一覧

  • Software Design
  • WEB+DB PRESS
  • Web Site Expert
  • 組込みプレス

最近のコメント