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

^ReDoSの色々$

LHazy
July 15, 2020

 ^ReDoSの色々$

LHazy

July 15, 2020
Tweet

More Decks by LHazy

Other Decks in Technology

Transcript

  1. /^ReDoSの色々$/

    View Slide

  2. 今日話すこと
    ● 正規表現のおさらいとReDoSの仕組み
    ● ReDoSの事例
    ● ReDoSのスキャンツールの紹介
    ● ReDoSの予防
    ● まとめ
    間違いの指摘や質問は @kawada_syogo225 までお願いします!

    View Slide

  3. /^自己紹介$/
    ● Hazy(@kawada_syogo225)
    ● WAFの開発・運用・監視と
    Webの脆弱性のリサーチ
    ● ^(?:珈琲|カメラ|カフェ巡り|.*)$

    View Slide

  4. 正規表現のおさらい

    View Slide

  5. 連接・選択・繰り返し
    ● 連接
    ○ 単純に隣り合う文字を表す。ただの文字列も正規表現。
    ○ 例:abcd、hogefuga、regex
    ● 選択
    ○ 並べた正規表現のどれかを選ぶ。
    ○ 例:Java(S|s)script ← JavaScript、または、Javascriptを表す。
    ● 繰り返し
    ○ ある正規表現を繰り返し適用する。
    ○ 例:(0|1)* ← 0か1が繰り返し出現する文字列にマッチする。つまり、バイナリ。

    View Slide

  6. 文字クラス・特殊文字・キャプチャ
    ● 文字クラス
    ○ アルファベット、数字などのまとまった文字達を表す。
    ○ 例:[a-zA-Z]、[0-9]、[02468]
    ● メタ文字
    ○ 数字や非単語構成文字(記号)や行頭、行末などを表す特別な記号
    ○ 例:^\s++$ ← 空白のみで構成される行
    ● キャプチャ
    ○ 正規表現のグループ化、演算の優先度の変更、部分的な取り出しに利用できる
    ○ 例:YYYY/MM/DDをYYYY-MM-DDに変換する正規表現と JavaScriptコード。
                   
    > '2020/07/15'.replace(/(\d\d\d\d)\/(\d\d)\/(\d\d)/, '$1-$2-$3');
    '2020-07-15'
    >

    View Slide

  7. 色々なJavaScriptにマッチする正規表現

    View Slide

  8. 繰り返しについてもう少し
    ● スター演算子
    ○ 0回以上の繰り返しを表す
    ○ 例:\d* ← 空文字か任意個の数字列にマッチ
    ● プラス演算子
    ○ 1回以上の繰り返しを表す
    ○ 例:\d+ ← 一つの数字か任意個の数字列にマッチ
    ● 疑問符演算子
    ○ 0回か1回の繰り返しを表す
    ○ 例:\d? ← 空文字か1個の数字にマッチ
    ● 範囲量指定子
    ○ n~m回の繰り返しを表す。( n < m)
    ○ 例:\d{2,10} ← 2個以上、10個以下の数字の繰り返しにマッチ

    View Slide

  9. 問題1
    ● 文字列「1234」に対して下の正規表現を実行した場合、グループ1と
    グループ2にキャプチャされる文字列は?

    View Slide

  10. 答え
    ● グループ1は「1234」
    ● グループ2は空

    View Slide

  11. 問題2
    ● 文字列「1234」に対して下の正規表現を実行した場合、グループ1と
    グループ2にキャプチャされる文字列は?

    View Slide

  12. 答え
    ● グループ1は空
    ● グループ2は「1234」

    View Slide

  13. (欲張りな|控え目)な量指定子
    ● 欲張りな量指定子
    ○ 可能な限り長くマッチしようとする。「 *」、「+」、「?」、「{n,m}」が欲張る。
    ○ 例:(\d*)(\d*) ← 左のグループが全ての数字を消費する。
    ● 控え目な量指定子
    ○ 可能な限り短くマッチしようとする。「 *?」、「+?」、「??」、「{n,m}?」が控え目。
    ○ 例:(\d*?)(\d+) ← 左のグループは控え目なため、右のグループが欲張る。

    View Slide

  14. 問題
    ● 文字列「xxxxxxxxxxy」に対して下の正規表現を実行した場合、どのような
    動きになるか?

    View Slide

  15. 答え
    1. 最初の「x+」が10個の(全て)の「x」にマッチする。
    2. 2番目の「x+」が失敗する。
    3. 最初の「x+」が「x」を一つ手放して、9個の「x」にマッチする。
    4. 2番目の「x」が1個の「x」にマッチする。
    5. グループに繰り返し「+」がついているが、これ以上マッチする部分が
    ない為、1回のマッチで終了する。
    6. 「y」が「y」とマッチする。

    View Slide

  16. マッチ対象に「y」がなかったら?
    1. 最初の「x+」が2つ「x」を手放して8つの「x」にマッチ。
    2. 2番目の「x+」が2個の「x」にマッチ。
    3. グループの繰り返しに失敗。
    4. yのマッチに失敗。
    5. 2番目の「x+」が「x」を手放して1つの「x」にマッチ。
    6. グループの繰り返しに失敗。
    7. yのマッチに失敗。
    8. 最初の「x+」が3つの「x」を手放して8つの「x」にマッチ。
    9. 2番目の「x」が3つの「x」にマッチ。
    10. 以下、繰り返し。
    文章で説明するとめんどい。。。

    View Slide

  17. regex101で正規表現の動きを追ってみる
    https://regex101.com/

    View Slide

  18. バックトラック
    ● 正規表現はマッチするまであらゆる組み合わせを試行する。
    ● 直前の例でみたような、後戻りして再試行するような動作を
    バックトラックという。
    ● (x+x+)+ だけでもマッチ組み合わせが 大量に存在するが、その全てを
    試行してもマッチすることはない。
    ○ (9,1)、(8,2)、(8,1)、(5,5)、(1,9)
    ○ ((7,1),(1,1))
    ○ ((1,1),(1,1),(1,1),(1,1),(1,1))

    View Slide

  19. ReDoSとは
    ● ReDoSとは入力に対し、組み合わせやバックトラックによる試行の回数が
    増大することにより計算リソースが消費され、可用性が失われる脆弱性。
    ● 入力された文字列の長さに対して O(2n) や O(2^n) で計算量が増加する。

    View Slide

  20. ReDoSの事例

    View Slide

  21. Stack Overflowの例
    ● 2016年7月20日にReDoSで34分の停止が発生。
    ● 「-- play happy sound for player to enjoy」の後に2万個のスペースが続く
    投稿が原因でDoSった。
    ● 原因の特定に10分、コードの修正に14分、修正の適用に10分かかった
    らしい。。。対応、早くない?!
    ● 行頭と行末のスペースを除去するために「^[\s\u200c]+|[\s\u200c]+$」
    という正規表現を使用していた。
    ● https://stackstatus.net/post/147710624694/outage-postmortem-july-20-2016

    View Slide

  22. Cloudfrareの例
    ● 2019年7月2日に27分の停止が発生。
    ● XSSを検知すためのWAFルール(正規表現)で過度なバックトラックが
    発生しCPUリソースが枯渇したことが原因。
    ● 詳細なレポートは下記を参照。
    ○ https://blog.cloudflare.com/details-of-the-cloudflare-outage-on-july-2-2019/

    View Slide

  23. ModSeucrity CRSの例
    ● ModSecurityはOWASPが提供するOSSなWAF。
    ● CRS(Core Rule Set)はOWASPが提供するOSSなWAFルール。
    ● 2019年にCRSのReDoSが5つ見つかっている。
    ○ https://coreruleset.org/20190425/regular-expression-dos-weaknesses-in-crs/

    View Slide

  24. Expressの例
    ● 2016年にExpress が依存する nagotiator という Accept-Language ヘッダー
    を扱うライブラリでReDoSが見つかった。
    ● 修正コミット
    ○ https://medium.com/node-security/regular-expression-denial-of-service-affecting-express-js-9c397c164c43
    ● 以下のようなコードを書いてるとDoSる。
    app.get('/', (req, res) => {
    if (req.acceptsLanguages
    ('ja')) {
    res.send('ピエン');
    } else {
    res.send
    });

    View Slide

  25. ReDoSの検出ツール

    View Slide

  26. w3af
    ● 右のようなReDoSを引き起こしそうな文字列を送信して
    RTTが通常より4倍遅くなればReDoSと判定。
    ● 「a」や「1」は10個ずつ増やしていき、最終的に80個
    まで試す。
    ● ソースコードは以下。
    ○ https://github.com/andresriancho/w3af/blob/master/w3af/plugins/audit/redos.py
    aaaaaaaaaaX!
    aaaaaaaaaaaaaaaaaaaaX!
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaX!
    [email protected]!
    [email protected]!
    [email protected]!
    11111111119!
    111111111111111111119!
    1111111111111111111111111111119!

    View Slide

  27. Wisdom/RegEx-DoS
    ● esprimaというES7まで対応したJavaScriptのパーサを使って
    正規表現リテラルを摘出。
    ● new RegExp(‘aaaa’) や動的に正規表現を組み立てている場合は
    摘出できない。
    ● ReDoSの判定自体は safe-regex に丸投げ。
    ● リポジトリ
    ○ https://github.com/Wisdom/RegEx-DoS

    View Slide

  28. safe-regex
    ● regexp-tree というライブラリを使って正規表現をASTに変換して、
    ASTを再帰的に走査して、一番ネストした * 演算子を探す。
    ● ネストの深さが「1」以上、または、* 演算子が25個より多く
    使用されている場合は危険と判定。
    ● 「星の高さ」という概念を基にしている。
    ● 例えば、(b|aa*b)*aa* の星の高さは 2 。
    ● 入れ子になった * 演算子は組み合わせ爆発を誘発しやすい。
    ● リポジトリ
    ○ https://github.com/davisjam/safe-regex/

    View Slide

  29. davisjam/vuln-regex-detector
    ● 複数の検出器によるチェックを行い、指定した言語の正規表現エンジンにて
    テストを行うことで検知の精度を高めている。
    ● 正規表現エンジンの機能や独自の最適化によって特定のエンジンのみ処理時間が
    悪化するケースがある為、このような方針を採用している。
    ● Githubリポジトリを指定してのスキャンが可能で、ソースコードからの正規表現の
    摘出はJavaScriptとPythonしているが、動的に正規表現を組み立てている場合は
    対応できない。
    ● 正規表現の摘出、ReDoSの検知、テストがそれぞれ別のスクリプトに
    なっているため、単体で利用可能。
    ● リポジトリ
    ○ https://github.com/davisjam/vuln-regex-detector/

    View Slide

  30. google/re2
    ● Googleが開発した正規表現エンジン。
    ● ユーザーからの信頼できない入力に対してリスクなく正規表現を扱えるよう
    設計・実装されている。
    ● 入力された文字列に対して線形時間でマッチングを行えることを
    保証している。
    ● その代わりに、他の正規表現エンジンと比べて機能が制限されている。
    ○ https://github.com/google/re2/wiki/WhyRE2
    ● 先述のCloudflareの事例で、事後対応としてRE2の採用が上がっている。

    View Slide

  31. ReDoSの予防

    View Slide

  32. 正規表現のパフォーマンスに気を付ける
    以下のような基本的なお作法を守る。
    1. 量指定子を入れ子にしない
    2. 曖昧さを取り除く
    3. 控え目な量指定子や強欲な量指定子を使ってバックトラックを抑制する。
    場合によっては、独自にロジックを書いた方が正規表現より高速な場合もある。

    View Slide

  33. ツールやエンジンのオプションを活用する
    ● ReDoSのチェックは時間がかかるため、チェック済みの正規表現を
    ライブラリとして持っておくのも良いかも。
    ● エンジンによってはバックトラックの上限が設定できたりするので、
    確認する。
    ● PHPは「pcre.backtrack_limit」で可能。
    ● ModSecurityは「SecPcreMatchLimit/SecPcreMatchLimitRecursion」
    ● .NETはRegexコンストラクタの第三引数でタイムアウトを設定可能。

    View Slide

  34. まとめ
    ● ReDoSは正規表現のマッチングの計算量の増大により引き起こされる。
    ● ReDoSはビジネスロジック、ライブラリ、ミドルボックス等至る所に
    潜んでいる。
    ● WAFでの防御ができない。むしろ、WAFが攻撃対象になる。
    ● 現時点では脆弱性診断が難しい。
    ● 予防のために、パフォーマンスに関する作法を学ぼう。
    ● ツールを使用して疑わしい正規表現をチェックする。
    ● 正規表現エンジンや言語の設定で計算リソースを制限する。

    View Slide

  35. 追記:ReDoSを使ったサイドチャネル攻撃
    ● ReDoSはサイドチャネルにも使えるよってツッコミがあったので、
    参考資料を載せておきます。
    ● https://speakerdeck.com/lmt_swallow/revisiting-redos-a-rough-idea-of-data-exfiltration-by-redos-and-side-channel-techniques

    View Slide

  36. 参考文献
    ● 正規表現技術入門 ー最新エンジン実装と理論的背景ー
    ○ https://gihyo.jp/book/2015/978-4-7741-7270-5
    ● 詳説 正規表現
    ○ https://gihyo.jp/book/2015/978-4-7741-7270-5
    ● 正規表現入門 星の高さを求めて
    ○ https://www.slideshare.net/sinya8282/ss-32629428
    ● Runaway Regular Expressions: Catastrophic Backtracking
    ○ https://www.regular-expressions.info/catastrophic.html
    ● The Impact of Regular Expression Denial of Service (ReDoS) in Practice
    ○ https://medium.com/bugbountywriteup/introduction-987fdc4c7b0
    ● The Regular Expression Denial of Service (ReDoS) cheat-sheet
    ○ https://levelup.gitconnected.com/the-regular-expression-denial-of-service-redos-cheat-sheet-a78d0ed7d865
    ● A Sense of Time for JavaScript and Node.js
    ○ https://medium.com/@davisjam/a-sense-of-time-for-javascript-and-node-js-68c9114f5d48
    ● 正規表現とセキュリティ / Regular Expressions and Their Security-Related Aspects
    ○ https://speakerdeck.com/lmt_swallow/regular-expressions-and-their-security-related-aspects

    View Slide