PHP弱類型漏洞學習


簡介

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
View Code

 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('登陸失敗!');
}
View Code

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('登陸失敗!');
}
?>
View Code

 避免bool比較可以使用三個等號作比較即可。

數字轉換比較缺陷

當賦值給PHP變量的整型超過PHP的最大值PHP_INT_MAX時,PHP將無法計算出正確的結果,攻擊者可能會利用其跳過某些校驗邏輯,如密碼校驗、賬號充值校驗等

<?php 
$a=98869694308861098395599991222222222222;
$b=98869694308861098395599992999999999999;

var_dump($a===$b);


?>
View Code

 再實際的業務邏輯中,一定要對最大值進行限制,避免數據越界而導致錯誤的執行結果。

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';
}

?>

  
View Code

 

 最終輸出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));
    
?>
View Code

 

 

 

 

2222

參考學習:《php安全之道》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM