R0ot's Blog

分享代码,记录生活

0%

PHP弱类型比较绕过

简介

PHP是一种弱类型语言,这意味着变量的类型是根据上下文自动推断的,不需要强调声明(如c语言),带来方便的同时,也带来了许多安全隐患
PHP的比较也分为弱类型(==)比较和强类型(===)比较,还有(!=)和(!==)

md5比较绕过

在ctf赛题中,经常会出现类似于这样的一段代码,要求我们传入两个参数的值不同,而md5()后的值相同

1
2
3
4
5
$a=$_GET['a'];
$b=$_GET['b'];
if ($a!=$b && md5($a) ==md5($a)){
echo 'ok!!';
}

0e等于0绕过

一个字符串经过md5处理后如果是以0e开头的,那么在php中就会被认为是科学计数法表示的数字(在科学计数法中,eE用于表示指数。例如,数字300可以表示为3e23E2,意思是3 × 10^2同样,数字0.003可以表示为 3e-33E-3,意思是 3 × 10^-3),也就是说0e开头的表示的数字为0 × 10^n都为0,这样一来,就可以成功绕过比较

下面是常见的md5后为0e开头的字符串
QNKCDZO =>md5 0e830400451993494058024219903391
s878926199a =>md5 0e545993274517709034328855841020
0e215962017 =>md5 0e291242476940776845150308577824

需要注意的是,这种绕过手法只适用于弱类型比较,强类型比较是不能使用这种方式的
还有一种题目,是上面题目的变种,希望传入参数的值与其本身md5()处理过的值相同

1
2
3
4
$a=$_GET['a'];
if($a==md5($a)){
echo 'ok!!';
}

这里只要一个字符是以0e开头,md5后还是0e开头即可
0e215962017 =>md5 0e291242476940776845150308577824

数组绕过

md5()函数期望的得到的是一个字符串,但是如果传入一个数组的话,函数会报出一个警告,并返回NULL
当我们传入两个不同的数组,参数值必然不相等,而经过md5处理后,其值为NULL, **payload**?a[]=1&b[]=2`

原生类绕过

如果在类中进行比较一般是无法通过数组进行绕过的,这时候可以配合反序列化中的原生类技巧绕过,原生类绕过

哈希冲突绕过

MD5 是一种哈希算法,它将任意长度的输入数据映射到固定长度(128 位)的输出。由于 MD5 算法的输出长度是固定的,而输入数据的长度是任意的,所以理论上必然存在两个不同的输入数据,它们的 MD5 哈希值相同。

但是一般这些字符中都有一些不可见字符,所以这里采用url编码
$a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2

$b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
这两个字符串即是哈希冲突的两个字符串

字符串与数字之间的弱类型

字符强转为数字

php在做匹配和比较时候,会根据匹配的类型做类型转换,例如比较数字和字符串是否相等,就会进行转换,转换规则是前面的数字不变后面字母被当成字符型舍去
简单来说,在php中
123==123a
6asdijbsujy==6
后面的字符会被舍去,只比较最前面的数字

字符串被解析成十六进制

本来应该输入的是字符串,但是以0x开头的字符串在进行一些比较或运算时,就被php当做16进制数进行解析了

1
2
3
4
5
6
<?php
$hex = '0xdeadc0de';
$dec = 3735929054;
if($hex ==$dec) {
echo 'OKKK';
}

ps:在php中使用dechex()将十进制数转换为十六进制数,使用hexdec()将十六进制数转换为十进制数
对字符串进行十六进制编码解码可以用下面的脚本,hex2bin将十六进制数转化为二进制字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
function hexEncode($str) {
return bin2hex($str);
}

function hexDecode($str) {
return hex2bin($str);
}

// 示例
$str = "index.php";
$encoded = hexEncode($str);
$decoded = hexDecode($encoded);

echo "原始字符串: $str\n";
echo "编码后的字符串: $encoded\n";
echo "解码后的字符串: $decoded\n";
?>