php 正则 回溯,PHP正则匹配绕过
之前沒有從機制上去了解過PHP正則匹配繞過具體是怎么一回事,于是主動去網上找了一些資料來加深理解
NFA與正則表達式
常見的正則引擎,被細分為DFA(確定性有限狀態自動機)與NFA(非確定性有限狀態自動機)。
由于NFA的執行過程存在回溯,所以其性能會劣于DFA,但它支持更多功能。大多數程序語言都使用了NFA作為正則引擎,其中也包括PHP使用的PCRE庫。所以這里詳細介紹一下NFA(Nondeterministic Finite Automaton),非確定有限狀態自動機。
對于正則表達式 ab|ac,對應 NFA 可以是這樣的:
可以看到,在狀態 1 這里,如果輸入 a,其實有兩種可能,如果后面的符號是 b,那么可以匹配成功,后面符號是 c 也能匹配成功。所以狀態機在執行過程中,可能要嘗試所有的可能性。在嘗試一種可能路徑匹配失敗后,還要回到之前的狀態再嘗試其他的路徑,這就是“回溯”。
所以有限狀態機的工作過程,就是從起始狀態開始,一個字符一個字符地讀取輸入串,并與正則表達式進行匹配,如果匹配不上,則進行回溯,嘗試其他狀態。
回溯的具體流程
設正則為].*,假設匹配的輸入是<?php phpinfo();//aaaaa,執行的流程如下:
分析
① 第4步,第一個.*指可以匹配任何字符,所以最終匹配到輸入串的結尾,即//aaaaa
② 第5步,因正則.*后還有字符[(`;?>],NFA開始回溯,一個一個a地吐出
③ 第12步,最終吐出;,此時.*匹配的是<?php phpinfo(),而后面的;匹配上[(`;?>],結果滿足正則表達式的要求,于是不再回溯
④ 第13步往后匹配;
⑤ 第14步匹配.*,此處的.*匹配到了字符串末尾,匹配結束
在正則表達式調試的過程中,吐字符的過程就是相當于NFA的回溯,由此得知上面總共回溯了8次,為第5-12步。
對PHP正則的回溯次數限制的利用
PHP為了防止正則表達式的拒絕服務攻擊(reDOS),給pcre設定了一個回溯次數上限pcre.backtrack_limit,次數由PHP5.3.7 版本之前默認值為 10萬 ,到PHP5.3.7 版本之后默認值為 100萬 ,該值可以通過php.ini設置,也可以通過 phpinfo 頁面或var_dump(ini_get('pcre.backtrack_limit'));查看。
利用
PHP手冊告訴我們, preg_match 函數的返回值有3種,分別為(安全的寫法是使用 === 運算符對返回值進行比較,手冊推薦用效率更快的 strpos 函數替代 preg_match 函數):returns 1; // 如果匹配到.
returns 0; // 如果未匹配到.
returns FALSE; // 發生錯誤時.
假設我們的回溯次數超過了100萬,會出現什么現象呢?比如:php > var_dump(preg_match('/].*/is','<?php phpinfo();//'.str_repeat('c',1000000)));
bool(false)
可見,preg_match返回的非1和0,而是false
我們通過上述技巧繞過 preg_match 函數,通過發送超長字符串的方式,使正則執行失敗,最后繞過目標對PHP語言的限制。
相關
總結
以上是生活随笔為你收集整理的php 正则 回溯,PHP正则匹配绕过的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 奇瑞星途瑶光车型 OTA 升级:新增第二
- 下一篇: php root 启动,php-fpm如