このページは、SQLインジェクションの学習用に作成されたサンドボックスです。

ユーザー名を入力して、SQLインジェクションの脆弱性を体験できます。

ユーザーテーブル

以下のユーザーデータは、SQLインジェクションの学習用に用意されたものです。

サンドボックス内のデータベースにはユーザー名とカード名が入っています。

ユーザー名 カード名
例えば、ユーザー名に「admin' OR '1'='1」を入力すると、脆弱な処理では全てのユーザーが表示される可能性があります。
他にもUNION SELECT文を使って、他のテーブル「cards」のデータを取得することも可能です。
ただし、対策ありの処理では、プレースホルダを使用しているため、SQLインジェクションは防がれます。

                    
脆弱な処理:入力された文字はそのままSQLクエリに使用されます。
対策あり:プレースホルダを使い、SQLインジェクションを防ぐ試みをしています。

試してみましょう




実行結果


            
今回のサンドボックス環境では
SELECT * FROM users WHERE name = '入力されたユーザー名'
というSQLクエリが実行されます。
脆弱な処理では入力された値をそのまま入れてsqlクエリを実行します。
/* 脆弱な処理 */
$query = "SELECT * FROM users WHERE name = '$name'";
$stmt = $db->query($query);
例えば「'OR'1'='1」を入力すると、$nameの部分に値がそのまま入り
SELECT * FROM users WHERE name = '' OR '1'='1'
というクエリが実行され全てのユーザーが表示されます。
あるいはUNIONやコメントアウト機能を使い「' UNION SELECT * FROM cards --」のように
入力することでUNION SELECTを使い好きな処理を実行しつつ
「--」を最後に入れることで以降の入力を無視できてしまいます。

対策ありの処理では、プレースホルダを使用してsqlインジェクションを防ぎます
/* 対策あり */
$stmt = $db->prepare('SELECT * FROM users WHERE name = ?');
$stmt->execute([$name]);
$stmt=$stmt = $db->prepare('SELECT * FROM users WHERE name = ?');の部分で入力する型を作り
$stmt->execute([$name]);で「?」の部分に$name(今回の場合入力したユーザー名)を入れて実行します。
この際、「'OR'1'='1」という入力でSQLインジェクションの攻撃があったとしても、
SELECT * FROM users WHERE name = ' ' OR '1'='1' 'のように「'OR'1'='1」をまとめて文字列として処理して
SQLインジェクションは防がれます。

最後に

今回紹介したSQLインジェクションは対策を施していても、新しい方法で攻撃を行ってくる可能性があります。
そのため、SQLインジェクションに限らずセキュリティを高めるには、
最新技術を使ったり、実装したシステムを放置せず定期的なスキャンを行うことも重要です。