何故か今更購入。
本書は具体的な実装コード、攻撃コードなどがきちんと書かれており、PHPのセキュリティを学習する上で非常に参考になる良書です。
2005年発行なので一部の新しい攻撃には対応していないこともありますが、基本的な考え方は今でも十分通じるものです。
ただ大きな問題点が一つ。
本書ではSQLインジェクション対策のエスケープが一貫してaddslashes()で行われています。
それも無知によるものではなく、データベース独自の関数について言及した上で、
>MySQL・PostgreSQL・SQLite等、文字列のクオーティングについての方言がきつくないデータベースエンジンを利用するのであれば、addslashes()を使うのがベストだと筆者は考えます。
と明言しています。
結論から言うとやっぱりaddslashes()は駄目です。
そもそもSQLiteのエスケープは'なのでこの時点で明白な間違いですが、それ以外にも実際にセキュリティ上の問題が発生する可能性があります。
ここらへんを参考に(というか剽窃レベル)実証コードを書いてみます。
addslashes.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
//リクエスト代わり
$_REQUEST['id']="\x95' OR 1=1 #";
//addslashesします
$hoge=addslashes($_REQUEST['id']);
//MySQL
$db=mysql_connect('localhost','testuser','testpass');
mysql_select_db('test',$db);
//SJISのときに問題が起こる
mysql_set_charset('SJIS',$db);
//SQL実行
$sql =" SELECT * FROM test ";
$sql.=" WHERE ";
$sql.=" name= '".$hoge."'";
$ret=mysql_query($sql,$db);
$data=mysql_fetch_assoc($ret);
|
まずリクエストに
"\x95' OR 1=1 #"
というよくわからない文字列を与えます。
その文字列をaddslashes()すると、シングルクオーテーションがエスケープされます。
"\x95\' OR 1=1 #"
ところでSJISにおいて\の文字コードは"\x5c"です。
また"\x95\x5c"という文字コードには「表」が割り当てられています。
そこでaddslashes()されたリクエスト文字列は以下のように誤読されてしまいます。
"表' OR 1=1 #"
完成されたSQLは以下のようになります。
SELECT * FROM test WHERE name= '表' OR 1=1 #'
SQLインジェクションにあっさり成功しました。
上記はSJISでしか起こらない問題ではあるのですが、そのような穴になりそうな部分をわざわざ残しておく必要もありません。
DB固有のエスケープ関数を使用すべきです。
更に言うと、mysql_set_charset()を使用せず
"SET NAMES SJIS"
を使用した場合、mysql_real_escape_string()を使用したときでさえもSQLインジェクションが起こることがありますがそれはまた別の問題。
ちなみに一番正しいのはO/Rマッパかプリペアドステートメントを使用することです。
ところで本書の同じ場所に、
>magic_quotes_gpc設定との相性が良い
と書いてあるのですがこれはどういう意味なんだろう?