历史漏洞回顾
在某次HW的第二天,就爆出了某VPN服务因变量覆盖漏洞导致了多家企业被攻陷,一时之间在蓝队中引起了轩然大波。那么让我们一起来看一下当时的部分漏洞代码。
在这里我们可以看到圈红线的地方调用了一个名叫show_form()的方法并传了一个$REQUEST的参数进去。$REQUEST又叫超全局变量,它的作用是可以接收post传参和get传参(php5.0以下的版本还可以接收cookie传参)。了解$REQUEST变量之后我们在看一下show_form()方法里写了些什么。
我们可以看到圈红线的位置就是接收了$_REQUEST参数的地方,在往下面看一行,重点来了,extract()函数就是造成本次变量覆盖的关键,它的作用就是将数组键值分离,键当作变量的名,值当作变量的值。
来给大家举个例子:
$this_array("name"=>"楚留香","age"=>"25","height"=>"175");
extract($this_array);
转变之后就变成了$name=“楚留香”,$age="25",$height="175"
到这里呢大家应该就可以明白此次的变量覆盖是由于$_REQUEST的滥用接收到了外部传递过来的内容在通过extract()函数转化成了变量,引起了变量覆盖,我们可以直接覆盖$strip_slashes和$host:
/tool/log/c.php?strip_slashes=system&host=id
通过对函数的覆盖导致原来的$strip_slashes($host)
在我们控制参数的情况下变为了system(id)
什么是变量覆盖
变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,来达到渗透攻击的目的。
变量覆盖类型
变量覆盖的类型大致分为以下几种这里分别给大家例举出来
extract函数使用不当
此函数的利用方式已经在漏洞回顾中详细介绍了,这里略过
parse_str函数使用不当
parse_str()函数可以将通过这个函数设置的变量,覆盖已经存在的同名变量
例:$a=1; parse_str(‘a=2’); echo $a; 结果=2
<?php
$a=1; //原变量为1
parse_str('a=2'); //经过parse_str函数后注册变量$a,重新赋值
print_r($a); //输出结果为2
?>
注意:此函数在代码审计中的出现频率不高,有兴趣的小伙伴可以自信搜索开源项目练习
import_request_variables函数使用不当
import_request_variables(string $type)函数可以将GET、POST、COOKIE的参数定义成变量。(PHP 4 >= 4.1.0, PHP 5 < 5.4.0)
这里注意一下要传的参数$type代表要注册的变量,G代表GET,P代表POST,C代表COOKIE,第二个参数为要注册变量的前缀。
例:$a=123; import_request_variables(‘G’);此时我通过get传参一个?a=456,那么我现在输出$a其内容就会被转换成456。
<?php
$a=123; //原变量为123
import_request_variables(‘G’); //get传入a=456,覆盖a的值
echo $a; //输出结果为456
?>
$$使用不当
“$$”是PHP当中的一种魔术写法,有什么作用呢举个例子
例:$a=abc,$$a=456,$abc=?
<?PHP
$a='abc';
$$a=456;
echo $abc;
?>
解析:这里面呢首先给$a赋值,$a的值就是abc,那么$$a呢就相当于将原来的$a又定义成了变量,这时候$a的值是abc,$$a就是把$a的值变成变量也就成了$abc;所以$$a=456也就相当于$abc等于456。
变量覆盖代码审计
本次案例通过DuomiCms
1、首先我们先用代码审计工具全局搜索里搜寻一下“$$”
在这里我们发现有可能出现变量覆盖的文件,注意“$$”变量覆盖一般会配合foreach循环出现。
2、我们点进相应的页面发现这段代码将接受的POST、GET、COOKIE内容变成了变量,并且对立面的值进行了转义
_RunMagicQuotes这个是自定义的函数作用就是将循环出来的值加一个反斜杠进行转义不用太纠结作用。
3、到这里我们已经可以确定这个就是变量覆盖。
4、接下来我们可以看看都有哪些页面跟存在变量覆盖的页面有关联,可以全局搜索一下
这里我们可以看到有个登陆页面引用了变量覆盖的页面,通过这个页面想到是不是可以用变量覆盖来改变一下session的值把我们变成管理员呢。
5、我们来把session的内容打印一下看需要传递什么参数。
得到需要传递的session
array(5) {["duomi_group_id"]=> string(1) "1"["duomi_admin_id"]=> string(1) "1"["duomi_admin_name"]=> string(5) "admin"["duomi_ckstr"]=> string(4) "fyet" ["duomi_ckstr_last"]=> string(0) "" }
6、万事俱备接下来就 是构造session并且看效果了
总结
变量覆盖作为白盒审计还是会经常遇到的,但是不代表存在这些函数就一定可以执行变量覆盖,核心是我们是否能控制自己传的参数去改变变量的内容,所以在发现这些可能存在漏洞的函数时,也要找寻是否存在传参的点。