SQLインジェクション

更新日2010-07-29 (木) 14:05:19

SQLインジェクション対処関数

DBにデータを入れる前に次の関数で処理する

SQLitesqlite_escape_string()
PostgreSQLpg_escape_string()
MySQLmysql_real_escape_string()(MySQL に接続した後で使う)

データベースに登録するのが数値の場合は,$x に値を代入した後に settype($x, "int"); や settype($x, "float"); で数値の型を厳密にする

表示時は < > & " をそれぞれ < > & " に変換する関数 htmlspecialchars() で処理する。

参考:http://oku.edu.mie-u.ac.jp/~okumura/php/security.php

セカンドオーダーSQLインジェクション

(e.g.) SQL: insert into id value ('10') <=10が入力されるはずが

10'' union [SQL文] <=このように入力

''はじめの'はエスケープと判断されDBには

10' union [SQL文]

と保存される。

次にアクセスがあったとき

select * from table where id = '10';  =(これが)=> select * from table where id = '10' union [SQL文]';

として実行される

[SQL文] => delete from table where id = '20 とすれば

select * from table where id = '10' union delete from table where id = '20' ;

となる

このように1回目でSQLを仕込んで、2回目に実行させるSQLインジェクションをいう

シングルクオーテーションを使わないSQLインジェクション

数値データを''でくくらないでSQLを発行するときおきる

select * from table where id = 10 ;

このとき「10」のかわりに「10 union [SQL文]」

で実行されてしまう。

マルチバイト文字の問題

SJISでおこりやすい

phpでaddslashes()やphp.iniでmagic_quotes_gpcがonのときは

例えば、\x97' が入力されると'がエスケープされて\'になり

\x97\' =>

「\'」の部分もエンコードしてみると、「\x5C\x27」となり、全体では「\x97\x5C\x27」となる。

結果 「予'」という文字になり、'がエスケープされない

この場合はSJIS以外か、mb_convert_encoding($str, 'SJIS', 'SJIS') 関数で文字列に おかしな文字コードを入れないようにする。

参考
http://www.atmarkit.co.jp/fsecurity/column/ueno/42.html

サブクエリ

サブクエリによって引き起こされるSQLインジェクション

参考
http://www.atmarkit.co.jp/fsecurity/rensai/hoshino09/hoshino02.html

クロスサイトスクリプティング

sjisは一番弱いようだ。

example.php (SJIS)

<html>

<form>
テキスト1: <input type=text name=text1 value="<?php echo htmlspecialchars($_GET{'text1'}) ?>"><br>
テキスト2: <input type=text name=text2 value="<?php echo htmlspecialchars($_GET{'text2'}) ?>"><br>
<input type=submit value="送信">
</form>

</html>

アドレス欄に以下のように入れるとスクリプトが動作する

example.php?text1=%82&text2=%20onmouseover=alert('xss')%20%82

ソース表示

<html>

<form>
テキスト1: <input type=text name=text1 value="・><br>
テキスト2: <input type=text name=text2 value=" onmouseover=alert('xss') ・><br>
<input type=submit value="送信">
</form>

</html>

これは%82(82h)がSJISの1バイト目になり、2バイト目の"(22h)と結合してSJIS文字として解釈された結果「value=" ...... value="」までがtext1のvalue属性になり、その後の文字列がスクリプトとして動作した。

PHP 文字列エスケープ関数(一応)

mysql_real_escape_string() は、MySQL のライブラリ関数 mysql_real_escape_string をコールしています。 これは以下の文字について先頭にバックスラッシュを付加します。 \x00, \n, \r, \, ', " そして \x1a.

mysql_client_encoding() - 文字セット名を返す

pg_escape_string() は、データベースに挿入するための 文字列をエスケープ(参考:pg_escape_bytea())

注意
「’」(シングルクオート)と「\」(バックスラッシュ)のエスケープを実 施している場合でも、文字コードの問題によってSQLインジェクションが発生するケース。

処理系の日本語対応が不十分な場合、シフトJISで2バイト目が「\」(バックスラッシュ)のアスキーコードである「0×5C」になっている文字が入力されると「’」(シングルクオート)が「\(0×5C)」にエスケープされます。
これにより、SQLインジェクションを成立させることが可能となりますので、 対策の際には注意が必要です。
具体的には以下の方法があります。

最新のデータベース接続ライブラリを使用した上で、データベースエンジンにて提供されたエスケープ機能を利用する
バインド機構を利用する
PostgreSQLの場合は、以下の設定を利用する。この場合円記号「\」のエスケープはしないことに注意。

backslash_quote = off
standard_conforming_strings = on~

addslashes() - 文字列をスラッシュでクォートする~ addcslashes() -エスケープしたい文字を指定する
stripslashes() - クォートされた文字列のクォート部分を取り除く(addslashesで取り除かれた文字列の復元)

htmlspecialchars() - HTML特殊文字を置き換え( < => <)

参考
http://www.atmarkit.co.jp/fsecurity/rensai/hoshino10/hoshino01.html


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2010-07-29 (木) 14:05:19 (2760d)