[英]Java : Matcher.find using high cpu utilization
我正在使用mod安全規則https://github.com/SpiderLabs/owasp-modsecurity-crs來清理用戶輸入數據。 我正面臨cpu射擊和延遲匹配用戶輸入與mod安全規則正則表達式。 總的來說,它包含500多個正則表達式來檢查不同類型的攻擊(xss,badrobots,generic和sql)。 對於每個請求,我會查看所有參數並檢查所有這500個正則表達式。 我正在使用Matcher.find
來檢查參數。 在這種情況下,一些參數屬於無限循環,我使用以下技術解決了這個問題。
消除用戶請求大約需要大約500毫秒,並且cpu%會上升。 我使用visualvm.java.net和我的測試套件運行程序進行了分析。
Cpu配置文件輸出
請幫我減少cpu使用率和平均負載?
如果可能的話, 編譯你的正則表達式並保留它們,而不是重復(隱式)編譯(特別是在循環中)。
請參閱java.util.regex - Pattern.compile()的重要性? 了解更多信息。
我建議你看一下這篇論文: “為了更快的字符串匹配進行入侵檢測或超過Snort的速度”
有更好的方法來進行您描述的匹配。 從本質上講,您可以選擇要匹配的500個模式,並將其編譯為單個后綴樹,該樹可以非常有效地將輸入與所有規則進行匹配。
該論文解釋說,這種方法被Dan Gusfield描述為“精確集匹配的Boyer-Moore方法”。
Boyer-Moore是一種眾所周知的字符串匹配算法。 本文描述了Boyer-Moore用於集匹配的變體。
我認為這是你問題的根源,而不是正則表達式本身:
對於每個請求,我會查看所有參數並檢查所有這500個正則表達式
無論你的正則表達式有多快,這仍然是很多工作。 我不知道你有多少參數,但即使只有少數參數,每個請求仍然會檢查數千個正則表達式。 這會殺死你的CPU。
除了通過預編譯和/或簡化它們來改善正則表達式性能這些顯而易見的事情之外,您可以執行以下操作來減少正則表達式檢查的數量 :
根據參數類型使用用戶輸入的肯定驗證。 例如,如果某個參數必須是一個簡單的數字,請不要浪費時間檢查它是否包含惡意XML腳本。 只需檢查它是否匹配[0-9] +(或類似的簡單)。 如果是,那就沒問題 - 跳過檢查所有500個正則表達式。
嘗試找到可以消除整類攻擊的簡單正則表達式 - 在正則表達式中找到常見的東西。 例如,如果您有100個正則表達式檢查是否存在某些HTML標記,請檢查該內容是否首先包含至少一個HTML標記。 如果沒有,您立即節省檢查100個正則表達式。
緩存結果。 webapps中生成的許多參數都會重復出現。 不要一遍又一遍地檢查相同的內容,但只記得最終的驗證結果。 注意限制緩存的最大大小以避免DOS攻擊。
另請注意,否定驗證通常很容易繞過。 有人只是更改了惡意代碼中的幾個字符,而且你的正則表達式不匹配。 你必須增加你的regexp“數據庫”,以防止新的攻擊。 正面驗證(白名單)沒有這個缺點,而且更有效。
避免表達:
也許您可以考慮對正則表達式進行分組,並根據用戶輸入應用一組給定的常規表達式。
如果你有如此多的正則表達式,你可以使用trie算法( http://en.wikipedia.org/wiki/Trie )對它們進行分組(至少部分)。
這個想法是,如果你有例如/abc[0-9-]/
, /abde/
, /another example/
, /another example/
。 /.something else/
和/.something else/
/.I run out of ideas/
,你可以將它們組合成單一的正則表達式
/a(?:b(?:c[0-9-]|de)|nother example)|.(?:I run out of ideas|something else)/
通過這種方式,匹配器只能運行一次而不是四次,並且您可以避免大量的回溯,因為常見的起始部件是如何在上面的正則表達式中編寫的。
在這500個中必須有一部分有問題的正則表達式。就是這樣的正則表達式
String s = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB";
Pattern.compile("(A+)+").matcher(s).matches();
將需要數年才能完成。
因此,在您的情況下,我會記錄所有有問題的正則表達式與他們有問題的輸入。 找到這些后,您可以手動重寫這些有問題的正則表達式並測試它們與原始版本。 可以使用更簡單,更易讀的java函數重寫正則表達式。
另一種選擇,雖然它不能解決上面的問題,但你也可以使用更快(在某些情況下為x20)和更有限的正則表達式庫 。 它可以在Maven Central中找到 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.