不正なJSONデータによるSQL Injectionへの対策について (Json.pm+SQLクエリビルダー)
http://developers.mobage.jp/blog/2014/7/3/jsonsql-injection
本家SQL::Makerで、SQL Injectionになる可能性があることが発表されました。
徳丸さん(@ockeghem)にご報告をいただき、
以前に習作で作ったPHP版SQL_Makerでも同様の可能性があることがわかったため対応しました。
(ノーマル版) https://github.com/memememomo/php-SQL-Maker
(Composer対応版) https://github.com/memememomo/composer-sql-maker
対応方法は本家と同じでstrict
モードを実装しました。
strict
モードをオンにすると、
値としてハッシュや配列を渡せなくなります。
$builder = new SQL_Maker(array('driver' => 'mysql', 'strict' => 1));
$builder->select('user', array('*'), array('name' => array('foo', 'bar')));
// => Exception! Will not generate SELECT * FROM `name` IN (?, ?) any more
strict
モードをオンにして、条件を設定する場合は、
SQL_QueryMaker のオブジェクト経由で行います。
SQL_Makerをnewすると、SQL::QueryMakerのsql_
というプレフィックスの関数がインポートされます。
$builder = new SQL_Maker(array('driver' => 'mysql', 'strict' => 1));
$builder->select('user', array('*'), array('name' => sql_in(array('foo', 'bar'))));
// => SELECT * FROM `user` WHERE `name` IN (?, ?)
関数一覧は以下のページにあります。
https://github.com/memememomo/php-sql-querymaker
ノーマル版は今まで5.2などでも動いていたのですが、
今回の改修でクロージャを使い始めたので、
PHP5.3以上が必須となりました。
今回修正したバージョンを 0.02 としていて、
以前までのバージョンは 0.01 として残しています。
https://github.com/memememomo/php-SQL-Maker/tree/0.01
バリデーションなどで対応済みであれば、
0.01 を使うことも可能です。
ノーマル版とComposer版について
今後の対応として、
- セキュリティやバグについては、両バージョンで更新
- 新機能などについてはComposerバージョンで行う
という方針でいます。
PHPでの問題
JSON SQL Injection、PHPならJSONなしでもできるよ
http://blog.tokumaru.org/2014/07/json-sql-injectionphpjson.html
上記の記事でも解説されているように、
PHPではJSON以外にもInjectionが起こる可能性あります。
PHPには、HTTPパラメータの名前を「hoge[TEST]」のようにすると、
ハッシュのデータに変換する機能があります。
これを利用すると、
以下のように JSON SQL Injection と同じ問題が起こります。
<?php
//「http://domain/sample4.php?id[TEST]=1」というURLでアクセス
// 数値が入る想定だが、
// この場合は array('TEST' => 1) になる。
$id = $_GET['id'];
$builder = new SQL_Maker(array(
'driver' => 'mysql'
));
$table = 'user';
$column = array('id', 'name');
$where = array('id' => $id);
list($sql, $binds) = $builder->select($table, $column, $where);
// => SELECT `id`, `name` FROM `user` WHERE (`id` TEST ?)
ということなので、
なにかしらのクエリビルダを使っている場合は、
さらに注意が必要となります。