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. XSS1000本ノックを

    支える技術
    4IJCVZB944UFDIUBML
    1SFTFOUFECZ!ZBHJIBTIPP

    View full-size slide

  2. whoami
    ➤ 八木橋 優 Yagihashi Yu

    HN: やぎはしゅ

    Twitter: @yagihashoo

    Web: https://xss.moe/

    Job: 脆弱性診断

    その他いろいろ
    ➤ katagaitai勉強会、

    SECCON/SECCON Beginners、

    その他・・・
    2

    View full-size slide

  3. knock.xss.moe
    3

    View full-size slide

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

    View full-size slide

  5. XSS1000本ノック

    #とは
    5

    View full-size slide

  6. katagaitai勉強会
    ➤ 某社のCTFチームが年に2回くらい開催している勉強会
    ➤ 本来はその辺のCTFの過去問を紹介・解説する
    ➤ 2017年春ごろのやぎはしゅ

    「夏の勉強会、喋ることになったけど、

     資料作るの面倒くさいわ〜…」

    「何なら喋るのも面倒くさいわ〜…」

    「そうだ、資料も作らず、喋るのも

     やめればいいんだ!!」

    ⇒参加者がひたすらXSSするだけの

     最高の勉強会の開催を決意
    6
    % 6 (

    View full-size slide

  7. 参加者がひたすらXSSする勉強会
    ➤ 先に決めたこと

     1. 資料作らない 2. 解説しない 3. 嫌になるほど長時間やる
    ➤ XSS Challengeを紹介してひたすら解いてもらう?

    ⇒タダ乗り感がやばくてさすがに罪悪感がやばい

    ⇒しかも過去問紹介と大差ないので解説圧力がやばい
    ➤ XSS問しか出ないCTFをやればいいのでは?

    ⇒参加者にWrite-upを書いてもらえば万事解決

    ⇒どうせなら1000問くらい出したい

    ⇒PhantomJS使ったXSS問とか、作ったことはあるけど

     たくさん作るの面倒くさい

    ⇒XSS問出題プラットフォームをついでに作ることを決意
    7

    View full-size slide

  8. ★機密情報を抜くところまでがXSSです

    ⇒すべての問題でFLAGを盗むのがゴール
    ★ステージ制の導入で圧倒的成長

    ⇒現在のステージを解かないと次のステージには進めない
    ★1000問用意しとけばとりあえず最大手になれるのでは

    ⇒楽に、大量に、XSS問を出題するためのプラットフォーム作り
    XSS1000本ノック
    ➤ ただひたすらにXSSをキメるだけのCTF
    ➤ 決めたこと

     1. alertするだけのヤワなやつは要らない

     2. 嫌になるほどXSSばかりやって逆に好きになってもらう

     3. XSS Challengeの最大手を目指す
    8

    View full-size slide

  9. XSS問題の変遷
    9

    View full-size slide

  10. XSS問題の変遷(≒歴史)
    1. 『正規表現』時代
    2. 『alert関数置き換え』時代
    3. 『alert出せたら挙手』時代
    4. 『箱庭XSS』時代
    5. 『PhantomJS/Selenium Web Driver』時代
    6. 『Headless Chrome/Firefox』時代
    10
    ➤ 僕が見たことのあるCTF等におけるXSS問題の出題手法を

    紹介しつつ歴史を振り返ってみる

    (※私見かつ前後関係は適当)

    View full-size slide

  11. 『正規表現』時代
    ➤ (Web上でいい例がないか探してみたけどなかったよ…)
    ➤ 何のひねりもなく、正規表現でXSSペイロードが正解っぽいか
    を判定する方法
    ➤ 想定解が正規表現に落とし込めるほど限られているので

    あれば使えなくもない
    ➤ やぎはしゅも昔々作ったことがあるが大量の想定外の解との
    終わりなき闘いになるので実際のところ現実的ではない
    ➤ input.match(/alert\(1\)<\/script>/)
<br/>⇒img.onerrorでもできるよ!スペースは???などなど<br/>11<br/>

    View full-size slide

  12. 『alert関数置き換え』時代
    ➤ XSS Challenges(https://xss-quiz.int21h.jp/)や

    XSS Games(https://xss-game.appspot.com/)など
    ➤ 元々のalert関数を自作のものに置き換えて正しい文字列を

    引数として渡しているかなどをもとに判定する
    ➤ 実装が手軽にできるので、競技として行うものでなければ

    これが最適解かもしれない
    ➤ ただし、CTFなど、競技性のあるXSS Challengeの場合は

    開発者ツールなどで容易に不正が可能なので不向き

    12

    View full-size slide

  13. 『alert出せたら挙手』時代
    ➤ 昔セキュリティキャンプのCTFで見た稀有な例
    ➤ オフラインで開催しているCTFだからこそできる、

    alertを出せたら運営を呼んで確認してもらい、FLAGを

    教えてもらうという方法
    ➤ お世辞にもスマートとはいえない
    ➤ 趣旨が異なるものの、Cure53のXSS Challengeなど、

    最終的に人の目でペイロードを確認するケースも同様かも

    (賞金あったりするし、これはむしろ妥当)
    13

    View full-size slide

  14. 『箱庭XSS』時代
    ➤ SECCONの代名詞
    ➤ google:箱庭XSS / google:XSS Bonsai
    ➤ .NET FrameworkのWebControlを使ってIE7っぽい動きをする

    exeを配布するという狂った斬新な切り口を提示した問題作
    ➤ 僕は好きですよ!次回作待ってます!
    ➤ 実態としては確かalert関数の置き換えをしていたような

    気がするので、あくまで発展系(要出典)

    ⇒ブラウザの開発者ツールやローカルプロキシなどで

     悪さができないという点で優秀
    14

    View full-size slide

  15. 『PhantomJS/Selenium WebDriver』時代
    ➤ いろいろなCTFで多数の事例あり?

    (ただしPhantomJSは終わった感あるので今後は出なそう)
    ➤ 実際のブラウザ自体を操作、またはエミュレーションする
    ➤ alertを実行できたらFLAG…などの単純な設問から脱却し

    管理者ユーザでログイン済のセッションをハイジャックする

    といった発展的、実践的な設問が可能となった
    ➤ XSS問の多様性の観点ではひとまずここで頭打ち?

    実際のブラウザが動くならもうこれ以上はないよね、

    という感じ
    15

    View full-size slide

  16. 『Headless Chrome/Firefox』時代
    ➤ Google CTFなどで実績あり
    ➤ 正直XSS問のためだけにSelenium準備するの面倒くさい
    ➤ PhantomJSのビルド面倒くさすぎ
    ➤ 現れた救世主、ChromeとFirefoxのHeadlessモード!
    ➤ 特にChromeではSeleniumを噛ませずに自在に操作できる
    ➤ FirefoxはMDN見る限りはやっぱりSelenium使ってる
    ➤ 手軽さ、実際のブラウザが動く点でもはや一強といっても

    過言ではない
    16

    View full-size slide

  17. こんな構成
    17

    View full-size slide

  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
    問題ページ
    スコアサーバ
    被害者クライアント

    View full-size slide

  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…

    View full-size slide

  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のあるページ)に

    アクセスする

    View full-size slide

  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を窃取するための
    ペイロードを組む

    View full-size slide

  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を送信する

    View full-size slide

  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が

    順にアクセスしていく

    View full-size slide

  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を

    外部に送信するなど被害者ブラウザと

    同じ動きをする

    View full-size slide

  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をスコアサーバに

    送信し、次の問題に進む

    View full-size slide

  26. 構成(ポイント)
    ➤ 各問題を、可能な限り想定解で解いてもらう(後述)
    ➤ 設問の柔軟性を損なわないため、各問題ページ全てに

    VirtualHostを切っている

    ≒proxy_passすればPHP以外で動いている問題ページも

     容易に使うことができる

    (PHPだけでよければサブドメインの値でincludeする内容を

     変える方が簡単そう)
    ➤ Headless Chromeを並列でバシバシ実行するのが難しそう

    (※調べ方が悪いだけ説あり)なので、ジョブキューを

    用意してユーザからのリクエストに応じて順次実行する
    26

    View full-size slide

  27. 課題1
    「セパレーション」
    27

    View full-size slide

  28. 同一ホスト上でXSS問を提供することの難しさ
    ➤ 同一ホスト上で大量のXSS問を用意する場合、オリジンまで

    同一のものとしてしまうと簡単な問題のXSSを使って別の

    問題のFLAGを取得することができてしまうケースがある
    ➤ 素直にSame Origin Policyに頼りたいが問題毎にドメインを

    用意するのは面倒くさい(2,3問ならそれもあり)
    ➤ DNSでワイルドカードあてるにしても1000個の問題を

    サブドメイン毎に効率よく振り分ける方法は考える必要あり
    28
     取りうる選択肢
    1. サブドメインの値に紐づく問題ファイルをincludeする
    2. サブドメイン毎にDocRoot分けてVirtualHost切る

    View full-size slide

  29. 1. サブドメインの値に基いてinclude先変える
    29
     ⭕メリット
    1. *.knock.xss.moeは問題ページを、knock.xss.moeをスコアサーバを、
    といった具合に、単一のアプリケーションですべて完結する設計が可能
    2. サブドメインの値に応じてinclude先のPHPファイルを変えるだけなので

    Webサーバへの負荷は少なそう
     ❌デメリット
    1. そもそも単一のアプリケーションで完結するのって便利なのか?

    (XSS問題の提供プラットフォームとしては逆に不便では)
    2. PHP以外の言語で作った問題ページを用意するのが大変

    (今後特定の言語やフレームワーク依存の問題も出すかも?)

    View full-size slide

  30. 2. サブドメイン毎にDocRoot分けてVirtualHost切る
    30
     ⭕メリット
    1. proxy_passすれば何でもあり⇒設問の柔軟性を損なわない
    2. スコアサーバから問題を切り離すことで、スコアサーバの

    汎用性向上、問題の管理も楽ちん(別リポジトリで管理)
     ❌デメリット
    1. 設定ファイル地獄
    2. Webサーバへの負荷がちょっとヤバそう

    (VirtualHost多すぎてNginxの起動時に怒られるw)

    View full-size slide

  31. 2. サブドメイン毎にDocRoot分けてVirtualHost切る
    31
     ❌デメリット
    1. 設定ファイル地獄

    ⇒問題の追加時に設定ファイルも自動で書き換えてしまおう

    ⇒さすがに気持ち悪いので妥協案を採用(あとで見せます)
    2. Webサーバへの負荷がちょっとヤバそう

    (VirtualHost多すぎてNginxの起動時に怒られるw)

    ⇒設定ファイルへの追記か何かで解決した(はず)

    ⇒負荷自体は実はそんなでもない?あまりよくわかってなry

    View full-size slide

  32. 結論
    32
    倱嶷獌512؋⊠┊猳

    View full-size slide

  33. 課題2
    「別解」
    33

    View full-size slide

  34. 別解は1000本ノックにも襲いかかる
    ➤ katagaitai勉強会当日は、たくさんの別解が観測できました
    ➤ 実のところ、あんまり気にしていない

    ⇒別解も解だよね、というお気持ち
    ➤ せっかくなのでこちらが想定している解法でやってみて

    欲しい!

    ⇒可能な限り想定解以外を削ぎ落とす対策を考える
    34
     よく見かける別解
    1. 外部ファイル参照(文字数制限がなかったことに…)
    2. eval+location.hash(文字種の制限もなかったことに…)

    View full-size slide

  35. Content Security PolicyでXSS対策!
    ➤ 「外部ファイル読み込まれるのツラい…」

    「eval実行されるのツラい…」

    って、どこかで聞いたことのある話
    ➤ Content Security Policyを使えば外部リソース読み込みや

    evalの実行を防止することができる!!
    ➤ 本来はまっとうなセキュリティ施策として使われるべき

    CSPだが、XSS問の別解防止にも大変役に立つので知見として

    どんどん広めていきたい
    ➤ 実際の例を見るのは1000本ノックを受けてもらえばいいので

    ここでは1つだけ具体例を紹介する

    35

    View full-size slide

  36. Content Security PolicyでXSS対策!(具体例)
    36
    header('X-XSS-Protection: 0');
    function myescape($s)
    {
    return substr($s, 0, 65);
    }
    ?>
    = myescape($_GET['q']) ?>
    CSP導入前
    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で外部オリジンの

    スクリプトの参照を

    禁止することで、

    想定外の解法を潰しこむ

    View full-size slide

  37. 結論
    37
    倱嶷獌%52؋㧡涹猳

    View full-size slide

  38. ➤ 資料作らない

    ⇒使い回しの自己紹介スライドとURL掲載用のスライド以外

     使わなかった!
    ➤ 解説しない

    ⇒前に立たない代わりに個別に回って詰まってる人向けに

     解説・アドバイス

    ⇒結果的に各参加者の習熟度に合わせた話ができた
    ➤ 嫌になるほど長時間やる

    ⇒4時間ぶっ通しで参加者がXSSキメ続ける異様な空間を

     具現化した
    当初の目標と達成度合い
    40

    View full-size slide

  39. knock.xss.moe
    41

    View full-size slide

  40. Any Questions?

    Feel free to ask me on
    Twitter(@yagihashoo)!
    42

    View full-size slide