GSS資安電子報0082期【正規表示式阻斷服務(ReDos)攻擊】

2013-02-22 11:40

alt

資料來源: HP提供  翻譯整理:叡揚資訊 資訊安全事業處alt

正規表示式阻斷服務(ReDos)其實不是什麼新的技術,但並未被重視。正規表示式使用起來常常會犯些小錯誤,而這對攻擊是非常有效的,有時甚至難以解決。

容易發生的錯誤

簡單的說,任何正規表示式的pattern會有重複的符號,如「+」、「*」,表示可重複的部份(但這不是唯一有弱點的pattern,可參考以下其他有弱點的pattern),且這類的問題是滿常見的,連OWASP都有收錄此問題,並建議如果達到驗證pattern,可參考:

 http://en.wikipedia.org/wiki/ReDoS#Vulnerable_regexes_in_online_repositories)

常見弱點pattern:

  • (a+)+

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

  • (a|aa)+

  • (a|a?)+

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

攻擊範例

以下為幾個攻擊測試,pattern為「^(a+)+$」,同時測試Java與.Net,結果如下:

Input

Java
Pattern.matches("^(a+)+$", input);

.NET
new Regex("^(a+)+$").IsMatch(input)

aaaaaaaaaaaaaaaaaaaa!

79ms

299ms

aaaaaaaaaaaaaaaaaaaaa!

144ms

542ms

aaaaaaaaaaaaaaaaaaaaaa!

259ms

1113ms

aaaaaaaaaaaaaaaaaaaaaaa!

434ms

2139ms

aaaaaaaaaaaaaaaaaaaaaaaa!

867ms

4509ms

aaaaaaaaaaaaaaaaaaaaaaaaa!

1823ms

8672ms

正如您看到的,長度25個字元時,會讓執行序忙碌長達1秒,而每多加一個字元所花費的時間是以倍數成長。且不要以為攻擊字串使用一連串的「a」是很容易過濾,這一切都需仰賴驗證pattern的設計,是否能辨別看起來像個正常的字串,但其實是個攻擊行為。所以不易透過簡單的驗證來阻止此類型的攻擊。

不易修復

OWASP提到的弱點pattern,是以Java為例檢測類別名稱「^(([a-z])+.)+[A-Z]([a-z])+$」。這不是一個非常複雜的pattern,但該如果調整?注意實際上真的有可能類別名稱是長於25個字元,其實不是那麼容易解決。並需妥協於false positives(誤報) 與 false negatives(誤判)。

其他解決辦法

有些版本的Perl PCRE函式庫有個「match」函式,當執行pcre_exec()與pattern匹配時呼叫遞迴。通過控制每次執行操作時可被呼叫的最大次數,限制所使用的資源。而限制的數量被設定於pcreapi文件中。預設值為10萬,可直接修改數值或也可透過命令修改如「--with-match-limit=500000」。