SQLインジェクション その7
関連記事:
SQLインジェクション その1
SQLインジェクション その2
SQLインジェクション その3
SQLインジェクション その4
SQLインジェクション その5
SQLインジェクション その6
脆弱性への対策
文字列リテラルの問題SQLインジェクション脆弱性を快勝するにはSQLを組み立てる際にSQLの変更を防ぐことである。その具体策には以下の2つがある。
- プレースホルダによりSQL文を組み立てる。
- アプリケーション側でSQL文を組み立てる際に、リテラルを正しく構成するなどSQL文が変更されないようにする。
bは完全な対応は難しく、aのプレースホルダを使用することを強く推奨する。
PHPからDBを利用する場合、PEARのMDB2を推奨する。
プレースホルダを利用すると先の蔵書検索のSQLは以下のようになる。
SELECT * FROM books WHERE author = ? ORDER BY id
SQL文中の"?"がプレースホルダ(place holder)で、変数屋敷など可変パラメータの場所に埋め込んでおくものである。"place holder" とは「場所取り」という意味。
MDB2を利用してコードは以下のようになる(DBはPostgreSQL)。
<?php require_once 'MDB2.php'; header('Content-Type: text/html; charset=UTF-8); $author = $_GET['author']; // 接続時に文字コード(UTF-8)を指定 $mdb2 = MDB2::connect('pgsql://<ユーザ名>:<パスワード>@<ホスト名>/<データベース名>?charset=utf8'); $sql = 'SELECT * FROM books WHERE author = ? ORDER BY id'; // SQL呼び出し準備。第2引数の配列でプレースホルダの方を指定する。 $stmt = $mdb2->prepare($sql, array('text')); // SQL文実行 $rs = $stmt->execute(array($author)); // 表示処理は省略 $mdb2->disconnect(); // 切断 ?>
プレースホルダ
プレースホルダには2種類の方式がある。
静的プレースホルダ
プレースホルダを含むSQLがそのままDBエンジンに送られ、DBエンジン側でコンパイルされる。次にバインド値がDBエンジンに送られてDBエンジン側で値を当てはめられた後にSQL文を実行される。
バインド値を入れる前にコンパイルされるのでSQLインジェクション脆弱性は原理的に発生ない。
アプリケーションのライブラリ側で値をバインドしてからDBエンジンに送られる。リテラルは適切に処理されるので処理系にバグがなければSQLインジェクション脆弱性は発生しない。
原理的にSQLインジェクションの可能性がない静的プレースホルダ方式の方が安全である。
動的プレースホルダの実装の問題でSQLインジェクション脆弱性が発生した例がある。
LIKE述語とワイルドカード
LIKE述語を使って "_" や "%" を検査する場合はこれらの文字をエスケープする必要がある。
このエスケープを怠ることとSQLインジェクションは別物だが混同している人が多い。
"_" や "%" を自体を検索したい場合はESCAPE句を指定してWHERE句はいかのようになる。
WHERE name LIKE '%#%%' ESCAPE '#'
DBエンジンによってエスケープが必要な文字は異なる。OracleやDB2では全角文字の "%" と "_" もエスケープの必要がある。
参考文献:体系的に学ぶWebアプリケーションの作り方 4.4.1 SQLインジェクション
![]() | 体系的に学ぶ 安全なWebアプリケーションの作り方 脆弱性が生まれる原理と対策の実践 徳丸 浩 ソフトバンククリエイティブ 2011-03-03 売り上げランキング : 4070 Amazonで詳しく見る by G-Tools |
« SQLインジェクション その6 | Main | 二度と上州屋には行かない »
「MySQL」カテゴリの記事
- MySQLメモ020:INSERT後にAUTO_INCREMENTなカラムの値を取得する方法(PDO編)(2015.02.14)
- MySQLメモ019:TIMESTAMP型の列には勝手にNOT NULL制約とDEFAULT制約が付く(2015.02.12)
- MySQLメモ018:MySQL WorkbenchでTRUNCATEできるようにする(2015.02.11)
- MySQLメモ017:CREATE文、AUTO_INCREMENT、ENGINE(2015.02.08)
- SQLインジェクション その7(2013.10.14)
「PostgreSQL」カテゴリの記事
- CakePHPのインストール(2015.06.14)
- PHPからPDOでPostgreSQLに接続する(2015.06.09)
- PostgreSQLのインストール その2(2015.03.29)
- PostgreSQLのインストール その1(2015.03.23)
- 列の値を使って日時に「+n日」する(2015.02.04)
「SQL」カテゴリの記事
- 列の値を使って日時に「+n日」する(2015.02.04)
- TIMESTAMP WITH TIME ZONE型(2014.07.20)
- PL/pgSQL(2014.02.16)
- PostgreSQLで自作の関数を定義する(2014.02.15)
- PostgreSQLのPREPARE(2014.02.15)
「セキュリティ」カテゴリの記事
- PHPメモ041:パスワードのSalt付きハッシュ値(2014.08.09)
- ファイルインクルード脆弱性(2014.05.18)
- ファイルダウンロードによるXSS その3(2014.03.27)
- ファイルダウンロードによるXSS その2(2014.03.23)
- ファイルダウンロードによるXSS その1(2014.02.24)
The comments to this entry are closed.
Comments