[PHP-users 14846]Re: GETのセキュリティ

Osamu Shigematsu m5issige @ mr.hitachi-medical.co.jp
2003年 4月 24日 (木) 09:18:14 JST


重松です。こんにちは。

> GETで渡すか、POSTで渡すかというところは、この件についてはどちらでも
> 関係ないような気もします。送信しようとしているデータが単純にURIとして
> 目に見える格好なのか(容易に偽装できるか)、目に見えない状態なのか
> (偽装するのに一手間入れるか)だけの違いですよね。

結局、送っているデータというのは、他のスレッドでも書いたと思いますが、
tcpdump だとか、Ethereal (やっぱりつづり間違ってた、
フォローありがとうございます) で、パケットをキャプチャされれば、
たとえ、暗号化されていても (無論、暗号化されたままではありますが)
データのやり取りの内容を見ることは、簡単にできます。

> SQLインジェクションへの対策っていうのは、ようはそういうことなんです(多分)。
> 「送信されてきたデータを、そのままSQLへ代入するんじゃなくて、事前にそのデータの
> 妥当性をチェックしましょう」ってことですよね。
> このあたりは重松さんがウェブで丁寧に説明されていらっしゃいますので、
> そちらを参考に・・・。URL・・・どこでしたっけ?。重松さん?。

そんなにはまとまってないですが、

	http://www.ravi.ne.jp/~shige/?DirectSqlCommandInjection

においてあります。

疑問点や、不備、もっと良い資料へのポインタなどを突っ込んでいただければと
思いますが、SQL インジェクションというのは、何も PHP に限った
問題ではないので、もっと偉い人の資料をあたった方が良いかもしれません。

たとえば:
	http://www.ipa.go.jp/security/awareness/vendor/programming/index.html
	http://java-house.jp/~takagi/paper/iw2002-jnsa-takagi-dist.pdf

> >#if文が偉い長くなってしまって面倒におもうのですが、
> >#何かいい手段はないでしょうか。
> 
> 正規表現とか使えばいいのでは?、と思います。
> ereg("^[0-9]{1,}$",$ID)
> とか。少なくともこれでどんなIDを渡されても、SQLインジェクションを招くような
> データであるかどうかはチェックできます(よね?、多分)。(^-^;;。

いやあ、場合によっては、だめかも。

	hoge.php?ID=1%00%27%20OR%20%27A%27%3D%27

	URL エンコードされていないもとのデータは "1\0' OR 'A'='A"

をうけとる、hoge.php が、


	$ID = $_GET['ID'];
	if (ereg('^[0-9]{1,}$', $ID) {
		$sql = "SELECT * FROM users WHERE id = '$ID'";
		if ($db->query($sql)) {
			// 件数の確認 (というか、見つかったかどうか)
			// 最初のデータの表示
		}
	}
	else {
		die("怪しいデータを察知!");
	}

だったりすると。。。
組み立てられる SQL 文は、

	SELECT * FROM users WHERE id = 1\0' OR 'A'='A'

となるかと思います。

# ちなみに、NUL は PHP の設定にもよりますが、自動的に \0 と
# 変換されたとします。

この攻撃が成立する前提条件は:

(1) ID が CHAR など文字として、データベースに格納されている。
-> 数値ではないのだから、まともな設計なら文字だと思います。

(2) ereg がバイナリセーフではなくて、mb_ereg などのエイリアスではない。
-> レンタルサーバでは良くあることでは?

(3) NUL (NULL バイト) 文字、\0 が自動的にエスケープされる
-> そういう処理はよく有効になっていると思います。

ということで、あながちありえないともいえないような。

-- 
Osamu Shigematsu <m5issige @ mr.hitachi-medical.co.jp>




PHP-users メーリングリストの案内