PHP弱类型

== 和 === 的区别

强类型比较:===
强类型比较在进行比较的时候,会先判断两种字符的类型是否相等,在比较数值

弱类型比较:==
弱类型比较在进行比较的时候,会先将字符串类型转换成相同的类型,再比较,中间有一个强转的过程(优先转换为数字类型) —重点

在弱比较(=)如果比较一个数字和字符串 或者 比较涉及到数字内容的字符串,首个字符串值会被转换成数值,并按照数值来进行比较

1
2
3
4
5
6
<?php
var_dump("admin"==0); //Ture
var_dump("2admin"==1); //Flas
var_dump("admin" == 2);//Flas
var_dump("admin" ==0);//True
var_dump("0e123456"=="0e654321");//True

注意

  • 当数字在前时后面的字母便会转换成数值型,为0

  • 当字母在前,数字在后时字母将无法转换成数字型,会直接当成字符串类型

1、和布尔型比较

在布尔值之间进行比较的时候,0 和 ‘’ 空字符串,都代表false,' ',非空的字符串,代表非false

1
2
3
4
<?php
var_dump(0==false);//Ture
var_dump(''==false);//True
var_dump(' '==false);//False 有空格意味着非空

2,单引号0意味着等于空

思考: 为什么会存在‘0’和 布尔值之间的比较

总结:’0’ 字符串’0’ “0”等于空等于false

3、‘0’等于 ‘ ’二者又不相等

注意以前: ‘’ 引号里面没有内容,代表false, ‘0’引号里面有个0,也代表false

奇怪的特性死记硬背

当‘0’单引号0和 别的数据相比较时,‘0’单引号0意味着等于‘’空 等于false
但是‘0’单引号和‘’空相比较时,他们二者又不相等

1
2
3
<?php
var_dump('0'==false);//Ture 单引号‘0’ 意味着等于空,空等于false,所以结果为Ture
var_dump(''=='0');//False ‘’ 这个也等于空,‘0’这个也等于空,但是二者相比较时,二者又不相等,所以结果为False
1
2
'0' == 0 //true  
'0'=='' //false

4、0e开头的字符串比较hash值比较

在进行比较运算时,如果遇到了0e这类字符串,PHP会将它解析为科学计数法。

PHP它把每一个以”0E”开头的哈希值都解释为0,

如果两个不同的数据参数值经过哈希以后,其哈希值都是以”0E”开头的,那么PHP将会认为他们相同,都是0

1
2
<?php
var_dump("0e1234" == "0e4567"); // true

哈希值0e开头的,不同密码值

1
2
3
4
5
6
7
8
9
0e开头的md5和原值:
QNKCDZO
0e830400451993494058024219903391
240610708
0e462097431906509019562988736854
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469

5、0x开头的字符串比较

在进行比较运算时,如果遇到了0x这类字符串,PHP会将它解析为十六进制

所谓的弱类型比较漏洞,也就在在进行比较判断下一步执行行为的时候,可以利用该漏洞,实现一个
最终结果为真的 一个 返回值

1
2
<?php
var_dump("0x1046a" == "66666" ); // true

6、in_array

重点:函数搜索 比较的时候,是有可能存在弱类型比较漏洞的

1
2
3
4
5
6
7
8
9
10
<?php
$arr1 = array("hello","nihao","wohao") ;
$brr1 = "hello";

if(in_array($brr1,$arr1)){
echo "在数组中";
}else{
echo "不在数组中";
}
//输出:在数组中

关键在于in_array的第三个参数:

  • true 代表=== 强类型比较
  • false 代表== 弱类型比较

默认为false

1
2
3
4
5
6
7
8
9
10
<?php
$arr1 = array(0,"nihao","wohao") ;
$brr1 = "hello";

if(in_array($brr1,$arr1)){
echo "在数组中";
}else{
echo "不在数组中";
}
//输出:在数组中

7、strcmp()字符串比较 -Ascii码

1
2
3
4
5
6
7
8
9
注意:此比较区分大小写
用途:比较括号内的两个字符串string1和string2的大小
语法:strcmp(string $string1, string $string2): int
返回:
str1等于str2时候,返回0
str1大于str2时候,返回1
str1小于str2时候,返回-1

略记: strcmp -二进制安全字符串比较

在5.3及以后的php版本中,当strcmp()括号内是一个数组与字符串比较时,也会返回0。

结论:进行字符串进行比较的时候,比较的是,第1个字符的值,第1个字符的值,决定了整个比较结果

进行比较的时候,只比较字符串,只比较ascii码,含有特殊意义的字符,也只会被认为是字符,并不会具有特殊意义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$a ='abc';
$c = 'dbc';
echo strcmp($a,$c);//-1
echo "<br>";

$a ='abc';
$c = 'Abc';
echo strcmp($a,$c);//1
echo "<br>";

$a ='abc';
$c = 'abc';
echo strcmp($a,$c);//0

ASCII码对照表

8、MD5比较–利用条件苛刻

注意:在进行 MD5 弱类型比较漏洞利用的时候,必须是对方也使用了MD5(数组)的情况下,才有可能利用成功

用途:计算字符串的 MD5 散列值

当你传递一个array时,md5()不会报错,只是会无法正确地求出array的md5值,返回null,
这样就会导致任意2个array的md5值都会相等。

1
2
3
4
5
6
7
8
9
<?php
$a = array("abcde");
$b = array("qwerio");
if ($a != $b && md5($a) == md5($b)){
echo '比较的值相等';
}else{
echo '比较的值不相等';
}
//输出:比较值相等

9、Json_decode相关的弱类型比较

注意:变量不变量并不重要,重要的是,我们可以通过key,取到对应的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//json_decode变量存在的证明
<?php
$a="ssss";//字符串类型的 4个s

//$b="ssss"
// {key1:value1, key2:value2,key3:value3}
// 'xxx' "xxx"
//"{key1:value1}" '{key1:value1}'
$message = json_decode('{"b":"ssssb"}'); // object 对象
if($a === $message->b)//"ssss"
{ //强类型证明变量a的存在
echo "ok";
}else{
echo "no";
}

//返回值:obj 和 array 的证明
<?php
$json_str = '{"a":1,"b":2,"c":3}';
$ret =json_decode($json_str,true);
var_dump($ret);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
$a="admin";//1、这是程序要比较的值,这个值对于攻击者而言是不可知的

if (isset($_GET['message']))//3、最终payload message={"key":0}
{
$message = json_decode($_GET['message']);//将json格式的key value,转换成变量$key=value ==> $message=sss
if ($message->key == "admin"){
exit();
}
if ($message->key == $a)
{//2、但是没有关系,因为这里用的是两个等号,弱类型比较,只需要利用比较逻辑,就可以让其实现相等
//也就是可以利用0=="admin"这种形式绕过

echo '你比较的值二者相等';//目的输出ok
}
else{
echo '失败';
}
}
//输出:你比较的值二者相等

10、Array_search弱类型

array_search — 在数组中搜索给定的值,如果成功则返回首个相应的键名,也是通过 == 进行比较的

1
2
3
4
5
6
<?php
$array = array(0 => 'blue', 1 => 'red', 2 => 'green', 3 => 'red');

$key = array_search('green', $array); // $key = 2;
$key = array_search('red', $array); // $key = 1;
?>
1
2
3
4
<?php
$a=array("a"=>"llll","b"=>0,"c"=>"blue");
echo array_search("red",$a); //返回键名b
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
if (!is_array($_GET['cmd'])){
die();
}
$cmd = $_GET['cmd'];
for($i = 0; $i < count($cmd); ++$i){
if($cmd[$i] === 'admin'){
echo 'no';
die();
}
$cmd[$i] = intval($cmd[$i]);
}

if (array_search('admin', $cmd) === 0){

echo 'flag';
}
else{
echo 'no, you failed';
}

//paylaod: cmd[]=0

11、Switch比较缺陷

//本质上switch 做了一个弱类型比较 //$a==’hello’?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
$a = 0;
//本质上switch 做了一个弱类型比较
//$a=='hello'
switch ($a){
case 'hello':
echo 'hello';
break;
case 0:
echo 0;
break;
default:
echo '没找到';
}