pasasの日記: エスケープとセキュリティホール(その2)
なんだか最近このネタ多いな。
「SQL 文に値を渡すときにはエスケープしましょう」というのは、こちらでもちょこっと触れた通り。
でも、以下のように書いてもよくない。
(例によってサンプルは PHP。)
<?
$sql = "select * from table_name where uid = ".addslashes( $UID);
if( ( $result = pg_exec( $sql)) == false ) {
die("pg_exec()");
exit;
}
?>
ここでテーブル table_name の フィールド uid は int だとして、変数 $UID は URL に埋め込まれる形で送られてくるとする。
そして、通常の処理では UID は整数値しかとらないとする。
確かに $UID は addslashes でエスケープされているんだけど、
addslashes がエスケープするのはシングルクォーテーションや、\ などの記号だけで、その他の文字はエスケープしない。
とすると、ユーザが UID を以下のようにして URL に埋め込むと、
UID=1+%3B+delete+from+table_name+%3B
もう見てわかる通り、実行される SQL 文は次のようになる。
select * from table_name where uid = 1 ; delete from table_name ;
まぁ、これはテーブルの名前がわからないと実行できないんだけど、潜在的に重要な問題になっているということには注意。
「えー、だって一般ユーザはテーブル名までわからないよぉ」なんて言う方は、もう一度セキュリティについて考え直したほうがよいと思う。
というわけで結論。
入力された値を SQL 文に投入するときには、たとえその値が int だったとしても、クォーテーションで囲みましょう。
こんな感じ。
$sql = "select * from table_name where uid = '".addslashes( $UID)."' ";
または $UID が必ず int になるようなロジックを通すかだなぁ。