簡介
PHP在使用雙等號(==)判斷的時候,不會嚴格檢驗傳入的變量類型,同時在執行過程中可以將變量自由地進行轉換類型。由於弱數據類型的特點,在使用雙等號和一些函數時,會造成一定的安全隱患
eg:
<?php var_dump("admin"==0); //true var_dump("1admin"==1); //true var_dump("admin1"==1); //false var_dump("admin1"==0); //true var_dump("0e123456"=="0e4456789"); //true ?>
== 在進行比較的時候,會先將字符串類型轉化成相同,再比較
=== 在進行比較的時候,會先判斷兩種字符串的類型是否相等,再比較
Hash比較缺陷
研發人員在對比Hash2字符串的時候常常用到等於、不等於(!=)進行比較。如果Hash值以0e開頭,后面都是數字,當與數字進行比較時,就會被解析成0x10n,會被判與0相等,攻擊者可以繞過某些系統邏輯
PHP在處理哈希字符串時,會利用”!=”或”==”來對哈希值進行比較,它把每一個以”0E”開頭的哈希值都解釋為0,所以如果兩個不同的密碼經過哈希以后,其哈希值都是以”0E”開頭的,那么PHP將會認為他們相同,都是0。
攻擊者可以利用這一漏洞,通過輸入一個經過哈希后以”0E”開頭的字符串,即會被PHP解釋為0,如果數據庫中存在這種哈希值以”0E”開頭的密碼的話,他就可以以這個用戶的身份登錄進去,盡管並沒有真正的密碼。
<?php var_dump("0e123456789012345678901234567890"==="0"); //false var_dump("0e123456789012345678901234567890"=="0"); //true ?>
加密后為0E的字符

QNKCDZO 0e830400451993494058024219903391 s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 s214587387a 0e848240448830537924465865611904 s214587387a 0e848240448830537924465865611904 s878926199a 0e545993274517709034328855841020 s1091221200a 0e940624217856561557816327384675 s1885207154a 0e509367213418206700842008763514 s1502113478a 0e861580163291561247404381396064 s1885207154a 0e509367213418206700842008763514 s1836677006a 0e481036490867661113260034900752 s155964671a 0e342768416822451524974117254469 s1184209335a 0e072485820392773389523109082030 s1665632922a 0e731198061491163073197128363787 s1502113478a 0e861580163291561247404381396064 s1836677006a 0e481036490867661113260034900752 s1091221200a 0e940624217856561557816327384675 s155964671a 0e342768416822451524974117254469 s1502113478a 0e861580163291561247404381396064 s155964671a 0e342768416822451524974117254469 s1665632922a 0e731198061491163073197128363787 s155964671a 0e342768416822451524974117254469
CTF例題
<?php $pass=$_GET['password']; $password='0e342768416822451524974117254469'; if (md5($pass)==$password) { echo "flag{xx-xx-xxxx-xiaohua}"; }else{ echo "error"; } ?>
payload:
http://127.0.0.1/index.php?password=s1885207154a
預防方案 :
PHP5.6以上使用hash_equals()函數比較Hash值,可以避免對比惡意繞過
低於5.6可用可以實現的函數解決
參考學習:https://www.freebuf.com/news/67007.html
bool比較缺陷
在使用json_decode()函數或使用unserialize()函數時,部分結構被解釋成bool類型,也會造成缺陷。
json_decode漏洞代碼:

<?php $str='{"user":true,"pass":true}'; $data=json_decode($str,true); if($data['user']=='root' && $data['pass']=='myPass'){ print_r('登陸成功 獲得flag{xx-ssss-xiaohua}'); }else{ print_r('登陸失敗!'); }
unserialize漏洞代碼:

<?php $str='a:2:{s:4:"user";b:1;s:4:"pass";b:1;}'; $data=unserialize($str); if($data['user']=='root' && $data['pass']=='myPass'){ print_r('登陸成功 獲得flag{xx-ssss-xiaohua}'); }else{ print_r('登陸失敗!'); } ?>
避免bool比較可以使用三個等號作比較即可。
數字轉換比較缺陷
當賦值給PHP變量的整型超過PHP的最大值PHP_INT_MAX時,PHP將無法計算出正確的結果,攻擊者可能會利用其跳過某些校驗邏輯,如密碼校驗、賬號充值校驗等

<?php $a=98869694308861098395599991222222222222; $b=98869694308861098395599992999999999999; var_dump($a===$b); ?>
再實際的業務邏輯中,一定要對最大值進行限制,避免數據越界而導致錯誤的執行結果。
switch比較缺陷
當再switch中使用case判斷數字時,switch會將其中的參數轉換為int類型進行計算

<?php $num='2xiaohua'; switch($num){ case 0:echo '000000'; break; case 1:echo '1111'; break; case 2:echo '2222222'; break; case 3:echo '333333'; } ?>
最終輸出2222
數組比較缺陷
當使用in_array()或array_search()函數時,如果$strict參數嗎有設置為true,則in_array()或array_search()將使用松散來判斷$needle是否存在$haystack中
bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )//strict默認為false miixed array_search( mixed $needle , array $haystack [, bool $strict = FALSE ] )//strict默認為false
漏洞代碼:

<?php $array=[0,1,2,'3']; var_dump(in_array('abc',$array)); var_dump(array_search('abc',$array)); ?>
2222
參考學習:《php安全之道》