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