LoginSignup
5
5

More than 5 years have passed since last update.

PHP版SQL::MakerでJSON SQL Injectionの対応版を出しました

Posted at

不正な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モードをオンにすると、
値としてハッシュや配列を渡せなくなります。

sample.php
$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_というプレフィックスの関数がインポートされます。

sample.php
$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 と同じ問題が起こります。

sample4.php
<?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 ?)

ということなので、
なにかしらのクエリビルダを使っている場合は、
さらに注意が必要となります。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5