学習忘備録

学習のアウトプットや感じた事を発信していきます

SQLインジェクション

書籍を読んで

www.amazon.co.jp

こちらの書籍を読んでWebアプリケーションを作る際に重要な要点を自分用としてアウトプットします。

 

SQLインジェクション

SQLによるデータベースアクセスの実装に不備があると、SQLインジェクションという脆弱性が生まれる

対策としては静的プレースホルダを使う事

概要
  • データベース内の全ての情報が盗まれる / 内容が書き換えられる
  • 認証を回避される
  • データベースサーバ上のファイルの読み出し、書き込み、プログラムの実行などを行われる

非常に影響の大きい為、SQLインジェクション脆弱性が絶対に混入しないようなプログラミングが求められる

攻撃手法の種類
  • エラーメッセージを用いる
    • エラーメッセージにID, パスワードなどが表示されてしまう
    • 情報漏洩
  • UNION SELECTを用いる
    • データベースを改ざんされる
      • データの一部が個人情報に置き換わる
    • 情報漏洩
  • 認証を回避される
    • パスワードに入力する値でWHERE句が常に成立する状態にされる
    • パスワードを知らなくてもログイン出来てしまう
  • データ画面の改ざん
  • その他の攻撃
    • OSコマンドの実行
    • ファイルの読み出し / 書き出し
    • HTTPリクエストにより他のサーバを攻撃

SQLインジェクション攻撃による影響はデータベースエンジンによって異なる。

全てのデータベースエンジンで発生する共通の影響は、データベース内のデータの読み出し

脆弱性の生まれる原因

リテラルの扱いによるもの

リテラルとはSQL文中で決まった値を示すもの

'hogehoge' という文字列や、 10,-5 という数値などがリテラルの例

文字列リテラルの問題
  • SQLの標準規格では、文字列リテラルはシングルクォートで囲う
  • 文字列中にシングルクォートを含めたい場合には、シングルクォートを重ねる決まり
    • ○ -> 'O''Really' × -> ’O’Really’
  • シングルクォートで囲われていない所の代わりにSQL文として意味を持つ文字列を挿入されたらどうなるか
数値項目に対するSQLインジェクション
  • 数値を入力する場所に数値を入力しセミコロンで区切り、意味を持つSQL文を入れられるとそれが実行されてしまう
対策
  1. プレースホルダによりSQL文を組み立てる
  2. アプリケーション側でSQL文を組み立てる際に、リテラルを正しく構成するなど、SQL文が変更されないようにする

2は完全な対応が難しいので、1のプレースホルダによるSQL組み立てが望ましい

プレースホルダ
  • SQL文中のクエッションマーク「?」がプレースホルダ
  • 変数や式など可変のパラメータの場所に埋め込んでおくもの
    • 「場所取り」という意味の英語
  • プレースホルダに値を割り当てることを「バインド」と呼ぶ
PDOの安全な利用法

PDO -> どのデータベースを使っているか隠蔽してくれる

同じ関数を使う事が出来る、将来データベースを変えてもパラメータだけ変えれば良い

静的プレースホルダ
  • 値のバインドをデータベースエンジン側で行う
    • SQL文がデータベースエンジンに送られる
    • コンパイルなどの実行準備が行われる
    • SQL文が確定される
    • バインド値がデータベースエンジンに送られる
    • エンジン側で値を当てはめた後にSQL分が実行される
  • 後からSQL分が変更される可能性は原理的にあり得ない
動的プレースホルダ
  • SQLを呼び出すアプリケーション側のライブラリ内で、パラーメをバインドしてからデータベースエンジンに送る方式

プレースホルダには静的、動的と2種類あり、どちらを使ってもSQLインジェクションは解消されるが、原理的にSQLインジェクションの可能性がないという点で静的プレースホルダの方が優れている。可能であれば、静的プレースホルダを利用するべき。

LIKE述語とワイルドカード

SQLインジェクションとは別の問題だが、曖昧検索として使用するLIKE述語の利用出来るようにする場合、ワイルドカード文字の機能を利用出来なくするために、ワイルドカード文字をエスケープする必要がある。

プレースホルダを用いた様々な処理

複雑なSQL文を組み立てたい場合でもプレースホルダを利用してSQL呼び出しが可能

SQLインジェクションの保険的対策

プレースホルダの利用に加えて実施するとよい保険的対策

根本対策に抜けがあったり、ミドルウェア脆弱性があったりする場合に、攻撃の被害を軽減する対策のこと

詳細なエラーメッセージの抑止

SQLのエラーメッセージが表示されると、SQLインジェクションの存在が外部から分かりやすくなる為

入力値の妥当性検証

アプリケーションの要件に従った入力値検証が望ましい

例えば、有番号欄では数値のみ / ユーザIDであれば英数字などの制限

データベースの権限設定

アプリケーションを利用するユーザに対しての適切な権限設定

商品情報を表示するアプリケーションでは読み込み権限だけでよく、書き込み権限を付与する必要はない

--> 商品データ改ざんの防止

さらに進んだ学習のために

IPAの「安全なSQLの読み出し方」を参照

プレースホルダが使えない場合の対策

既存アプリケーションの対策では、プレースホルダによる実装への変更で改修コストが大きくなりすぎてしまう状況が考えられる

そのような場合は、文字列連結によるSQL文組み立ての構造を生かしたまま、リテラルを正しく構成することでSQLインジェクションを解決出来る

  • 文字列リテラル内で特別な意味を持つ記号文字をエスケープする
  • 数値リテラルは数値以外の文字が混入しないようにする