登録フォームなどからSQL文が生成されるような文字が入力され、データベース内の情報を不正に抜き取られたり、改ざんされたりするような攻撃方法を、SQLインジェクションと呼びます。
例えば以下のようなnameテーブルがあり、SELECTによるSQL文を考えます。
1 |
SELECT * FROM name WHERE name='ウェブの葉'; |
入力フォームから「ウェブの葉」という値をそのままSQL文に代入すると、単にそのレコードが1件選択されるだけですが、以下のような文字列が入力されると「a=a」は必ず真なので、全てのレコードが返ってきてしまいます。
1 |
' OR 'a'='a |
を入力すると…
1 |
SELECT * FROM name WHERE name='' or 'a'='a'; |
このように、入力された値をそのままSQL文の中で連結させた場合にSQLインジェクションが実行されてしまいます。上記の例ではレコードが表示されるだけですが、下記のような場合は(テープル名が推測された場合ですが)、データそのものが消去されてしまいます。
1 |
' OR 1 = 1; DELETE FROM name; -- |
を入力すると…
1 |
SELECT * FROM name WHERE name=' ' OR 1 = 1; DELETE FROM name; -- '; |
「−– 」(−–の後に半角)以降の文字はコメントとして認識されます。
例えば下記のようなSQL文があったとします。
1 |
SELECT * FROM name WHERE name='〇〇' AND id ='〇〇'; |
通常はnameとidにそれぞれ値を入力しないといけませんが、nameの部分にだけ下記のような文字列を入力してみます。
1 |
' OR 1 = 1;-- |
すると−– 以降の文字が単なるコメントとして処理され、AND以降は SELECTととは切り離されてしまいます。
1 |
SELECT * FROM name WHERE name=' ' OR 1 = 1;-- ' AND id ='〇〇'; |
プリペアードステートメント
SQLインジェクション対処法は、「′」のような特殊文字をエスケープしてくれるプリペアードステートメントを利用するのが一般的です。
下記のコードはプリペアードステートメントの例です。値はエスケープされてから、SQL文の中に用意したプレースホルダ(?)に入力されるような構造を持ちます。
1 2 3 4 5 6 7 8 9 |
//プリペアードステートメントを組み立てる $stmt = $mysqli->prepare("INSERT INTO name (name) VALUES (?)"); //プレースホルダへ実際の値を設定する $stmt->bind_param('s', $yourname); $yourname = $_POST['yourname']; //実行する $stmt->execute(); |
関連ページ
MySQLにつないでデータを追加する[INSERT][mysqli]