Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A talk about XSS thousand knocks(Shibuya.XSS techtalk#10)

Yu Yagihashi
December 13, 2017

A talk about XSS thousand knocks(Shibuya.XSS techtalk#10)

2017/12/13 Shibuya.XSS techtalk#10 #shibuyaxss
『XSS1000本ノックを支える技術』
See Other => https://knock.xss.moe/

Yu Yagihashi

December 13, 2017
Tweet

More Decks by Yu Yagihashi

Other Decks in Programming

Transcript

  1. whoami ➤ 八木橋 優 Yagihashi Yu
 HN: やぎはしゅ
 Twitter: @yagihashoo


    Web: https://xss.moe/
 Job: 脆弱性診断
 その他いろいろ ➤ katagaitai勉強会、
 SECCON/SECCON Beginners、
 その他・・・ 2
  2. 参加者がひたすらXSSする勉強会 ➤ 先に決めたこと
  1. 資料作らない 2. 解説しない 3. 嫌になるほど長時間やる ➤ XSS Challengeを紹介してひたすら解いてもらう?


    ⇒タダ乗り感がやばくてさすがに罪悪感がやばい
 ⇒しかも過去問紹介と大差ないので解説圧力がやばい ➤ XSS問しか出ないCTFをやればいいのでは?
 ⇒参加者にWrite-upを書いてもらえば万事解決
 ⇒どうせなら1000問くらい出したい
 ⇒PhantomJS使ったXSS問とか、作ったことはあるけど
  たくさん作るの面倒くさい
 ⇒XSS問出題プラットフォームをついでに作ることを決意 7
  3. XSS問題の変遷(≒歴史) 1. 『正規表現』時代 2. 『alert関数置き換え』時代 3. 『alert出せたら挙手』時代 4. 『箱庭XSS』時代 5.

    『PhantomJS/Selenium Web Driver』時代 6. 『Headless Chrome/Firefox』時代 10 ➤ 僕が見たことのあるCTF等におけるXSS問題の出題手法を
 紹介しつつ歴史を振り返ってみる
 (※私見かつ前後関係は適当)
  4. 『正規表現』時代 ➤ (Web上でいい例がないか探してみたけどなかったよ…) ➤ 何のひねりもなく、正規表現でXSSペイロードが正解っぽいか を判定する方法 ➤ 想定解が正規表現に落とし込めるほど限られているので
 あれば使えなくもない ➤

    やぎはしゅも昔々作ったことがあるが大量の想定外の解との 終わりなき闘いになるので実際のところ現実的ではない ➤ input.match(/<script>alert\(1\)<\/script>/)
 ⇒img.onerrorでもできるよ!スペースは???などなど 11
  5. 『alert関数置き換え』時代 ➤ XSS Challenges(https://xss-quiz.int21h.jp/)や
 XSS Games(https://xss-game.appspot.com/)など ➤ 元々のalert関数を自作のものに置き換えて正しい文字列を
 引数として渡しているかなどをもとに判定する ➤

    実装が手軽にできるので、競技として行うものでなければ
 これが最適解かもしれない ➤ ただし、CTFなど、競技性のあるXSS Challengeの場合は
 開発者ツールなどで容易に不正が可能なので不向き
 12
  6. 『箱庭XSS』時代 ➤ SECCONの代名詞 ➤ google:箱庭XSS / google:XSS Bonsai ➤ .NET

    FrameworkのWebControlを使ってIE7っぽい動きをする
 exeを配布するという狂った斬新な切り口を提示した問題作 ➤ 僕は好きですよ!次回作待ってます! ➤ 実態としては確かalert関数の置き換えをしていたような
 気がするので、あくまで発展系(要出典)
 ⇒ブラウザの開発者ツールやローカルプロキシなどで
  悪さができないという点で優秀 14
  7. 『Headless Chrome/Firefox』時代 ➤ Google CTFなどで実績あり ➤ 正直XSS問のためだけにSelenium準備するの面倒くさい ➤ PhantomJSのビルド面倒くさすぎ ➤

    現れた救世主、ChromeとFirefoxのHeadlessモード! ➤ 特にChromeではSeleniumを噛ませずに自在に操作できる ➤ FirefoxはMDN見る限りはやっぱりSelenium使ってる ➤ 手軽さ、実際のブラウザが動く点でもはや一強といっても
 過言ではない 16
  8. 構成(ざっくり) ➤ Nginx+PHP(Slim, php-resque)+SQLite+Node(Puppeteer) 19 a4ec56…f84.knock.xss.moe 89bdae…c4d.knock.xss.moe b53cf3…489.knock.xss.moe 問題ページ スコアサーバ

    被害者クライアント 問題毎に VirtualHost 分ける php-resqueで
 ジョブキュー管理 思考停止して
 Slim + SQLite…
  9. 構成(動きのイメージ) ➤ Nginx+PHP(Slim, php-resque)+SQLite+Node(Puppeteer) 23 a4ec56…f84.knock.xss.moe 89bdae…c4d.knock.xss.moe b53cf3…489.knock.xss.moe 問題ページ スコアサーバ

    被害者クライアント ④送られたURLはジョブキューに
 登録され、HeadlessChromeが
 順にアクセスしていく
  10. 構成(動きのイメージ) ➤ Nginx+PHP(Slim, php-resque)+SQLite+Node(Puppeteer) 24 a4ec56…f84.knock.xss.moe 89bdae…c4d.knock.xss.moe b53cf3…489.knock.xss.moe 問題ページ スコアサーバ

    被害者クライアント ⑤XSSが発火し、
 例えばCookieに含まれているFLAGを
 外部に送信するなど被害者ブラウザと
 同じ動きをする
  11. 同一ホスト上でXSS問を提供することの難しさ ➤ 同一ホスト上で大量のXSS問を用意する場合、オリジンまで
 同一のものとしてしまうと簡単な問題のXSSを使って別の
 問題のFLAGを取得することができてしまうケースがある ➤ 素直にSame Origin Policyに頼りたいが問題毎にドメインを
 用意するのは面倒くさい(2,3問ならそれもあり)

    ➤ DNSでワイルドカードあてるにしても1000個の問題を
 サブドメイン毎に効率よく振り分ける方法は考える必要あり 28  取りうる選択肢 1. サブドメインの値に紐づく問題ファイルをincludeする 2. サブドメイン毎にDocRoot分けてVirtualHost切る
  12. 1. サブドメインの値に基いてinclude先変える 29  ⭕メリット 1. *.knock.xss.moeは問題ページを、knock.xss.moeをスコアサーバを、 といった具合に、単一のアプリケーションですべて完結する設計が可能 2. サブドメインの値に応じてinclude先のPHPファイルを変えるだけなので
 Webサーバへの負荷は少なそう

     ❌デメリット 1. そもそも単一のアプリケーションで完結するのって便利なのか?
 (XSS問題の提供プラットフォームとしては逆に不便では) 2. PHP以外の言語で作った問題ページを用意するのが大変
 (今後特定の言語やフレームワーク依存の問題も出すかも?)
  13. Content Security PolicyでXSS対策! ➤ 「外部ファイル読み込まれるのツラい…」
 「eval実行されるのツラい…」
 って、どこかで聞いたことのある話 ➤ Content Security

    Policyを使えば外部リソース読み込みや
 evalの実行を防止することができる!! ➤ 本来はまっとうなセキュリティ施策として使われるべき
 CSPだが、XSS問の別解防止にも大変役に立つので知見として
 どんどん広めていきたい ➤ 実際の例を見るのは1000本ノックを受けてもらえばいいので
 ここでは1つだけ具体例を紹介する
 35
  14. Content Security PolicyでXSS対策!(具体例) 36 <?php header('X-XSS-Protection: 0'); function myescape($s) {

    return substr($s, 0, 65); } ?> <?= myescape($_GET['q']) ?> CSP導入前 <?php header('X-XSS-Protection: 0'); header('Content-Security-Policy: script-src \'self\' \'unsafe-inline\' \'unsafe-eval\''); function myescape($s) { return substr($s, 0, 65); } ?> <?= myescape($_GET['q']) ?> CSP導入後 65文字以内でCookieを
 抜き取る問題だが 「//gj.gy」などで
 外部ファイルを参照すると
 だいぶハードルが下がる CSPで外部オリジンの
 スクリプトの参照を
 禁止することで、
 想定外の解法を潰しこむ