深入淺出:理解ReDoS By Regex Injection的弱點、威脅與修補策略

Turned-on Computer Monitor Displaying Text

在這個資料驅動的時代,我們的網路生活越來越依賴各種軟體應用。然而,這些應用的安全性卻時常被忽視,尤其是那些不易被察覺,但一旦被利用將會產生嚴重影響的漏洞。今天,我們要來談談其中一種名為ReDoS(正規表示式拒絕服務)的攻擊手法。

ReDoS:一個危險而又常被忽視的弱點

ReDoS或稱正規表示式拒絕服務攻擊,是一種對系統性能的攻擊方式。這種攻擊利用了特定正規表示式的糟糕效能,導致大量的CPU時間被耗盡,而使得系統不再能夠處理新的請求。舉個例子來說,當一個用戶在網站上輸入一個極端長且複雜的字符串進行搜索,如果後端的正規表示式無法高效地處理這樣的字符串,就有可能導致CPU資源的耗盡,我知道有人會想說現在是什麼時代了CPU都已經快到不知道哪裡去了怎麼可能還會讓這種攻擊成功,但是在實務的環境中,為了一些成本考量因素,一般來說不會給這麽高效能的CPU,如此一來這種攻擊就很有可能會成功。

威脅情境:使用者輸入被惡意利用

想像一下,你的網站有一個搜索框,使用者可以在裡面輸入任何他們想查找的詞彙。你的後端使用正規表示式來解析這些輸入,以便將結果返回給使用者。如果這裡的正規表示式寫得不夠優化,那麼一個惡意使用者就有可能輸入一個極端長且複雜的字符串,使得你的系統需要消耗大量的時間去處理這個請求,而導致對其他正常用戶請求的處理速度大大降低。

修補建議:提升正規表示式的效能

修復ReDoS攻擊的首要之務,就是要優化我們的正規表示式。我們要避免那些可能會導致「回溯」的正規表示式,回溯會使得正規表示式的處理時間大大增加。 那什麼是回溯呢?

當我們提到正規表示式的「回溯」,實際上我們是在談論正規表示式引擎如何嘗試匹配正規表示式模式和目標字符串的過程。

在進行匹配的時候,正規表示式引擎會從左到右依次嘗試匹配每一個模式元素。當引擎在某一點上無法繼續匹配時,它會「回溯」到先前已匹配的某一位置,然後從那裡嘗試不同的匹配方式。

這種「回溯」機制使得正規表示式具有強大的靈活性,但也可能帶來性能問題。特定的正規表示式,如含有大量的群組(group)或選擇(choice)元素,可能導致回溯過程變得極其複雜和耗時。

舉一個例子來說明回溯的情況:

假設我們有一個正規表示式 a*b,我們試圖將其匹配到字符串 aaaaac。在初次嘗試匹配時,a* 會貪婪地匹配所有的 a,然後引擎嘗試匹配 b,但此時已經沒有字符可以匹配。於是引擎「回溯」,放棄先前匹配的最後一個 a,然後再次嘗試匹配 b。這個過程將重複進行,直到回溯到所有的 a 都被放棄。最終,這個正規表示式無法匹配目標字符串,因為目標字符串的最後一個字符是 c,而不是 b

另一個例子,假設我們有一個正規表示式 (x+y+)+z,這個表達式意味著我們希望匹配一或多個 xy 的連續出現,後面跟著一個 z。那麼,如果我們嘗試將其匹配到一個只包含 xy,但不包含 z 的長字符串,例如 xxxxxyyyyyy,我們將會見到回溯的情況。

在這個情況下,正則表達式引擎會首先嘗試匹配 (x+y+)+,它會成功地匹配所有的 xy。然後,引擎會嘗試匹配 z,但是,由於目標字符串並不包含 z,這個匹配會失敗。

於是,引擎開始回溯。它會放棄對最後一個 y 的匹配,然後再次嘗試匹配 z。但是,由於目標字符串仍然不包含 z,所以這個嘗試仍然會失敗。引擎會再次回溯,這次放棄對倒數第二個 y 的匹配,然後再次嘗試匹配 z

這個回溯和嘗試匹配的過程將不斷重複,直到引擎放棄了對所有 xy 的匹配。最終,由於目標字符串並不包含 z,所以這個正則表達式無法成功匹配目標字符串。然而,由於大量的回溯,這個匹配過程可能會消耗大量的時間。

如果你的正規表示式含有大量這種可能導致大量回溯的模式,而你又試圖將其匹配到一個很長的字符串,那麼這可能會導致你的應用程序耗費大量的時間在這個匹配過程中,這也就是所謂的 ReDoS 攻擊。

所以除了要過濾這種不佳的寫法外,我們還需要限制用戶輸入的長度,避免出現超長字符串的輸入。

以C#為例,我們可以如下優化正規表示式:

csharpCopy code
// 不佳的正規表示式寫法
Regex.IsMatch(input, @"^(a+)+$");

// 優化後的正規表示式寫法
Regex.IsMatch(input, @"^a+$");

在這裡,我們消除了重複的 + 操作符,避免了回溯的產生,使得正規表示式可以高效地處理字符串。

總結,ReDoS是一個不容忽視的安全問題,我們需要對正規表示式有深入的理解,並且在實際的編程中採取優化措施,才能有效防止這種攻擊。希望這篇文章可以幫助大家對ReDoS有更深入的了解,並在自己的程式設計中做出相應的防護措施。

最後依照慣例,提供一些參考連結給大家

  1. OWASP Regular expression Denial of Service – ReDoS:Open Web Application Security Project (OWASP) 是一個非盈利性的國際組織,提供了大量的免費資源來提升軟體安全性。在這個頁面,他們詳細地解釋了ReDoS攻擊,包括它是如何工作的,以及如何防止這種攻擊。 連結:https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS

  2. Regex101:這是一個線上的正則表達式編輯器和測試工具。你可以在這個網站上測試你的正則表達式,看看它們是如何匹配文本的,也可以看到匹配過程中可能出現的回溯。 連結:https://regex101.com/

  3. Microsoft .NET Regular Expressions:這是Microsoft官方的.NET正則表達式教程,包含了大量的資訊和範例,可以幫助你理解和使用C#的正則表達式。 連結:https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expressions

  4. Regular-Expressions.info:這個網站提供了大量的正則表達式相關資訊,包括教程,範例,以及一些常見問題的解答。 連結:https://www.regular-expressions.info/

  5. Preventing Regex Denial of Service (ReDoS) attacks in .NET applications:這篇部落格文章提供了一些具體的策略來防止ReDoS攻擊在.NET應用程序中發生。 連結:https://blog.stayhacking.com/preventing-regex-denial-of-service-redos-attacks-in-net-applications-d3a0c44a7c19

發佈留言