簡體   English   中英

Java:Matcher.find使用高CPU利用率

[英]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。

除了通過預編譯和/或簡化它們來改善正則表達式性能這些顯而易見的事情之外,您可以執行以下操作來減少正則表達式檢查的數量

  1. 根據參數類型使用用戶輸入的肯定驗證。 例如,如果某個參數必須是一個簡單的數字,請不要浪費時間檢查它是否包含惡意XML腳本。 只需檢查它是否匹配[0-9] +(或類似的簡單)。 如果是,那就沒問題 - 跳過檢查所有500個正則表達式。

  2. 嘗試找到可以消除整類攻擊的簡單正則表達式 - 在正則表達式中找到常見的東西。 例如,如果您有100個正則表達式檢查是否存在某些HTML標記,請檢查該內容是否首先包含至少一個HTML標記。 如果沒有,您立即節省檢查100個正則表達式。

  3. 緩存結果。 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM