脆弱性"&'\ Advent Calendar 2014 (16日目)

この記事は脆弱性"&'<<>\ Advent Calendar 2014の16日目の記事です。

Enjoy!

で終わらせようかと思ったんだけど、毎日Enjoyし過ぎじゃないのみたいに思われそうなのでここ数日のを少し解説。

//d.hatena.ne.jp/hasegawayosuke/20141212/p1">脆弱性"&'<<>\ Advent Calendar 2014 (12日目) :URLが示すとおりAppleのサイトで任意コンテンツを表示可能な脆弱性。見つけたときにはもともとAppleサイトの問題なのかなと思ったけれど、Oracleのサイトにも同じような問題があって、Oracleへ連絡したらJavadoc脆弱性ということでJavaの脆弱性修正にて対応された。
//d.hatena.ne.jp/hasegawayosuke/20141213/p1">脆弱性"&'<<>\ Advent Calendar 2014 (13日目) :特許庁。見たまま。フレーム内に任意コンテンツを挿入可能。
//d.hatena.ne.jp/hasegawayosuke/20141214/p1">脆弱性"&'<<>\ Advent Calendar 2014 (14日目) :オライリーのフィードバックコメントを書くページ。12日目、13日目はiframeやframeとして任意コンテンツが差し込めるだけだったけどオライリーのサイトはURLを見るとわかるように普通にXSS
//d.hatena.ne.jp/hasegawayosuke/20141215/p1">脆弱性"&'<<>\ Advent Calendar 2014 (15日目) :マイクロソフト。alert内を見るとわかるようにDOM based XSSなので2013年当時のChromeXSS Auditorでは止まらない(今だとたぶん止まる)。
//d.hatena.ne.jp/hasegawayosuke/20141216/p1">脆弱性"&'<<>\ Advent Calendar 2014 (16日目) :今日。マイクロソフト。DOM based XSSでIE10のXSSフィルターを通過。

他にもいろいろあるけど出すと怒られたり金融系のように不安をあおりそうなところも多いのでこれくらいで。明日はまじめなネタを書くかも。

Enjoy!

AVTOKYO 2014で「CSPが切り開くWebセキュリティの未来」という題で話してきた

AVTOKYO2014で、にしむねあさんといっしょに「はせむねあ」というユニット名でContent-Security-Policyをテーマに話をしてきました。

内容はスライドのとおりで、攻撃者はFiddlerなどを使って任意のCSP違反レポートJSONを送信可能であること、Firefoxの場合にはCSP違反レポートのJSON内に「<」「>」などが含まれるので、違反レポートを表示する管理画面でのエスケープ漏れがあると違反レポートを通じて管理画面内でXSSする、などの話を行い、実際に管理画面でのXSSのデモを行いました。

デモはあんまり細かいことは考えてなかったんですが、アドリブ苦手なにしむねあさんがいい味を出してて、横で見ていても楽しかったです。ちなみに直前の打ち合わせは以下のような感じでした。

  • にしむねあ「私、デモ直前にステージ上で衣装を替えようと思うんですが、はせがわさんどうします?」
  • はせがわ「攻撃者の格好してからステージに出ようと思ってたけど、じゃあ同じくステージ上でデモ前に準備しましょうか。」
  • にしむねあ「じゃあ前半のスライドを話すのどうします?間に合いませんよね?」
  • はせがわ「にしむねあさんに話すのも含めてやらせているという構図そのものもネタにしたいので、自己紹介以降全部にしむねあさんにお願いしちゃってもいいですか?」
  • にしむねあ「え?あ、はい…。」

ここからにしむねあさん超真面目な顔で台本を復習し始め本番へ。おかげでにしむねあさんは発表まで落ち着いて飲めなかったようですみませんでした!

ちなみに、あまりに細かすぎて伝わってなかった部分の補足:

  • 攻撃検知システムは Web Notifications API を使っていて、ブラウザが非アクティブでもXSSを検知した瞬間に右下に通知ウィンドウが出てきて教えてくれる便利仕様。
  • XSSの攻撃パターンはIMEに辞書登録。いちおう効果が弱そうな順に「メラ」「ギラ」ベギラマ」「イオナズン」の読みを充ててました。
  • 時代はWebRTC。本当はXSSで攻撃者・管理者双方のカメラをONにして対談させたかったのですが、攻撃者・管理者あわせて1台のマシン上でデモを行っているので2台のカメラを動作させにくいのでああいうかたちになりました。

おまけ: https://www.flickr.com/photos/koyhoge/15608237270/

JavaScriptでリンク先URLがhttp/httpsか確認する方法

JavaScriptで動的にリンクを生成する際に、DOM-based XSSを防ぐためにリンク先がhttpあるいはhttpsに限定されていることを確認したい場合がある。典型的には以下のようなコードとなる。

    var div, elm; 
    // 変数 url は攻撃者がコントロール可能な文字列
    if( url.match( /^https?:\/\// ) ){
        div = document.getElementById( "info" );
        elm = document.createElement( "a" );
        elm.setAttribute( "href", url );
        elm.appendChild( document.createTextNode( url ) );
        div.appendChild( elm );
    }

この場合、変数urlに「http://example.jp」や「https://example.jp」などが与えられたときにはA要素が生成されリンク先としてそれらのURLが設定され、「javascript:alert(1)」「vbscript:MsgBox 1」などの場合にはリンクは生成されず、DOM-based XSSを防ぐことができる。
ただし、このコードではurlには「http://」あるいは「https://」で始まる文字列であることが強制されるために、「/foo」のような文字列を与えて <a href="/foo"> のような相対URLのリンクを設定することができない。
このような場合に、与えられた文字列をパースして先頭部分にプロトコルらしきプレフィックスが含まれていなければ…のような処理を自分で書くことはあまりいい方法ではないのでどうしたものかと思案していたところ、malaさんから「elm.href = "javascript:"; elm.protocol でとれない?」と教えてもらった。A要素にprotocolプロパティがあるのも知らなかったので試してみたところ、以下のようなコードでメジャーなブラウザではうまくいくことがわかった。いくつかのブラウザではURLがhttpの相対リンクであってもelm.protocolが「:」や空文字になったりすることもあり、またURLが不正な場合にもelm.protocolが「:」や空文字になったりすることがある。ただし、不正なURLではクリックしてもDOM-based XSSは発生しないので特に問題はないと思われる。

    var div, elm; 
    // 変数 url は攻撃者がコントロール可能な文字列
    div = document.getElementById( "info" );
    elm = document.createElement( "a" );
    elm.setAttribute( "href", url );
    if( elm.protocol.match( /^https?:$/ ) || elm.protocol === ":" || elm.protocol === "" ){
        elm.appendChild( document.createTextNode( url ) );
        div.appendChild( elm );
    }

なお、A要素にはprotocolだけでなくhostやhostnameなどのプロパティもあるので、ChromeFirefoxで new URL( url, location.href ); みたいに書いてたコードとほぼ同じことがIEでもできる。

相対パス解決したいときは大体これつかってますね、ブラウザの実装に頼る
DOMを信じろ! (by mala)

各ブラウザでの様々なURLを設定した場合のA要素のprotocolの値については http://utf-8.jp/test/a-elm-protocol.html にまとめておく。

2014-11-10追記: 関連: IE で a 要素を使って相対 URL からスキームを得る: Days on the Moon