
資料來源: HP提供 翻譯整理:叡揚資訊 資訊安全事業處
正規表示式阻斷服務(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 |
.NET |
|
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」。