代码审计-变量覆盖和反序列化漏洞

目录

案例一:Metinfo 5.0版本存在变量覆盖漏洞

案例二:phpmyadmin2.x版本存在反序列化漏洞


漏洞关键字

变量覆盖:extract( )、parse_str( )、importrequestvariables() $$等

反序列化:serialize()、unserialize()、 _construct、 _destruct等

案例一:Metinfo 5.0版本存在变量覆盖漏洞

由上面的关键字,知道了$$可能存在变量覆盖的漏洞。

Metinfo5.0版本存在着变量覆盖漏洞,刚好最近在学习代码审计,但是没有找到5.0的源码,下载了5.3的源码,5.3版本实际上已经修复了该漏洞,只能拿着它来学习一下变量覆盖漏洞,顺便学习是如何修复该漏洞的。

下面来看一下通过$$是如何产生变量覆盖漏洞的。

5.0版本的代码如下:

foreach(array('_COOKIE', '_POST', '_GET') as $_request) {
	foreach($$_request as $_key => $_value) {
		$_key{0} != '_' && $$_key = daddslashes($_value);
	}
}

这里先来了解一下foreach函数,foreach函数有两种用法:

第一种:遍历给定的数组,每次循环中,当前单元的值被赋给 $value 并且数组内部的指针向前移一步(因此下一次循环中将会得到下一个单元)。

foreach(array as $value)

第二种:同上,同时当前单元的键名也会在每次循环中被赋值给变量$key

foreach (array as $key => $value) 

看下面的两个例子来理解foreach函数。

$a = array('Tom','Mary','Peter','Jack');
foreach($a as $value){
    echo $value."</br>";
}

上述的代码产生的结果为:

Tom
Mary
Peter
Jack

第二个例子

$a = array('Tom','Mary','Peter','Jack');
foreach($a as $key => $value){
    echo $key.','.$value."</br>";
}

得到的结果为:

0,Tom
1,Mary
2,Peter
3,Jack

大概了解了foreach函数,回到正题。

代码中的$_request的值便是数组中的_COOKIE, _POST, _GET值,而$$_request便造成了变量覆盖,使得变量名=参数名,实现覆盖,接收$_COOKIE,$ _POST,$ _GET的值。

下面写一个例子,来看一下变量覆盖漏洞利用的条件:

<?php
    include '/include/common.inc.php';
    //条件一:commend.inc.php文件存在变量覆盖漏洞
    $file='1.php';
    //条件二:存在文件包含函数,包含可控变量
    include($file);
?>

所以已经知道了该cms中的common.inc.php文件中存在着变量覆盖的漏洞,因此我们就可以通过全局搜索文件包含函数,查询可控制的变量。

这里发现了/about/index.php文件中存在着require_once $module。之所以看这个文件是因为与我们的例子相似,$module变量并没有写死。有可能是可以被我们控制的,就像例子中的$file变量。接下来就是打开这个文件,查询它是否包含了common.inc.php,这样才存在变量覆盖漏洞,还有一个点就是看一下这个$module变量是否可控。

首先对于第一点,表面上是包含了/include/module.php文件,并没又包含common.inc.php,所以可能不存在变量覆盖漏洞。但是当我们找到 /include/module.php文件的时候,打开便发现了在/include/module.php中包含了common.inc.php,所以由于传递性,导致/about/index.php这个文件也存在了变量覆盖漏洞。

接下来就是看module变量是否是可控变量。

这段代码就是初始化module为空,就是由于这个module='',这个操作,使得我们之前传入的参数的值得到清空。修复了该漏洞,在5.0版本中是没有这个语句的。所以我们可以先将他进行注释掉,回到5.0版本。判断fmodule是否等于7,如果不等于7,就执行下面的语句,所以我们可以传参fmodule=7,那么就不会执行下面的语句,也就不会给module赋值,之后我们自己再给module传参,去包含我们自己想要的文件,实现变量覆盖。

payload:http://127.0.0.1/metinfo/about/index.php?fmodule=7&module=1.txt(此处的1.txt便是我们想要包含的文件)

修复方案就是添加了$module='',便将我们之前的输入置空,修复原有的变量覆盖的漏洞。

案例二:phpmyadmin2.x版本存在反序列化漏洞

没找到源码,这里使用小迪老师上课的截图记录笔记。

#反序列化-->自动审计或搜索关键字找到文件及代码段

_wakeup() //使用unserialize时触发

_sleep() //使用serialize时触发

_destruct() //对象被销毁时触发

_call() //在对象上下文中调用不可访问的方法时触发

_callStatic() //在静态上下文中调用不可访问的方法时触发

_get() //用于从不可访问的属性读取数据

_set() //用于将数据写入不可访问的属性

_isset() //在不可访问的属性上调用isset()或empty()触发

_unset() //在不可访问的属性上使用unset()时触发

_toString() //把类当做字符串使用时触发

_invoke() //当脚本尝试将对象调用为函数时触发

加载源码,通过反序列化的各种函数关键字来进行全局搜索。

在/scripts/setup.php文件中发现了unserialize函数,进行反序列化。

 

这段高亮的代码就是将POST方式传入的configuration的值进行反序列化之后,赋值给变量configuration。由于反序列化操作在执行的时候,会执行魔术方法wakeup,我们在上面的代码中看到了$PMA_Config = new PMA_Config();创建了对象,之后我们去全局搜索这个类,找其中的wakeup函数。

发现在/libraries/Config.class.php文件中存在着它的定义。

找到魔术方法之后,便是对文件的时间进行操作(这里没太看懂,手动狗头,实在是没有源码自己去审了)getsource就是获取内容,之后进行加载。追踪一下这个getsource函数和load函数。

在load函数中发现了关键的函数,file_get_contents(),该函数就是进行文件的读取,外层还有一个eval进行包裹,他就是将内容当作php来执行。

所以看到/scripts/setup.php文件中的代码的时候,经过if判断,通过POST方式传入action,以及configuration,判断他两个是否存在,如果存在,并且action不等于clear,那么就反序列化POST传过来的configuration。

可以看到已经将d:/test.txt的内容进行了输出。如果test.txt中的代码是恶意代码,便可以实现RCE。

猜你喜欢

转载自blog.csdn.net/weixin_44770698/article/details/125675088