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

6aaffafb38a160209c9164da25b3a3f3?s=47 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/

6aaffafb38a160209c9164da25b3a3f3?s=128

Yu Yagihashi

December 13, 2017
Tweet

Transcript

  1. XSS1000本ノックを
 支える技術 4IJCVZB944UFDIUBML 1SFTFOUFECZ!ZBHJIBTIPP

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


    Web: https://xss.moe/
 Job: 脆弱性診断
 その他いろいろ ➤ katagaitai勉強会、
 SECCON/SECCON Beginners、
 その他・・・ 2
  3. knock.xss.moe 3

  4. 今日のメニュー 1. XSS1000本ノック #とは 2. XSS問題の変遷 3. こんな構成 4. 課題1「セパレーション」

    5. 課題2「別解」 6. まとめ 4
  5. XSS1000本ノック
 #とは 5

  6. katagaitai勉強会 ➤ 某社のCTFチームが年に2回くらい開催している勉強会 ➤ 本来はその辺のCTFの過去問を紹介・解説する ➤ 2017年春ごろのやぎはしゅ
 「夏の勉強会、喋ることになったけど、
  資料作るの面倒くさいわ〜…」
 「何なら喋るのも面倒くさいわ〜…」


    「そうだ、資料も作らず、喋るのも
  やめればいいんだ!!」
 ⇒参加者がひたすらXSSするだけの
  最高の勉強会の開催を決意 6 % 6 (
  7. 参加者がひたすらXSSする勉強会 ➤ 先に決めたこと
  1. 資料作らない 2. 解説しない 3. 嫌になるほど長時間やる ➤ XSS Challengeを紹介してひたすら解いてもらう?


    ⇒タダ乗り感がやばくてさすがに罪悪感がやばい
 ⇒しかも過去問紹介と大差ないので解説圧力がやばい ➤ XSS問しか出ないCTFをやればいいのでは?
 ⇒参加者にWrite-upを書いてもらえば万事解決
 ⇒どうせなら1000問くらい出したい
 ⇒PhantomJS使ったXSS問とか、作ったことはあるけど
  たくさん作るの面倒くさい
 ⇒XSS問出題プラットフォームをついでに作ることを決意 7
  8. ★機密情報を抜くところまでがXSSです
 ⇒すべての問題でFLAGを盗むのがゴール ★ステージ制の導入で圧倒的成長
 ⇒現在のステージを解かないと次のステージには進めない ★1000問用意しとけばとりあえず最大手になれるのでは
 ⇒楽に、大量に、XSS問を出題するためのプラットフォーム作り XSS1000本ノック ➤ ただひたすらにXSSをキメるだけのCTF ➤

    決めたこと
  1. alertするだけのヤワなやつは要らない
  2. 嫌になるほどXSSばかりやって逆に好きになってもらう
  3. XSS Challengeの最大手を目指す 8
  9. XSS問題の変遷 9

  10. XSS問題の変遷(≒歴史) 1. 『正規表現』時代 2. 『alert関数置き換え』時代 3. 『alert出せたら挙手』時代 4. 『箱庭XSS』時代 5.

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

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

    実装が手軽にできるので、競技として行うものでなければ
 これが最適解かもしれない ➤ ただし、CTFなど、競技性のあるXSS Challengeの場合は
 開発者ツールなどで容易に不正が可能なので不向き
 12
  13. 『alert出せたら挙手』時代 ➤ 昔セキュリティキャンプのCTFで見た稀有な例 ➤ オフラインで開催しているCTFだからこそできる、
 alertを出せたら運営を呼んで確認してもらい、FLAGを
 教えてもらうという方法 ➤ お世辞にもスマートとはいえない ➤

    趣旨が異なるものの、Cure53のXSS Challengeなど、
 最終的に人の目でペイロードを確認するケースも同様かも
 (賞金あったりするし、これはむしろ妥当) 13
  14. 『箱庭XSS』時代 ➤ SECCONの代名詞 ➤ google:箱庭XSS / google:XSS Bonsai ➤ .NET

    FrameworkのWebControlを使ってIE7っぽい動きをする
 exeを配布するという狂った斬新な切り口を提示した問題作 ➤ 僕は好きですよ!次回作待ってます! ➤ 実態としては確かalert関数の置き換えをしていたような
 気がするので、あくまで発展系(要出典)
 ⇒ブラウザの開発者ツールやローカルプロキシなどで
  悪さができないという点で優秀 14
  15. 『PhantomJS/Selenium WebDriver』時代 ➤ いろいろなCTFで多数の事例あり?
 (ただしPhantomJSは終わった感あるので今後は出なそう) ➤ 実際のブラウザ自体を操作、またはエミュレーションする ➤ alertを実行できたらFLAG…などの単純な設問から脱却し
 管理者ユーザでログイン済のセッションをハイジャックする


    といった発展的、実践的な設問が可能となった ➤ XSS問の多様性の観点ではひとまずここで頭打ち?
 実際のブラウザが動くならもうこれ以上はないよね、
 という感じ 15
  16. 『Headless Chrome/Firefox』時代 ➤ Google CTFなどで実績あり ➤ 正直XSS問のためだけにSelenium準備するの面倒くさい ➤ PhantomJSのビルド面倒くさすぎ ➤

    現れた救世主、ChromeとFirefoxのHeadlessモード! ➤ 特にChromeではSeleniumを噛ませずに自在に操作できる ➤ FirefoxはMDN見る限りはやっぱりSelenium使ってる ➤ 手軽さ、実際のブラウザが動く点でもはや一強といっても
 過言ではない 16
  17. こんな構成 17

  18. 構成(ざっくり) ➤ Nginx+PHP(Slim, php-resque)+SQLite+Node(Puppeteer) 18 a4ec56…f84.knock.xss.moe 89bdae…c4d.knock.xss.moe b53cf3…489.knock.xss.moe 問題ページ スコアサーバ

    被害者クライアント
  19. 構成(ざっくり) ➤ 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…
  20. 構成(動きのイメージ) ➤ Nginx+PHP(Slim, php-resque)+SQLite+Node(Puppeteer) 20 a4ec56…f84.knock.xss.moe 89bdae…c4d.knock.xss.moe b53cf3…489.knock.xss.moe 問題ページ スコアサーバ

    被害者クライアント ①スコアサーバに登録し、
 問題ページ(XSSのあるページ)に
 アクセスする
  21. 構成(動きのイメージ) ➤ Nginx+PHP(Slim, php-resque)+SQLite+Node(Puppeteer) 21 a4ec56…f84.knock.xss.moe 89bdae…c4d.knock.xss.moe b53cf3…489.knock.xss.moe 問題ページ スコアサーバ

    被害者クライアント ②問題ページ上のXSSで
 FLAGを窃取するための ペイロードを組む
  22. 構成(動きのイメージ) ➤ Nginx+PHP(Slim, php-resque)+SQLite+Node(Puppeteer) 22 a4ec56…f84.knock.xss.moe 89bdae…c4d.knock.xss.moe b53cf3…489.knock.xss.moe 問題ページ スコアサーバ

    被害者クライアント ③スコアサーバにXSSが発火する
 URLを送信する
  23. 構成(動きのイメージ) ➤ 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が
 順にアクセスしていく
  24. 構成(動きのイメージ) ➤ 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を
 外部に送信するなど被害者ブラウザと
 同じ動きをする
  25. 構成(動きのイメージ) ➤ Nginx+PHP(Slim, php-resque)+SQLite+Node(Puppeteer) 25 a4ec56…f84.knock.xss.moe 89bdae…c4d.knock.xss.moe b53cf3…489.knock.xss.moe 問題ページ スコアサーバ

    被害者クライアント ⑥得られたFLAGをスコアサーバに
 送信し、次の問題に進む
  26. 構成(ポイント) ➤ 各問題を、可能な限り想定解で解いてもらう(後述) ➤ 設問の柔軟性を損なわないため、各問題ページ全てに
 VirtualHostを切っている
 ≒proxy_passすればPHP以外で動いている問題ページも
  容易に使うことができる
 (PHPだけでよければサブドメインの値でincludeする内容を
  変える方が簡単そう)

    ➤ Headless Chromeを並列でバシバシ実行するのが難しそう
 (※調べ方が悪いだけ説あり)なので、ジョブキューを
 用意してユーザからのリクエストに応じて順次実行する 26
  27. 課題1 「セパレーション」 27

  28. 同一ホスト上でXSS問を提供することの難しさ ➤ 同一ホスト上で大量のXSS問を用意する場合、オリジンまで
 同一のものとしてしまうと簡単な問題のXSSを使って別の
 問題のFLAGを取得することができてしまうケースがある ➤ 素直にSame Origin Policyに頼りたいが問題毎にドメインを
 用意するのは面倒くさい(2,3問ならそれもあり)

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

     ❌デメリット 1. そもそも単一のアプリケーションで完結するのって便利なのか?
 (XSS問題の提供プラットフォームとしては逆に不便では) 2. PHP以外の言語で作った問題ページを用意するのが大変
 (今後特定の言語やフレームワーク依存の問題も出すかも?)
  30. 2. サブドメイン毎にDocRoot分けてVirtualHost切る 30  ⭕メリット 1. proxy_passすれば何でもあり⇒設問の柔軟性を損なわない 2. スコアサーバから問題を切り離すことで、スコアサーバの
 汎用性向上、問題の管理も楽ちん(別リポジトリで管理)  ❌デメリット

    1. 設定ファイル地獄 2. Webサーバへの負荷がちょっとヤバそう
 (VirtualHost多すぎてNginxの起動時に怒られるw)
  31. 2. サブドメイン毎にDocRoot分けてVirtualHost切る 31  ❌デメリット 1. 設定ファイル地獄
 ⇒問題の追加時に設定ファイルも自動で書き換えてしまおう
 ⇒さすがに気持ち悪いので妥協案を採用(あとで見せます) 2. Webサーバへの負荷がちょっとヤバそう


    (VirtualHost多すぎてNginxの起動時に怒られるw)
 ⇒設定ファイルへの追記か何かで解決した(はず)
 ⇒負荷自体は実はそんなでもない?あまりよくわかってなry
  32. 結論 32 倱嶷獌512؋⊠┊猳

  33. 課題2 「別解」 33

  34. 別解は1000本ノックにも襲いかかる ➤ katagaitai勉強会当日は、たくさんの別解が観測できました ➤ 実のところ、あんまり気にしていない
 ⇒別解も解だよね、というお気持ち ➤ せっかくなのでこちらが想定している解法でやってみて
 欲しい!
 ⇒可能な限り想定解以外を削ぎ落とす対策を考える

    34  よく見かける別解 1. 外部ファイル参照(文字数制限がなかったことに…) 2. eval+location.hash(文字種の制限もなかったことに…)
  35. Content Security PolicyでXSS対策! ➤ 「外部ファイル読み込まれるのツラい…」
 「eval実行されるのツラい…」
 って、どこかで聞いたことのある話 ➤ Content Security

    Policyを使えば外部リソース読み込みや
 evalの実行を防止することができる!! ➤ 本来はまっとうなセキュリティ施策として使われるべき
 CSPだが、XSS問の別解防止にも大変役に立つので知見として
 どんどん広めていきたい ➤ 実際の例を見るのは1000本ノックを受けてもらえばいいので
 ここでは1つだけ具体例を紹介する
 35
  36. 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で外部オリジンの
 スクリプトの参照を
 禁止することで、
 想定外の解法を潰しこむ
  37. 結論 37 倱嶷獌%52؋㧡涹猳

  38. デモ 38

  39. まとめ 39

  40. ➤ 資料作らない
 ⇒使い回しの自己紹介スライドとURL掲載用のスライド以外
  使わなかった! ➤ 解説しない
 ⇒前に立たない代わりに個別に回って詰まってる人向けに
  解説・アドバイス
 ⇒結果的に各参加者の習熟度に合わせた話ができた ➤

    嫌になるほど長時間やる
 ⇒4時間ぶっ通しで参加者がXSSキメ続ける異様な空間を
  具現化した 当初の目標と達成度合い 40
  41. knock.xss.moe 41

  42. Any Questions?
 Feel free to ask me on Twitter(@yagihashoo)! 42