目的
SQLインジェクションについて理解を深める。
目次
SQLインジェクションとは
SQLインジェクション
とは、「Webページのテキスト入力欄」や「URL」などにSQL文の断片を埋め込むことで、データベースを改ざんしたり不正に情報を入手する手法のことです。
SQLインジェクションの対策
SQLインジェクション
の対策としては以下の2つが挙げられます。
- 特殊文字の変換
- より厳格なSQL文の生成
特殊文字の変換
基本的な対策としてあげられるものが、SQLにおいて意味を持つ特殊文字のエスケープです。
SQL文中では「'」
が文字列の終端を意味していることがポイントです。
たとえば、データベース内に格納された「user_id」と「password」が一致すると、ログインなどの認証を認めるアプリがあった場合、認証に用いられるSQL文は以下になります。
SELECT * FROM users WHERE user_id='$uid' AND password='$pwd'
ここに以下のように入力します。
$uid tarou
$pwd ' OR 'A'='A
すると前述のSQL文は以下のようになります。
SELECT * FROM users WHERE user_id='tarou' AND password='' OR 'A'='A'
もし、特殊文字である「'」をエスケープしていなかった場合、WHERE句の中では「user_id='tarou'」に加え、「password=''と'A'='A'」の2つの条件をORで判定することになります。
この「password=''」と「'A'='A'」は「OR」でつながっているため、どちらかがtrueの場合は認証が認められてしまいます。「'A'='A'」は確実にtrueのため、「user_id」と「password」が一致していなくても、user_idだけ正しければ認証が通ってしまいます。
しかし、特殊文字をきちんとエスケープした場合はユーザーからの入力の「'」
は単なる文字列として扱われるため、「password」に対する入力が「' OR 'A'='A'」という一連の文字列となります。このようなパスワードを設定していない限り、「password」不一致となるため認証は認められません。
実際にエスケープを行う場合は、フォームから「'」
を含む文字列が送信された場合に、別の記号で置き換えるような実装をすることで実現できます。
より厳格なSQL文の生成
ユーザーからの値をSQLへ反映する前に、SQL文の構造を確定する仕組みをとることで、より厳格に対策できます。SQL文確定後にユーザーからの値を入れて実行するため、ユーザーの入力値によってSQL文が変更されることはありません。
先ほどの例を用いると、データベースに対する処理を行う前に、以下のSQLを用意しておきます。
SELECT * FROM users WHERE user_id=? AND password=?
ここで、「user_id」と「password」の値として「?」
が使われており、これをプレースホルダーといいます。
プレースホルダー
プレースホルダーはユーザーの値が入力されるまでの一時的な仮引数のようなものです。あらかじめ確定したSQLにおいて、可変の値が入力される箇所に配置します。
このようにプレースホルダーを用いて設定すれば、「usersテーブルにおいてuser_idとpasswordの組み合わせが一致するかどうかを判定できる」という構文を事前に確定することができます。この後ユーザーからどのような値が入力されようとも、上記の構文の中でSQLが実行されることになり、SQLインジェクションを防ぐことが可能です。
すなわち、「password」として「' OR 'A'='A'」と入力をしても、これらは単純な文字列として認識されます。