$c->uri_for の汚染

Bugtraq: WordPress XSS vulnerability in RSS Feed Generator を見て。
Catalyst でも $c->uri_for() で生成される文字列は、安全な文字列であると (なんとなく) 思い込んでいたらそうではないのだな。

<a href="[% c.uri_for('/') %]">

みたいにエスケープしないで書くと、host 部分は $ENV{HTTP_HOST} (リクエストヘッダの Host:) から生成されることが多いので XSS が起きる。
これだと汚染された Host: を送ったクライアントにしか効かないような気がするんだけど、出力を Cache していると他のクライアントにも影響を及ぼせると。
まあ、出力はちゃんとエスケープしろ、という話だから目新しくはない。

$ GET -H 'Host:"><body onload=alert()>' http://example.com/
  • Name based virtual host を使っていれば起きない
  • Apache で実行している場合、Host: の値には '/', '\', '..' は許可されない

という制約はある。

実際に確認したところ、Catalyst-5.7014 で

では上記の現象が起きる。
Apache-2.2.2 + mod_perl-2.0.2 で

SetHandler modperl
PerlResponseHandler WebApp

とした場合は

http://%22%3E%3Cbody%20onload=alert(%22xss%22)%3E/

のように host 部分が URI escape された。
XSS は成立しにくそうだが、Cache した場合に不正なホスト名で汚染されちゃうという問題はあるか。