「クロスサイトスクリプティング対策の落とし穴」へのツッコミ

はじめに

この記事を数十人の人がブックマークしていたものの あまりに酷い内容なのでちょっと辛辣なコメントでのブックマークを残してみたのですが、その後もこの記事への(付けられているタグを見る限り肯定的な)ブックマークは止まず。これはちょっとはっきり問題点を指摘した方がいいかな…と思ってこうした記事を書く次第。

ツッコミ開始

典型的な例は,「テキストを出力する前に"<"と">"を取り除く」方法があります。

そんなの「典型的」ではありません。どう考えてもhtmlspecialchars等でエスケープするほうが「典型的」です。変な「典型的」を捏造しないで下さい。

「<」「>」を絶対に使わないような箇所(例えば郵便番号とか)ならば取り除いても良いでしょうが、一般論としては、「<」「>」という文字をプログラマが自分の都合で勝手に取り除く事は許されません。「>」なんて よく掲示板の返信とかに使うじゃないですか。勝手に取り除かれたら困りますよ。

「『間違った例』なのだからいいじゃないか」という反論もあるでしょうが、セキュリティの記事ならば『セキュリティ上 間違った例』を出すべきであり、本旨以外の部分まで間違ってよいというものではありません。


$safe_text = ereg_replace($_GET['text'], '[<>]', '');

ereg_replaceの引数は (パターン, 置換文字列, 元文字列) の順なんですが。これだと$safe_textは常に空文字列になってしまいます。まぁ確かにそれは この上無く「safe text」ですけど。


$safe_textに

" onmouseover="javascript: alert('XSS')

と設定されている場合,"<"と">"を取り除いてもクロスサイトスクリプティングに脆弱となります。そこで"javascript"という文字列を排除して安全性を確保しようと試みることにします。

onmouseoverに「javascript:」は要らないだろうというツッコミはさておき(というか大垣氏自身この少し下で「javascript:」無しのonmouseoverの例を出しているではないですか。もしかして「a要素の時はjavascript:が必要」とか勘違いしてます?)、なんでそこで「javascript」が危険だという発想になるんですか。どう考えても上の例で問題を起こしているのは「"」でしょう。大垣氏は「javascript」という文字列に恨みでもあるんですか?

しかも下の「対策」、しかし,javascript文字列がなくてもブラウザがJavaScriptと認識してしまうケースは多数あります、とか書いていますが、それ以前の脆弱性があります。

$safer_text = eregi_replace($safe_text, 'javascript', '');

そもそもこれも引数の順番を間違えているんですが それは脳内訂正するとして、これでは「jjavascriptavascript:...」と入力すれば「javascript:...」が残ってしまいます。だから いくら「間違った例」でも本旨でない部分まで間違えないで下さい。


<b onmouseorver="alert('XSS')">XSS</b>

onmouseo r ver、笑い。

や、別に誤字自体が悪いわけじゃないんですよ。ただ、上のereg_replaceの引数順序ミスといいこれといい、「コード中」に誤字等があるという事は 実際に動作をテストしていない可能性が高いという事です。正しい記事を書こうとする意思があるならテストはするべきです。テストなどしなくても絶対正しく動くコードを書ける力があるならばいいでしょうが、この間違いだらけの結果を見る限り…

正しい内容を書く力も無くて、正しい内容を書こうとする意思も無い。せめてどちらかくらい持って下さい。


…で、ここまでの内容なんですが、どうも「典型的でない『典型的な誤った対策』」をでっちあげ その「問題点」を指摘して『ぼくのかんがえた たいさく』へと誘導している…という印象を受けます。最初に書いたとおり、テキストを出力する前に"<"と">"を取り除く、なんてのより htmlspecialcharsでエスケープする方が「典型的」だと思うのですが、その場合「問題点」はどんなものですか?それを示してくれなければ『ぼくのかんがえた たいさく』をする必要はまったく無いわけですが。


この後の内容にも色々ツッコミたいところがあった(というかツッコむ文章はほぼ書きあがっていた)んですが、大垣氏のブログにこれに関する記事が載り、そのツッコミの多くが無効化されてしまいました。無念。

まずこの見出しに答えると、意図は伝わっていません(誤字とかは「意図」以前の問題ですが)。というか、これで意図を理解しろという方が無茶です。

なので「サニタイズ」ではなく「バリデーション」と「適切なエスケープ」によって対策すべきです、と書きたかったのですが「エスケープ」の部分を書いてないですね。バリデーションの時に説明するつもりですが、確かに尻切れとんぼのような感じです。

尻切れとんぼのような感じどころではありません。この記事には「バリデーション」の事は少し書かれていますが、「適切なエスケープ」については一切書かれていません。「尻切れとんぼ」は 切れて先が無くなってはいても その先に本来尻があることは判るものですが、この記事では「適切なエスケープ」が必要だという事はまったく匂わせすらしておらず、「バリデーション」だけで事足りるように読めます。(事実、私の書いていたツッコミの一つは「バリデーションだけではセキュリティ対策になんてならない」というものでした。)

あと、「適切なエスケープ」というのは 広義の「サニタイズ」の一種だと思うんですが、違うんですか。

まとめ

  • コードのミスが多すぎます。ちゃんとテストとかして下さい。
  • 本当の「典型的な対策」と、そしてその問題点を示して下さい。それが無ければ いくら「対策」を主張しても無価値です。
  • 記事の長さ制限とかあったのかもしれませんが、大切なことは 一言でもいいからちゃんと書いて下さい。

他にも色々言いたいことはあるんですが、長くなるし 少しこの記事の内容から離れてしまっているので、このへんで。興味あるという人がいれば書きますが。

追記:文章面での問題点

あと、「たぶん違う意味で言っているのだろうけど、こう読めちゃうなぁ。」「これはちょっと文章として間違っているんじゃ?」と思う点。


$safe_textに

" onmouseover="javascript: alert('XSS')

と設定されている場合,"<"と">"を取り除いてもクロスサイトスクリプティングに脆弱となります。

$safe_textに、じゃなくて「$_GET['text']に」、ですよね。重箱の隅ですが。


Webアプリケーションに限らず一般的なアプリケーションは,異常な入力を検出した場合はエラーとすべきです。

ここだけを取り出して見れば別に問題無いんですが、最初の方で挙げている例と合わせて読むと、「『<』とか『>』とか『javascript』があったら エラーとすべき」と誤読する人が出そうな気がします。