代码审计duomicms—变量覆盖漏洞

变量覆盖漏洞

什么是变量覆盖?
变量覆盖指的是可以用我们的传参值替换程序原有的变量值
如下

<?php
$a=123;
$a=1;
echo $a;
?>
怎么去寻找变量覆盖?

经常导致变量覆盖漏洞场景有:
$$使用不当,extract()函数使用不当,parse_str()函数使用不当import_request_variables()使用不当,开启了全局变量注册等。

经常引发变量覆盖漏洞的函数有:extract() parse_str() import_request_variables()

1.extract()


分析源码我们可以知道,

1、文件将get方法传输进来的值通过extrace()函数处理。

2、通过两个if语句分别判断是否存在gift变量,和变量gift的值和变量content的值是否相等。变量content的值是通过读取变量test的值获取到的。如果两个变量相等输出flag。如果不相等,输出错误。

似乎逻辑上没啥问题,但是如果我们传参了test呢?

第一开始test在php中已经定义了,但是因为extrace()函数,我传参test时相当于重新给test赋值对不对?因为php执行语句是自上而下,那我传的参数完全可以覆盖掉之前所定义的

那么当我传参gift=a&test=a,相当于 g i f t = a ; gift=a; gift=a;test=a
那么这里是不是就直接输出flag了呢 (因为 c o n t e n t 是 由 content是由 contenttest决定, g i f t 和 gift和 gifttest都是我可以决定的)

####2.parse_str()
parse_str() 将查询字符串解析到变量中:

<?php
	parse_str("name=zkaq&&age=60");
	echo $name."<br>";
	echo $age;
	?>

输出了zkaq和60

那么parse_str(“name=Bill&age=60”) 相当于完成了 n a m e = ′ z k a q ′ 和 name ='zkaq'和 name=zkaqage =‘60’

那么如果在parse_str中可以直接传参的话,那么是不是也可以覆盖变量呢。

不仅仅是函数会导致变量覆盖,有些特殊符号的特殊搭配也会引起变量覆盖漏洞,比如$$

$$ 导致的变量覆盖问题在CTF代码审计题目中经常在foreach中出现,如以下的示例代码,使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的值作为变量的值。因此就产生了变量覆盖漏洞。请求?name=test 会将$name的值覆盖,变为test。

来,我们上一个例题:

<?php
$a = 1;
foreach(array('_COOKIE','_POST','_GET') as $_request) {
    
    
foreach($$_request as $_key=>$_value) //将键和键值分开
{
    
    $$_key=addslashes($_value);}}//addslashes,就是类似于一个魔术引号的作用
echo $a;
?>

这个代码会接受我们的GET提交、POST提交、COOKIE参数,将这个接受来的参数依次放入$_request
k e y = > _key=> key=>_value 这是个数组解析,实际上就是键值分离
正常而言 a = 1 是 一 个 定 值 , 但 是 因 为 a = 1是一个定值,但是因为 a=1 k e y 的 缘 故 , 当 我 传 参 a = 2 ; 那 么 _key的缘故,当我传参a=2;那么 key,a=2; k e y = a d d s l a s h e s ( _key=addslashes( key=addslashes(_value);就变为了$a = 2 .

简单来说就是

<?php
$a = 'b';
$b = 'c';
echo $$a;
?>

输出结果等于C;


我们首先,自行搭建靶场,进行测试

我们安装好过后
我们可以使用seay代码审计工具去快速的找到危险函数,这里是变量覆盖的,所以特意自己加了一个匹配$$的规则:([^$"]|$)${?$
在系统配置的规则配置里面可以添加


打开自动审计功能,但是会存在90%以上的误报,自动审计

我们偶然发现存在weixin的文件夹,微信之前爆出过xxe漏洞,这代表这个cms也可能存在xxe,我们审计代码,果然发现具有这个函数,我们把这个漏洞复现一下
突然发现,必须要登陆,才可以传参进行XXE


通过我们的seay审计工具,我们快速的发现了一个存在变量覆盖的地方(duomiphp\common.php文件)

我们再看看能执行这个代码的先决条件,去满足这个if


isset() — 检测变量是否设置。
简单说就是
1.必须要有传参
2.键名不能有cfg_和GLOBALS 3.COOKIE传参中不能有$_k


我们发现这个login.php文件利用require_once()调用了
"…/duomiphp/common.php"文件,而且它开启了


而这个session是控制登陆用户的权限的一个参数
那么我们可以通过common.php进行一个伪造session


我们直接访问这个文件并构造这个变量
interface/comment.php?_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_id]=1&_SESSION[duomi_admin_name]=admin

然后直接访问admin目录


发现已经获取管理员权限

猜你喜欢

转载自blog.csdn.net/weixin_43264067/article/details/106157981