SQLインジェクション

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; –“でテストするのが良さそう