湖南衡陽網(wǎng)站建設(shè)怎么樣優(yōu)化網(wǎng)站seo
正則繞過
- 正則表達(dá)式
- PHP正則回溯
- PHP中的NULL和false
- 回溯案例
- 案例1
- 案例2
正則表達(dá)式
在正則中有許多特殊的字符,不能直接使用,需要使用轉(zhuǎn)義符\。如:$,(,),*,+,.,?,[,,^,{。
這里大家會有疑問:為啥小括號(),這個就需要兩個來轉(zhuǎn)義,但是中括號[]和大括號{}僅轉(zhuǎn)義左側(cè)。這樣的原因是,()存在一個特殊含義:組,而中括號和大括號,沒有左側(cè)就無法實(shí)現(xiàn)閉合,也就無法編譯。
當(dāng)然里面也存在一個特殊符號“-”,也是不需要轉(zhuǎn)義的,起到連接符的作用,主要使用在[]中,當(dāng)做普通文本即可。
除了一些特殊字符,還有一些特殊符號的表示,像:\d,\D,\s,\S,\w,\W,\b,\B。
還存在一些機(jī)制,像貪婪匹配,惰性匹配,又比如存在斷言,像:先行肯定斷言、先行否定斷言。這里就不多說了。
PHP正則回溯
回溯,可以簡單理解為返回,也就是在正則匹配時,依次匹配,如果產(chǎn)生不滿足正則表達(dá)式的情況,則向前依次返回搜索,知道匹配到為止,否則,正則無法匹配。
舉個例子:
匹配正則:/\d.*g.*/gm
正則表達(dá)的含義:首先匹配\d,也就是先數(shù)字匹配,然后是.*,全部匹配,匹配字母g,再全部匹配。
我們的案例給這個:1234as23gsfggsw,正常理解應(yīng)該2步差不多了。
我們在regex101.com查看一下具體匹配了幾步。
這里匹配了八步。
看一下第三步:
和我們想的差不多基本已經(jīng)匹配完了,但是這個正則沒有走完,也就是說它回去匹配字母g,再來看一下后面兩步。
開始了我們前面提到的回溯,開始從后往前匹配內(nèi)容,也就是字母g,在匹配到后,就會再向后匹配正則表達(dá)式。
在PHP中,回溯不是無限的,也就是說回溯步數(shù)是有限制的,根據(jù)英文文檔顯示可以回溯1000000次,這是一個很大的數(shù)字。
PHP中的NULL和false
作為弱數(shù)據(jù)型語言,php的比較還是比較特殊的。
PHP存在嚴(yán)格比較和松散比較。嚴(yán)格比較也就是“===”,松散比較“==”。
松散比較,比較的僅是數(shù)據(jù)的值。
嚴(yán)格比較,比較的是數(shù)據(jù)的值和類型。
PHP下,也存在一些隱式轉(zhuǎn)換,將NULL和false進(jìn)行轉(zhuǎn)換
下面就展示一下NULL和false的比較
0 == false: bool(true)
0 === false: bool(false)0 == null: bool(true)
0 === null: bool(false)false == null: bool(true)
false === null: bool(false)"0" == false: bool(true)
"0" === false: bool(false)"0" == null: bool(false)
"0" === null: bool(false)"" == false: bool(true)
"" === false: bool(false)"" == null: bool(true)
"" === null: bool(false)
很明顯,在嚴(yán)格模式下,NULL和false相同。
回溯案例
案例1
<?php
function areyouok($greeting){return preg_match('/Merry.*Christmas/is',$greeting); //正則匹配
}if(!areyouok($greeting)){if(strpos($greeting,'Merry Christmas') !== false){ echo 'welcome to nanhang. '.'flag{i_Lov3_NanHang_everyThing}';}else{echo 'Do you know .swp file?';}
}else{echo 'Do you know PHP?';
}
分析一下內(nèi)容:首先第一個函數(shù)里面是一個正則匹配,正則匹配的內(nèi)容是:Merry,然后任意字符,然后是Christmas。
來到下面的判斷,先判斷是否符合上面的正則,不符合,進(jìn)入下一層,否則返回打印,然后,又判斷。
這里有意思的兩個點(diǎn)是在判斷上,第一個判斷是否符合正則,正則則是一個字符串,不符合進(jìn)入下一個,而下一個則判斷字符串包不包含括號里的內(nèi)容,還要和false進(jìn)行嚴(yán)格比較。也就是說呢,要不是字符串,還要和false不完全等。
首先大家想到的是,第二個判斷為true就好了,但如果滿足的話,那就必須是字符串,但第一個判斷已經(jīng)否定了。
理論成立,但仍需要實(shí)測,
首先字符串
所以,這時候我們就要想到我們的NULL和false,它們兩個在嚴(yán)格比較下是相等的。
那這樣要如何解決,那greeting就不能為字符串,且要為NULL,數(shù)字就可以。
所以,greeting[]=123,就解決了。
案例2
<?php
function areyouok($greeting){return preg_match('/Merry.*Christmas/is',$greeting);
}$greeting=@$_POST['greeting'];
if(!is_array($greeting)){if(!areyouok($greeting)){if(strpos($greeting,'Merry Christmas') !== false){echo 'Merry Christmas. '.'flag{i_Lov3_NanHang_everyThing}';}else{echo 'Do you know .swp file?';}}else{echo 'Do you know PHP?';}
} else {echo 'fuck array!!!';
}
?>
這個案例是上面的升級版,在這里就沒有辦法,使用NULL,來實(shí)現(xiàn)繞過了,這里對數(shù)組也進(jìn)行了判斷,難度可見一斑。
但是我們要想到一個問題,如果我們無法匹配正則,那就繞過,不就可以了。
上面我們提到了,PHP也就只能回溯1000000次,多了就不行了,如果超了,正則就匹配失敗,也是滿足我們判斷條件的,所以,我們只需要在字符串加一些不相干的內(nèi)容,一直回溯,超過1000000次就可以了。
所以,此時的greeting=Merry Christmas + ‘a(chǎn)’*1000000。