资源收集自网络,加入一些极少个人观点,持续更新。
部分内容会在另外的文章中作更详细的说明。
MD5 compare 漏洞
PHP在处理哈希字符串时,会利用!=或==来对哈希值进行比较,它把每一个以 0e 开头的哈希值都解释为 0(科学计数法),所以如果两个不同的密码经过哈希以后,其哈希值都是以 0e 开头的,那么 PHP 将会认为他们相同,都是 0。
常见 payload 有
md5(str)
QNKCDZO
240610708
s878926199a
s155964671a
s214587387a
sha1(str)
aaroZmOk
aaK1STfY
aaO8zKZF
aa3OFF9m
同时 MD5 不能处理数组,见如下判断可绕过
if(@md5($_GET['a']) == @md5($_GET['b']))
{
echo "yes";
}
payload:/test.php?a[]=1&b[]=2
MD5 碰撞能生成 MD5 一样的不同文件,已经说明了 MD5 校验可能存在的不安全性。
王小云教授实现 MD5 碰撞的一个软件为 fastcoll,最新版本为 v1.0.0.5。
下载地址:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip
源代码:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5_source.zip
有兴趣的也可以查看一下下面两个文件
http://www.win.tue.nl/hashclash/SoftIntCodeSign/HelloWorld-colliding.exe
http://www.win.tue.nl/hashclash/SoftIntCodeSign/GoodbyeWorld-colliding.exe
ereg() 函数漏洞:00 截断
ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE
解析:如果 $_GET['password']
为数组,返回值为NULL
如果其中含有 %00
,则其后面的正则匹配会被绕过。
变量本身的 key
变量本身的 key 也可以当作变量提交给函数处理
<?php
print_r(@$_GET);
foreach ($_GET AS $key => $value)
{
print $key."\n";
}
?>
变量覆盖
全局变量覆盖
本特性已自 PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除。详情:http://php.net/manual/zh/security.globals.php
当 register_globals = on
时,传递过来的值会被直接的注册为全局变量直接使用。
<?php
//?id=1
echo "Register_globals: ".(int)ini_get("register_globals")."<br/>";
echo '$_GET["id"] :'.$_GET['id']."<br/>";
echo '$id :'.$id;
?>
变量$id没有初始化,此时变量的来源可能是$_GET['id'],也可能是$id。
防范方法:register_globals = off
对变量赋予初始值,例如 $id=0,那么即使在URL中有/test.php?id=1,也不会将变量覆盖,id 值为0。
extract()
extract(array,extract_rules,prefix)
作用:
从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建一个对应的变量。
extract() 在指定参数为 EXTR_OVERWRITE 或者没有指定函数可以导致变量覆盖。
<?php
$id=1;
extract($_GET);
echo $id;
?>
payload:/test.php?id=1
防范方法:在调用 extract() 时使用 EXTR_SKIP 保证已有变量不会被覆盖 extract($_GET,EXTR_SKIP);
import_request_variables()
在 register_globals = off
时,把 GET/POST/Cookie 变量导入全局作用域中。
<?php
import_request_variables("g", "get_");
echo $get_id;
?>
payload:/test.php?id=1
$$ 导致的变量覆盖
使用 foreach 来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。
<?php
$id=0;
foreach($_GET as $key => $value) {
echo $key."</br>".$value;
$$key = $value;
}
print "</br>".$id;
?>
payload:/test.php?id=1
parse_str()
parse_str() 函数把查询字符串解析到变量中,如果没有 array 参数,则由该函数设置的变量将覆盖已存在的同名变量。
<?php
parse_str("a=1");
echo $a."<br/>"; //$a=1
parse_str("b=1&c=2",$myArray);
print_r($myArray); //Array ( [c] => 1 [b] => 2 )
?>
类似的还有 mb_parse_str()。
strcmp()
int strcmp(string $str1,string $str2)
如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;
如果两者相等,返回 0。
<?php
$password=$_GET['password'];
if (strcmp('password',$password)) {
echo 'NO!';
} else{
echo 'YES!';
}
?>
要绕过,只需 $_GET['password'] 为数组或 object 即可。
payload:/test.php?password[]=
is_numeric()
<?php
echo is_numeric(233333);
echo is_numeric('233333');
echo is_numeric(0x233333);
echo is_numeric('0x233333');
//以上结果均返回 1
echo is_numeric('233333abc'); # 0
?>
unset()
unset(bar)
用来销毁指定的变量,如果变量 bar 包含在请求参数中,可能实现部分变量的销毁而实现程序逻辑绕过。
<?php
$_CONFIG['extraSecure'] = true;
foreach(array('_GET','_POST') as $method) {
foreach($$method as $key=>$value) {
// $$key == $_CONFIG
unset($$key);
}
}
if ($_CONFIG['extraSecure'] == false) {
echo 'flag {****}';
}
?>
string 转化为 int
在PHP中,所有应该是 int 的地方输入了 string,都会被转换成 int。
<?php
'abcd' == 0
'01' == 0
'1e1' == 10
//以上结果均返回 1
$array=[0,1,2,'3'];
var_dump(in_array('abc', $array)); //true
var_dump(in_array('1bc', $array)); //true
var_dump(intval('2')) //2
var_dump(intval('3abcd')) //3
var_dump(intval('abcd')) //0
//intval()也可以被 00 截断
if($req['number']!=strval(intval($req['number']))){
$info = "Number must be equal to its integer!! ";
}
//payload:$req['number']=0%00
$i ="abc";
switch ($i) {
case 0:
case 1:
case 2:
echo "i is less than 3 but not negative";
break;
case 3:
echo "i is 3";
}
?>
内容来源
https://blog.csdn.net/qq_35078631/article/details/75200157
https://www.cnblogs.com/xiaozi/p/7768580.html
https://www.jianshu.com/p/c9089fd5b1ba
评论 (0)