渗透测试基础 -变量覆盖漏洞

渗透测试基础-变量覆盖漏洞

    • 变量
    • 变量覆盖发生的函数
    • 变量覆盖靶场演练
    • 漏洞总结

只为对所学知识做一个简单的梳理,如果有表达存在问题的地方,麻烦帮忙指认出来。我们一起为了遇见更好的自己而努力!

变量

说到变量覆盖,那我们得回回课了,什么是变量?变量是如何被覆盖的?

变量一般比作盒子,我们可以在盒子里面放入东西,如果盒子多了,就得跟他们贴上标签,方便查找和调取。以这里的比喻来说,标签就是变量名,盒子里面的东西就是变量值

但这个盒子有个特点:就是一个盒子,只能存放一个东西,如果想要放入其他东西,就得将上一个物品拿出来才可以。这在代码层面,就直接被后来放入的东西覆盖掉。

实例


$a = 1;
echo $a;
$a = 2;
?>

在这里,会输出1,因为代码是从上往下执行的,这里并没有实施覆盖。但是变换一下echo的位置就会发生改变

实例


$a = 1;
$a = 2;
echo $a;
?>

这样,变量覆盖就发生了,这里$a的值就变为了21就会被覆盖掉。

但这个是需要改变代码才会实现的情况,正常情况下,开发不会做这样的事情出来,我们当然也改变不了代码的内容,所有这里就需要找开发所用的的函数,会不会出现不当的处理,造就变量覆盖漏洞的发生。

变量覆盖发生的函数

  1. extract()函数从数组中将变量导入到当前的符号表。

该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。

实例


$a = "Original";
$my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
extract($my_array);
echo "\$a = $a; \$b = $b; \$c = $c";
?>

输出

$a = Cat;$b = Dog;$c = Horse

基本解释就是 这个函数将数组变为变量

  1. parse_str()函数把查询字符串解析到变量中。

注释:如果未设置 array 参数,则由该函数设置的变量将覆盖已存在的同名变量。

注释php.ini文件中的 magic_quotes_gpc设置影响该函数的输出。如果已启用,那么在 parse_str()解析之前,变量会被addslashes()转换。

实例


parse_str("name=Peter&age=43");
echo $name."
"
; echo $age; ?>

输出

Peter
43
  //这个函数将字符串变为变量
  1. $$这个在php使用的最多

实例


$a = b;
$b = c;
echo $$a;
?>

输出

c

第一条$a = b,放入最后一条里面看。echo $$a => echo $b 所以就相当于执行了echo $b 所以输出了c

在来个实例


$a = 1;
foreach(array('_COKKIE','_POST','_GET') as $_REQUEST){
     
foreach($$_REQUEST as $_key=>$_value)
{
     $$_key=addslashes($_value);}}
echo $a
?>

渗透测试基础 -变量覆盖漏洞_第1张图片
foreach遍历数组,将数组里面的内容一个个拿出来去执行
渗透测试基础 -变量覆盖漏洞_第2张图片
as 将前面几个数组里面的值,依次放入$_REQUEST中,第一个_COOKIE 第二个_POST,第三个_GET

渗透测试基础 -变量覆盖漏洞_第3张图片
这里就cookie拆分一下,变为数值,这叫做键值分离,如果传进来的是GET,传进来的是a=1那这里就会变为$_key=a;$_value=1

因为在上面已经将a给解析出来了,所有这里放到下面,又变为了$a 然后函数addslashes()的意思是 函数返回在预定义的字符前添加反斜杠。

预定义字符是:
单引号(’)
双引号(”)
反斜杠(\)
NULL

那和我们这没关系,所有就变为了$a = 1

最后输出变量$a,值就发生了改变,经典的变量覆盖

变量覆盖靶场演练

变量覆盖漏洞想要黑盒测试发现,那可太难了,因为不知道这里传入什么数值才能达到目的,所以我们这里弄到了靶场doumiCMS的源码,对源码审计之后在来做靶场。

代码审计有几种:

  1. 全文阅读,理解每一条代码的含义{消耗时间太长,有些与安全无关,效率太低}
  2. 危险函数定位法,找一些危险函数,如数据库的连接函数mysqli_query(),找全部与这个函数相关的代码。
  3. 动态追踪(xdegue)不推荐,太过复杂。

现如今最合适的还是危险函数定位法

用到的工具就是 seay代码审计工具
渗透测试基础 -变量覆盖漏洞_第4张图片
规则添加变量覆盖的双美元符,然后进行全局搜索
渗透测试基础 -变量覆盖漏洞_第5张图片
渗透测试基础 -变量覆盖漏洞_第6张图片
这里发现了前面讲的实例基本一样的代码,我们试着来分析看一下
渗透测试基础 -变量覆盖漏洞_第7张图片
这里除了最后一个不知道什么意思,其他都知道,那先查一下干啥的
渗透测试基础 -变量覆盖漏洞_第8张图片
这里就找到了函数定义的地方,先看if条件写的是什么
magic_quotes_gpc()

如果magic_quotes_gpc为关闭时返回 0,否则返回 1。在 PHP 5.4.0 起将始终返回 FALSE
意思基本就是检查有没有开魔术引号,如果没开,就开一下。
渗透测试基础 -变量覆盖漏洞_第9张图片
最下面的else执行的函数有写
那这里与我们无关,继续往上面找,只要确定能执行到这里就行,代码能不能执行到这里,有几个方法可以验证。

  1. 看是不是在分支语句中,如if语句,就只会执行一个条件,显然这里并不是
  2. 寻找死亡函数,die()exit()
  3. 用死亡函数贴进去尝试

先说一下死亡函数的快速确定代码有没有执行的方法
渗透测试基础 -变量覆盖漏洞_第10张图片
访问这个文件,将函数放入if条件中,网页并没有发生改变,接下来换到else
渗透测试基础 -变量覆盖漏洞_第11张图片
换到else中,网页有了反应,说明是else中执行的语句。

接着往下看
找一下死亡函数exit()die()
渗透测试基础 -变量覆盖漏洞_第12张图片
在这里找到了死亡函数,不过这里有三个条件,满足了,就不会执行else里面的exit()

第一个
·strlen()·这个函数就是用来确认传进来值的长度的,只要大于0就满足,所有这里只要传了,就能通过

第二个
明显是自定义函数,所有找一下是什么意思
渗透测试基础 -变量覆盖漏洞_第13张图片


在这找到了,发现这里是个正则表达式的函数,用来匹配 cfg或者 GLOBALS 的,只要这里不传进去就好了

第三个
isset()如果指定变量存在且不为 NULL``,则返回 TRUE,否则返回FALSE。所有这里检查的就是看cookie是不是空的,空的就不满足。

那这个函数看下来,就是一个条件就行,只要传参里面不包含第二个条件里面的两个参数就行
知道了执行的条件那就好办了,现在就需要找另外个东西:session

cookie 代表身份
session 代表权限
有了session就能已管理员的权限登录后台,那现在就找,哪个文件引用了我们现在所用的文件。
渗透测试基础 -变量覆盖漏洞_第14张图片
渗透测试基础 -变量覆盖漏洞_第15张图片
这个看到了admin/login.php文件,这个login一般为登录界面,既然是admin的,那多半能得到管理员的权限。
渗透测试基础 -变量覆盖漏洞_第16张图片
这里使用了刚刚变量覆盖的文件
渗透测试基础 -变量覆盖漏洞_第17张图片
这里还使用了第二个文件,但是这里不知道文件的路劲是多少,所有得在找一下
渗透测试基础 -变量覆盖漏洞_第18张图片
这里添加个死亡函数,看看这个文件在哪。
渗透测试基础 -变量覆盖漏洞_第19张图片
这样就找到了文件在哪
渗透测试基础 -变量覆盖漏洞_第20张图片
代码下面还找到了登录检查,在往下面看。
渗透测试基础 -变量覆盖漏洞_第21张图片
这里就找到了_SESSION,既然找到了位置,那就看一下 登录成功的session是什么样子的,只要模仿一个就好了,反正源码在我们手上,账号密码也有。
渗透测试基础 -变量覆盖漏洞_第22张图片
渗透测试基础 -变量覆盖漏洞_第23张图片
这样就有了管理员的sisson,因为这里间接调用了我们最开始分析的变量覆盖的文件文件,所以这里传管理员的session进去就能已管理员的身份登录。

但是还有点需要注意,不是所有文件目录执行这个都可以的,需要找一个打开了session的地方,代码就是session_start(),只有找到有这个代码的地方才可以

在这个admin/login.php是不满足条件的,因为在变量覆盖漏洞的文件里面是没有session_starta()函数,这个chace.admin.php虽然有session_stsrt(),但是在文件的后面执行,也就没用了,所有还得找一个有session_start()且在文件包含common.php前面调用才可以。
渗透测试基础 -变量覆盖漏洞_第24张图片
渗透测试基础 -变量覆盖漏洞_第25张图片
这里就完美满足条件。

interface/comment.php?_SESSION[duomi_ckstr]=kwhi
&_SESSION[duomi_admin_id]=1
&_SESSION[duomi_group_id]=1
&_SESSION[duomi_admin_name]=admin

这里需要注意的是_RESSION前面的下划线是因为前面有一个$,所有不能多写,他会将这个自动填进去的。我们空出来就行。
渗透测试基础 -变量覆盖漏洞_第26张图片
渗透测试基础 -变量覆盖漏洞_第27张图片
渗透测试基础 -变量覆盖漏洞_第28张图片
在访问一下admin/login.php,就登录成功了
渗透测试基础 -变量覆盖漏洞_第29张图片

漏洞总结

防范方法:

  1. 使用原始变量

建议不注册变量,直接用原生的$_GET$_POST等数组变量进行操作,如果考虑程序可读性等原因,需要注册个别变量,可以直接在代码中定义变量,然后再把请求中的值赋值给他们

  1. 验证变量存在

如果一定要使用前面几种方式注册变量,为了解决变量覆盖的问题,可以再注册变量前先判断变量是否存在。如使用extract( )函数则可以配置第二个参数为EXTR_SKIP。使用php parse_str函数注册变量前需要先自行通过代码判断变量是否存在。最重要的一点,自行申明的变量一定要初始化,不然即使注册变量代码在执行流程最前面也能覆盖掉这些未初始化的变量。

《最好的防御,是明白其怎么实施的攻击》

你可能感兴趣的:(变量覆盖漏洞,php,安全)