PHP常见漏洞

md5加密漏洞

比较哈希字符串的时候,php程序把每一个以“0x”开头的哈希值都解释为科学计数法0的多少次方,恒为0。
所以如果两个不同的密码经过哈希以后,其哈希值都是以“0e”开头的,那么php将会认为他们相同。
另外md5加密是有几率两个字符串不同,但是加密后的值是相同的情况,这种情况称为哈希碰撞。

1
2
3
4
5
6
7
8
9
<?php
$str1 = 's878926199a';
$str2 = 's214587387a';

echo json_encode([
'md5_str1' => md5($str1),
'md5_str2' => md5($str2),
'bool' => md5($str1) == md5($str2)
]);

结果如下,两个值加密后竟然相等!
缺点你懂的,如果一个网站的某个用户密码加密后刚好是0e开头的,这个时候黑客过来破解,很容易就攻入了

1
2
3
4
5
{
md5_str1: "0e545993274517709034328855841020",
md5_str2: "0e848240448830537924465865611904",
bool: true
}

is_numeric漏洞

非数值->数值

可以将字符串转化成十六进制的数,该函数进行判断:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo json_encode([
is_numeric(233333),
is_numeric('233333'),
is_numeric(0x233333),
is_numeric('0x233333'),
is_numeric('233333abc'),
]);
//结果
[
true,
true,
true,
false,
false
]

16进制数0x61646D696EASII码对应的值是admin,如果我们执行了后面这条命令的话:SELECT * FROM tp_user where username=0x61646D696E,直接就可以查询admin。同样的1 or 1 -> 0x31206f722031

数值->非数值

原题是[极客大挑战 2019]BuyFlag,判断代码如下:

1
2
3
4
5
if (is_numeric($password)) {
echo "password can't be number</br>";
}elseif ($password == 404) {
echo "Password Right!</br>";
}

密码是404,但是不能输入数字,所以要考虑绕过的问题,这里记录解题思路。可以借助url编码中的空字符,例如%00或者%20,其中%00加在数值前面或者后面都可以,也就是%00404或者404%00这样,将%20加在数值末尾也可以绕过,比如404%20。

in_array漏洞

in_array中是先将类型转为整形,再进行判断
PHP作为弱类型语言,类型转换的时候,会有很大漏洞
转换的时候,如果将字符串转换为整形,从字符串非整形的地方截止转换,如果无法转换,将会返回0

1
2
<?php
var_dump(in_array("2%20and%20%", [0,2,3]));

结果如下:bool(true)

switch漏洞

switch中是先将类型转为整形,再进行判断
PHP作为弱类型语言,类型转换的时候,会有很大漏洞
转换的时候,如果将字符串转换为整形,从字符串非整形的地方截止转换,如果无法转换,将会返回0

1
2
3
4
5
6
7
8
9
10
11
<?php
$i ="abc";
switch ($i) {
case 0:
case 1:
case 2:
echo "i是比3小的数";
break;
case 3:
echo "i等于3";
}

结果如下,i是比3小的数。

intval强转漏洞

PHP作为弱类型语言,类型转换的时候,如果将字符串转换为整形,从字符串非整形的地方截止转换;如果无法转换,将会返回0

1
2
3
4
<?php
var_dump(intval('2')); //2
var_dump(intval('3abcd')); //3
var_dump(intval('abcd')); //0

这个时候 $a 的值有可能是 1002 union

if(intval(a) > 1000) { mysql_query("select * from news where id=".a)
}


PHP常见漏洞
https://k1nm0.com/2022/10/23/PHP常见漏洞/
作者
K1nm0
发布于
2022年10月23日
许可协议