如何防止JavaScript中的正則表達(dá)式回溯
正則表達(dá)式是用于在軟件應(yīng)用程序中操作和驗(yàn)證文本的強(qiáng)大工具。然而,某些正則表達(dá)式模式可能容易受到回溯的影響,這可能會(huì)導(dǎo)致超線性運(yùn)行時(shí),并可能導(dǎo)致DoS攻擊。在本文中,我們將探討什么是回溯、它如何導(dǎo)致性能問題以及如何在正則表達(dá)式中防止回溯。
正則表達(dá)式中的回溯是什么
回溯是正則表達(dá)式引擎用來處理包含可選或重復(fù)子模式的復(fù)雜模式的技術(shù)。當(dāng)正則表達(dá)式模式包含可選或重復(fù)的子模式時(shí),引擎可能需要嘗試子模式的多種組合才能找到匹配項(xiàng)。這個(gè)過程稱為回溯。
例如,有以下正則表達(dá)式:
/^[a-zA-Z0-9\s]+$/
此正則表達(dá)式應(yīng)匹配僅包含字母數(shù)字字符和空格的任何字符串。然而,它很容易受到回溯的影響,因?yàn)?code>+字符類后面的運(yùn)算符允許字符類的任意數(shù)量的重復(fù)。
攻擊者可以通過發(fā)送包含一長串不匹配字符的惡意搜索查詢來利用此漏洞,例如:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
該字符串包含 30 個(gè)a
字符,后跟一個(gè)b
. 當(dāng)正則表達(dá)式引擎嘗試匹配該字符串時(shí),它將前 30 個(gè)a
字符與字符類匹配,但無法匹配b
字符。然后,引擎將回溯并嘗試字符類的不同組合,直到匹配整個(gè)字符串或耗盡所有可能的組合。
在本例中,字符串中有 31 個(gè)字符,因此有 2 種可能的字符類組合可供嘗試。這可能需要很長的時(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)過多的時(shí)間來嘗試匹配字符串,從而更容易受到 DoS
攻擊。
另一方面,使用*
使子模式成為可選,這意味著如果不匹配,正則表達(dá)式引擎可以完全跳過它。這減少了引擎需要探索的可能路徑的數(shù)量。
回溯如何導(dǎo)致性能問題
回溯可能會(huì)通過兩種方式導(dǎo)致性能問題:
- 超線性運(yùn)行時(shí)間:回溯可能會(huì)導(dǎo)致正則表達(dá)式模式的運(yùn)行時(shí)間變得超線性,這意味著匹配模式所需的時(shí)間增長速度快于輸入字符串的長度。這可能會(huì)使該模式對于長輸入字符串極其緩慢,并且如果將該模式應(yīng)用于不受信任的用戶輸入,則可能會(huì)導(dǎo)致
DoS
攻擊。 - 高內(nèi)存使用量:回溯還會(huì)導(dǎo)致正則表達(dá)式引擎使用大量內(nèi)存,特別是當(dāng)模式包含嵌套的可選或重復(fù)的子模式時(shí)。這可能會(huì)導(dǎo)致應(yīng)用程序內(nèi)存不足并崩潰。
如何防止正則表達(dá)式模式中的回溯
為了防止正則表達(dá)式模式中的回溯,我們需要以避免可選或重復(fù)子模式的方式設(shè)計(jì)思路。以下是我們可以使用的一些技巧:
使用特定的字符類:
使用特定的字符類可以通過限制可以匹配子模式的字符數(shù)來幫助防止回溯。例如,/[a-z]/
匹配從 a
到 z
的任何小寫字母。
使用非捕獲組
使用非捕獲組可以通過避免不必要的內(nèi)存分配來幫助防止回溯。例如,/(?:ab)+/
匹配字符串ab
的一次或多次出現(xiàn),而不創(chuàng)建捕獲組。
使用原子組
使用原子組可以通過使子模式成為非可選來幫助防止回溯。例如,/a(?>b|c)/
匹配包含字母a
后跟b
或c
的字符串,而不進(jìn)行回溯。
使用多個(gè)子模式而不將其中任何一個(gè)設(shè)為可選
使用多個(gè)子模式而不將其中任何一個(gè)設(shè)為可選可以通過限制正則表達(dá)式引擎需要探索的可能路徑的數(shù)量來幫助防止回溯。例如,/^(ab|cd|ef)$/
匹配ab
、cd
或ef
字符串,而不進(jìn)行回溯。
使用所有格子模式:
使用所有格子模式可以通過使子模式成為非可選來幫助防止回溯。所有格子模式由語法(?+...
)表示。例如,/a(?+b)/
匹配包含字母a
后跟字母b
的字符串,而不進(jìn)行回溯。
使用惰性量詞:
使用惰性量詞可以通過使子模式可選來幫助防止回溯,但仍然可以防止回溯。惰性量詞由+?or*?
符號表示。例如,/a+?/
匹配一??次或多次出現(xiàn)的字母a
,但使用惰性量詞來防止回溯。
使用有界量詞:
使用有界量詞可以通過限制子模式的重復(fù)次數(shù)來幫助防止回溯。有界量詞由語法{min,max}
表示,其中min
和max
是指定最小和最大重復(fù)次數(shù)的整數(shù)。例如,/a{1,3}/
匹配包含重復(fù)一到三次的字母a
的字符串,而不回溯。
到此這篇關(guān)于如何防止JavaScript中的正則表達(dá)式回溯的文章就介紹到這了,更多相關(guān)JavaScript 正則表達(dá)式回溯內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript超詳細(xì)實(shí)現(xiàn)網(wǎng)頁輪播圖
這篇文章主要介紹了JavaScript超詳細(xì)實(shí)現(xiàn)網(wǎng)頁輪播圖,我們經(jīng)常會(huì)看到各種輪播圖的效果,它們到底是怎樣實(shí)現(xiàn)的呢?今天我們就一起來看一下具體實(shí)現(xiàn)方法吧2021-12-12tangram.js庫實(shí)現(xiàn)js類的方式實(shí)例分析
這篇文章主要介紹了tangram.js庫實(shí)現(xiàn)js類的方式,結(jié)合實(shí)例形式分析了tangram.js庫實(shí)現(xiàn)類的創(chuàng)建、繼承等相關(guān)操作技巧,需要的朋友可以參考下2018-01-01基于JavaScript實(shí)現(xiàn)飄落星星特效
這篇文章主要為大家詳細(xì)介紹了基于JavaScript實(shí)現(xiàn)飄落星星特效,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08ES6基礎(chǔ)之 Promise 對象用法實(shí)例詳解
這篇文章主要介紹了ES6基礎(chǔ)之 Promise 對象用法,結(jié)合實(shí)例形式詳細(xì)分析了ES6中 Promise 對象功能、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-08-08JS實(shí)現(xiàn)二維數(shù)組橫縱列轉(zhuǎn)置的方法
下面小編就為大家分享一篇JS實(shí)現(xiàn)二維數(shù)組橫縱列轉(zhuǎn)置的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04JavaScript實(shí)現(xiàn)點(diǎn)擊出現(xiàn)子菜單效果
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)點(diǎn)擊出現(xiàn)子菜單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-02-02