SQL Injectionはセキュリティ上の不備を意図的に利用し、アプリケーションが想定しないSQL文を実行させることによりデータベースシステムを不正に操作する攻撃方法
$ mysql -u root -p
mysql> show databases;
mysql> use test
CREATE TABLE users (
id int NOT NULL AUTO_INCREMENT,
name varchar(10),
PRIMARY KEY (id)
);
mysql> INSERT INTO users(name) VALUES
(‘フグ田サザエ’),
(‘フグ田マスオ’),
(‘磯野波平’),
(‘磯野フネ’),
(‘磯野カツオ’),
(‘磯野ワカメ’),
(‘フグ田タラオ’),
(‘タマ’)
;
mysql> select * from users;
$dsn = "mysql:dbname=test;host=localhost";
$user = "hoge";
$password = "fuga";
try {
$records = [];
$id = 1;
$pdo = new PDO(
$dsn, $user, $password
);
$prepare = $pdo->prepare('SELECT * FROM users WHERE id = '.$id.';');
$prepare->execute();
$records = $prepare->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
echo $e->getMessage();
}
var_dump($records);
$ php index.php
array(1) {
[0]=>
array(2) {
[“id”]=>
string(1) “1”
[“name”]=>
string(18) “フグ田サザエ”
}
}
ここで、”0 OR TRUE; –“とすると、全件表示される
$records = [];
$id = '0 OR TRUE; --';
$pdo = new PDO(
$dsn, $user, $password
);
$prepare = $pdo->prepare('SELECT * FROM users WHERE id = '.$id.';');
$prepare->execute();
$records = $prepare->fetchAll(PDO::FETCH_ASSOC);
テーブル名がわかった場合は、”0 OR TRUE; DELETE FROM users; –“でテーブルのレコードが全て削除されてしまう
$records = [];
$id = '0 OR TRUE; DELETE FROM users; --';
$pdo = new PDO(
$dsn, $user, $password
);
$prepare = $pdo->prepare('SELECT * FROM users WHERE id = '.$id.';');
$prepare->execute();
$records = $prepare->fetchAll(PDO::FETCH_ASSOC);
mysql> select * from users;
Empty set (0.00 sec)
### 対策
PDOの場合はクエリ実行前にbindValueでバインドする
$prepare = $pdo->prepare('SELECT * FROM users WHERE id = :id;');
$prepare->bindValue(':id', $id, PDO::PARAM_INT);
$prepare->execute();
mysql> select * from users;
+—-+——————–+
| id | name |
+—-+——————–+
| 9 | フグ田サザエ |
| 10 | フグ田マスオ |
| 11 | 磯野波平 |
| 12 | 磯野フネ |
| 13 | 磯野カツオ |
| 14 | 磯野ワカメ |
| 15 | フグ田タラオ |
| 16 | タマ |
+—-+——————–+
8 rows in set (0.00 sec)
“0 OR TRUE; –“でテストするのが良さそう