SQLインジェクションの危険性とその対策について
SQLインジェクションとは
Webアプリケーションでは様々な情報をデータベースに保存して管理します。このデータベースを操作するための言語としてSQLが使用されます。
SQLインジェクションは悪意あるユーザがサイトに不正な内容を入力し、データベース上で意図しないSQL文が実行されてしまうことです。
このままではイマイチわかりにくいので次に具体例を紹介します。
SQLインジェクションの具体例
userテーブルの中から名前が'tarou'というレコード取得するとき以下のSQL文を作成します。
SELCT * FROM user WHERE name = 'tarou';
'tarou'の部分はユーザからの入力値とします。
名前の入力欄に『tarou』と入力されたためこのようなSQL文が作成されたわけです。
では悪意あるユーザが名前の入力欄に『' OR 'A'='A'--』と入力したらどうなるでしょうか?
SELCT * FROM user WHERE name = '' OR 'A'='A'--';
当然このようなSQL文が作られます。
WHERE以降の条件をOR演算子で無理やり条件をTRUE(真)にすることで、なんとuserテーブルの全てのレコードを取得できてしまいます!
これはまずいですね。
ちなみに--はコメントアウトで以降の文字はコメントとして扱われます。
最後のシングルクォートが邪魔なのでコメントで消しているというわけです。
SQLインジェクションの対策
ユーザIDとパスワードを受け取ってログイン処理を行うとします。
まずダメな例ですがこのようなSQL文は絶対に書いてはいけません。
// ユーザが入力した値を直接SQL文に組み込んでいる
$sqlStr = "SELECT * FROM user WHERE id = '". $param["id"] ."' AND password = '". $param["password"] ."'";
$stmt = $db->prepare($sqlStr);
$stmt->execute(); // SQLを実行
ユーザが入力した値を文字列連結して直接SQLを組み立てていますが、これだとSQLインジェクションの標的になります。
悪い人がパスワードに『' OR 'A'='A'--
』を入力すればログインされてしまいます。
ユーザが入力した値で直接SQLを組み立てることは絶対にしてはなりません。
ではどうしたら良いのかといいますとプレースホルダを使用します。
プレースホルダを使用したSQL文は以下のようなコードです。
// プレースホルダを利用
$sqlStr = "SELECT * FROM user WHERE id = ? AND password = ?";
ユーザの入力値が入る予定の場所に?
が入っていることが確認できます。
この?
がプレースホルダです。
プレースホルダによるSQL文の組み立てはパラメータ部分をこの?
のような記号で示しておき、後からデータベース上で実際の値を機械的な処理で割り当てます。
プレースホルダを使用してSQLを実行するには以下のコードのようにします。
// プレースホルダを利用
$sqlStr = "SELECT * FROM user WHERE id = ? AND password = ?";
$stmt = $db->prepare($sqlStr);
$stmt->execute(array($param["id"], $param["password"])); // 値の配列を渡してSQLを実行
この割り当てる処理を「バインドする」と呼び、プレースホルダのことを「プレースホルダ変数」と呼ぶことがあります。
ちなみにプレースホルダには静的プレースホルダと動的プレースホルダがあります。
それぞれ以下の違いがあります。
-
静的プレースホルダ(プリペアドステートメント)
一般的には静的プレースホルダがよく使われ、プリペアドステートメントと呼ばれます。 プレースホルダのままのSQL文をデータベース側にあらかじめ送信して、実行前にSQL文の構造解析などの準備をしておく方式です。
SQL実行の段階で実際のパラメータの値をデータベースに送信し、データベース側がバインド処理します。
先にSQL文を確定させることで入力データによってSQL文が変更されません。 -
動的プレースホルダ
動的プレースホルダは静的プレースホルダと違い値のバインド処理をウェブアプリケーションのライブラリ内で実装する方式です。
この記事で紹介しているのは静的プレースホルダです。
動的プレースホルダはライブラリの実装に問題があるとSQLインジェクションを許してしまう可能性があるため、データベースが静的プレースホルダをサポートしているのであれば静的プレースホルダを使いましょう!
静的プレースホルダはSQLを準備する段階でSQL文の構文が確定し、後から構文が変化することがないので安全です。
【おまけ】SQLインジェクションの脆弱性を持っているかの判定方法(悪用厳禁)
判定方法としてサイトのSQLに組み込まれるであろう入力欄にシングルクォーテーション『'
』を入力して送信します。もし脆弱性があるとデータベースエラーが起こります。
例えば名前の欄に『'
』を入力するとこのようなSQL文ができると予想されます。
SELECT * FROM user WHERE id = ''';
SQL文は文字列をシングルクォーテーションで囲むので、もしプリペアドステートメントを使用していない脆弱性のあるサイトだと入力した『'
』がSQL文として認識されます。
つまりSQL文として『'
』が1つ余分になりSQLの構文が誤りになりデータベースエラーが発生します。
しかし脆弱性がないと文字列として認識されるため『'
』という文字を入力しただけとして扱われデータベースエラーは起こりません。
なお、当然ですが間違っても悪用はしないでください。
Author And Source
この問題について(SQLインジェクションの危険性とその対策について), 我々は、より多くの情報をここで見つけました https://qiita.com/iizuka-youhei/items/a394a7f4f829c8791367著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .