うん,あいびーえむいいたかっただけですねん.これでOK?
どれどれと思って筆者がコードを見てみたら、XSS脆弱性につながりそうな箇所がひとつだけ見つかったのだが、サンプル用のソースコードという前提にあってこれが「問題が盛りだくさんです.」って言うほどかあ?と。アイビーエムって言いたかっただけちゃうんかと。
ご指摘ありがとうございます.
核心突いてきていますね.そもそもあいびーえむいいたかっただけですねん.
意外なところからの突っ込みで面白かった.
っで,反論というより,Web屋さんの記事について補足しておきます.
mysql_real_escape_stringに関して
かつ、 $bodyについてはmysql_real_escape_stringを使っている。したがってSQLインジェクションを防ぐことができている。
mysql_real_escape_stringを使えば万事なんでもOK的な表現ですが,んなこたーないです.
大前提にMyISAMの問題点
乱暴に言うとMyISAMなので文字エンコードの概念がないです.
間違えてたらごめんなさい(いきなりか
マニュアルに明記されていませんが,実質バイナリーに近い取り扱いになるかと思います.
いわゆるPHPでもstrcutなど,標準の文字列関数でマルチバイトが期待通り処理できない話と近い世界観があります.
Shift_JISを突っ込む
$ echo $LANG ja_JP.UTF-8 $ echo -n "表" | iconv --to Shift_JIS | php -r '$c = mysql_connect("localhost", "root", ""); echo mysql_rl_escape_string(fread(STDIN, 2));' | iconv --from Shift_JIS 表\
件のコードで「add_post(1,"表");」とした場合,当てはめるとこうなると思います.
function add_post($userid,$body){ $sql = "insert into posts (user_id, body, stamp) values (1, '表\',now())"; $result = mysql_query($sql); }
$bodyの値の閉じクォートが消えます.
純粋にSQLの実行にエラーになるだけだと思いますが,だれか実行結果ください(苦笑
壊れたマルチバイトを食わせる
substr()を使っていることもありますし,使っていなくても食わせることは可能です.
$ echo $LANG ja_JP.UTF-8 $ echo -n "Web屋" | od -tx1 0000000 57 65 62 e5 b1 8b 0000006 $ echo -n "Web屋" | php -r '$c = mysql_connect("localhost", "root", ""); echo mysql_real_escape_string(fread(STDIN, 5));' | od -tx1 0000000 57 65 62 e5 b1 0000005
壊れたWeb屋の出来上がりです.
っで,同様に件のコードで「add_post(1,"\x57\x65\x62\xe5\xb1");」とした場合,当てはめるとこうなると思います.
function add_post($userid,$body){ $sql = "insert into posts (user_id, body, stamp) values (1, '\x57\x65\x62\xe5\xb1',now())"; $result = mysql_query($sql); }
Shift_JISの表のケースと同様に$bodyの値の閉じクォートが消えます.
純粋にSQLの実行にエラーになるだけだと思いますが,だれか実行結果ください(苦笑
ちなみにXSSは$bodyに対してのみ話しがありましたが,usernameの取り扱いも同様です.
htmlspecialchars()について
このようなケースでは、PHPの場合は例えば
echo htmlspecialchars($list['body']);
と書くことで防ぐのが基本である。
あまりいい基本ではありません(よくかかれる系ではありますが).第2引数は付与しておきましょう.
echo htmlspecialchars($list['body'], ENT_QUOTES);
が基本です.第2引数の必要性については読者に任せますが.
第3引数もつけた方がいいかもしれませんが,そこの是非は突っ込んで検証していないのでよしなにしてください.
SQLインジェクションについて
SQLインジェクションは今再度斜め読みした感じだとmysql_query()を使っていることもあり,ちょっと難しいかもしれないすね.
失礼しました.