防止 JavaScript 中的正則表達(dá)式回溯
正則表達(dá)式是用于在軟件應(yīng)用程序中操作和驗(yàn)證文本的強(qiáng)大工具。然而,某些正則表達(dá)式模式可能容易受到回溯的影響,這可能會(huì)導(dǎo)致超線性運(yùn)行時(shí),并可能導(dǎo)致DoS攻擊。在本文中,我們將探討什么是回溯、它如何導(dǎo)致性能問(wèn)題以及如何在正則表達(dá)式中防止回溯。
正則表達(dá)式中的回溯是什么
回溯是正則表達(dá)式引擎用來(lái)處理包含可選或重復(fù)子模式的復(fù)雜模式的技術(shù)。當(dāng)正則表達(dá)式模式包含可選或重復(fù)的子模式時(shí),引擎可能需要嘗試子模式的多種組合才能找到匹配項(xiàng)。這個(gè)過(guò)程稱為回溯。
例如,有以下正則表達(dá)式:
/^[a-zA-Z0-9\s]+$/
此正則表達(dá)式應(yīng)匹配僅包含字母數(shù)字字符和空格的任何字符串。然而,它很容易受到回溯的影響,因?yàn)?code>+字符類后面的運(yùn)算符允許字符類的任意數(shù)量的重復(fù)。
攻擊者可以通過(guò)發(fā)送包含一長(zhǎng)串不匹配字符的惡意搜索查詢來(lái)利用此漏洞,例如:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
該字符串包含 30 個(gè)a
字符,后跟一個(gè)b
. 當(dāng)正則表達(dá)式引擎嘗試匹配該字符串時(shí),它將前 30 個(gè)a
字符與字符類匹配,但無(wú)法匹配b
字符。然后,引擎將回溯并嘗試字符類的不同組合,直到匹配整個(gè)字符串或耗盡所有可能的組合。
在本例中,字符串中有 31 個(gè)字符,因此有 2 種可能的字符類組合可供嘗試。這可能需要很長(zhǎng)的時(shí)間,可能會(huì)導(dǎo)致服務(wù)器遭受 DoS
攻擊。
為了防止此漏洞,您可以修改正則表達(dá)式以使用*
運(yùn)算符代替+
運(yùn)算符,如下所示:
/^[a-zA-Z0-9\s]*$/
使用*
可以使正則表達(dá)式不易受到回溯并降低 DoS
攻擊的風(fēng)險(xiǎn),因?yàn)樗鼫p少了正則表達(dá)式引擎需要探索的可能路徑的數(shù)量。
+
的意思是“一個(gè)或多個(gè)”,而*
的意思是“零個(gè)或多個(gè)”。使用+
時(shí),正則表達(dá)式引擎必須在放棄之前嘗試與模式匹配的所有可能的字符組合。這可能會(huì)導(dǎo)致回溯并導(dǎo)致引擎花費(fèi)過(guò)多的時(shí)間來(lái)嘗試匹配字符串,從而更容易受到 DoS
攻擊。
另一方面,使用*
使子模式成為可選,這意味著如果不匹配,正則表達(dá)式引擎可以完全跳過(guò)它。這減少了引擎需要探索的可能路徑的數(shù)量。
回溯如何導(dǎo)致性能問(wèn)題
回溯可能會(huì)通過(guò)兩種方式導(dǎo)致性能問(wèn)題:
- 超線性運(yùn)行時(shí)間:回溯可能會(huì)導(dǎo)致正則表達(dá)式模式的運(yùn)行時(shí)間變得超線性,這意味著匹配模式所需的時(shí)間增長(zhǎng)速度快于輸入字符串的長(zhǎng)度。這可能會(huì)使該模式對(duì)于長(zhǎng)輸入字符串極其緩慢,并且如果將該模式應(yīng)用于不受信任的用戶輸入,則可能會(huì)導(dǎo)致
DoS
攻擊。 - 高內(nèi)存使用量:回溯還會(huì)導(dǎo)致正則表達(dá)式引擎使用大量?jī)?nèi)存,特別是當(dāng)模式包含嵌套的可選或重復(fù)的子模式時(shí)。這可能會(huì)導(dǎo)致應(yīng)用程序內(nèi)存不足并崩潰。
如何防止正則表達(dá)式模式中的回溯
為了防止正則表達(dá)式模式中的回溯,我們需要以避免可選或重復(fù)子模式的方式設(shè)計(jì)思路。以下是我們可以使用的一些技巧:
使用特定的字符類:
使用特定的字符類可以通過(guò)限制可以匹配子模式的字符數(shù)來(lái)幫助防止回溯。例如,/[a-z]/
匹配從 a
到 z
的任何小寫(xiě)字母。
使用非捕獲組
使用非捕獲組可以通過(guò)避免不必要的內(nèi)存分配來(lái)幫助防止回溯。例如,/(?:ab)+/
匹配字符串ab
的一次或多次出現(xiàn),而不創(chuàng)建捕獲組。
使用原子組
使用原子組可以通過(guò)使子模式成為非可選來(lái)幫助防止回溯。例如,/a(?>b|c)/
匹配包含字母a
后跟b
或c
的字符串,而不進(jìn)行回溯。
使用多個(gè)子模式而不將其中任何一個(gè)設(shè)為可選
使用多個(gè)子模式而不將其中任何一個(gè)設(shè)為可選可以通過(guò)限制正則表達(dá)式引擎需要探索的可能路徑的數(shù)量來(lái)幫助防止回溯。例如,/^(ab|cd|ef)$/
匹配ab
、cd
或ef
字符串,而不進(jìn)行回溯。
使用所有格子模式:
使用所有格子模式可以通過(guò)使子模式成為非可選來(lái)幫助防止回溯。所有格子模式由語(yǔ)法(?+...
)表示。例如,/a(?+b)/
匹配包含字母a
后跟字母b
的字符串,而不進(jìn)行回溯。
使用惰性量詞:
使用惰性量詞可以通過(guò)使子模式可選來(lái)幫助防止回溯,但仍然可以防止回溯。惰性量詞由+?or*?
符號(hào)表示。例如,/a+?/
匹配一??次或多次出現(xiàn)的字母a
,但使用惰性量詞來(lái)防止回溯。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-651808.html
使用有界量詞:
使用有界量詞可以通過(guò)限制子模式的重復(fù)次數(shù)來(lái)幫助防止回溯。有界量詞由語(yǔ)法{min,max}
表示,其中min
和max
是指定最小和最大重復(fù)次數(shù)的整數(shù)。例如,/a{1,3}/
匹配包含重復(fù)一到三次的字母a
的字符串,而不回溯。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-651808.html
到了這里,關(guān)于防止 JavaScript 中的正則表達(dá)式回溯的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!