关于php弱类型的一些笔记

本文探讨了PHP中不同类型的转换规则,特别是在比较运算符和某些函数中的行为,包括松散与严格比较的区别、switch语句的行为、in_array函数的用法、is_numeric函数的安全隐患以及md5函数在特定情况下的绕过技巧。

1.当比较运算时,会先转换类型,再进行比较,当一个字符串被转换为数值比较时,如果字符串的开始不包含’0e‘,’0x‘等特殊字符,其数值为开头数字表示的数值,如果字符串开头不为数字,则会转换为0,而如果开头包含0e,则会按照科学计数法计算,即两个0e开头的字符串会被认为相等。当有0x开头的字符串,则会转换为十六进制进行比较。如下:

<?php
if("0x1046a" == 66666){
	echo 'yes';
}
else{
	echo 'no';
}
?>

这样比较,返回结果总为’yes‘。
上述例子均为松散比较,当转换为===即严格比较时,上述大部分的比较不会为真,因为严格比较并不会将比较对象转换为同一类型。
2.部分函数在判断时,也会有松散性。
switch

<?php
$a = $_GET['id'];
switch($a){
	case 1:{
	echo '1';
	break;
	}
	case 2:{
	echo '2';
	break;
	}
	case 3:{
	echo '3';
	break;
	}
}
?>

当id=1sadkj时,会返回1,也就是switch内的参数,会转换为数字型。
in_array()
in_array(search,array,type),search参数时被搜索参数,array时需要检索的数字,type为检索类型,当在array中有search参数,则返回true,而当type为空时,检索时为松散比较,当type为true时,检索为严格比较。如下

<?php
$a = $_GET['id']; 
if(in_array($a,array(1,2,3,4))){
	echo 'true';
}
else{
	echo 'false';
}
?>

当传入的id为1awd时,会返回true,当将type改为true时,则会返回false,同时,如果id=1,那么也会返回false,因为get传入的参数均是字符串。
is_numeric
该函数用于判断参数是否为数字,这里的判断同样是松散比较,因此传入十六进制的字符串可以进行绕过,而这个函数的漏洞有时可以进行二次注入,当后端对传入的数据通过该函数进行验证时,就可以将恶意语句进行十六进制编码,而十六进制的数据在储存进数据库时,会进行解码,将恶意语句存入数据库,如果代码未对取出的数据进行校验,就会造成二次注入。
strcmp
该函数会比较传入的两个字符串,如果值相等,就会返回0,str1>str2,返回>0,str1<str2时,返回<0。在5.3及以后的php版本中,比较的如果是数组和字符串,也会返回0。
md5
该函数用于返会字符串的md5值,而由于数组无法计算md5值,会返回null,因此两个数组的md5值进行比较会返回true。而有些字符串转换为md5后,为0e开头,在比较时会转换为科学计数法,也可以绕过一些防护。如下为一些md5值0e开头的字符串:
QNKCDZO s878926199a s155964671a s214587387a s878926199a s1091221200a
而在做题时,遇到了一种md5验证的题,部分源码如下:

 <?php
$string_1 = $_GET['str1']; 
$string_2 = $_GET['str2'];
        if(is_numeric($string_1)){ 
            $md5_1 = md5($string_1); 
            $md5_2 = md5($string_2); 
            if($md5_1 != $md5_2){ 
                $a = strtr($md5_1, 'cxhp', '0123'); 
                $b = strtr($md5_2, 'cxhp', '0123'); 
                if($a == $b){
                    echo 'flag';
                }
                else {
                    die('you are close');
                }
}
		}
?>

代码大意为找一个数字,它的MD5值与另一个参数的MD5值进行比较,如果相等则返回flag,做这道题时,是在网上找到的代码,如下:

<?php
$count = 0;
for ($i = 1; $i <= 100000000; $i++) {
    $md5 = strtr(md5($i), 'cxhp', '0123');
    if (preg_match('/^0e\d+$/', $md5)) {
        echo $i . " " . md5($i) . "<br>";
        $count++;
    }
    if ($count == 2) {
        break;
    }
}

该代码会生成两个0e开头的数字,将这两个数字作为参数传入,即可得到flag。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值