浅析安全反序列化漏洞

一、概述

对于这个漏洞的学习,有几个大体的思路,一是向大佬学习;二是找到可以利用的点,再不断构造合理的对象向这个点靠近;三是把几个子链分别构造好再连起来。

另外,查到的资料说这个漏洞并不是适用于所有的TP5.0.X版本,这里为了不产生歧义,只记成TP5.0.24版本。

二、分析

(一)环境搭建

Windows、PHPStudy(PHP5.6)、ThinkPHP5.0.24;

首先安装此版本的ThinkPHP,

composer create-project topthink/think tp 5.0.24

index controller改为

class Index
{
    public function index()
    {
        @unserialize($_GET['k']);
    }
}

调用栈如下,

File.php:160, think\cache\driver\File->set()
Memcache.php:94, think\session\driver\Memcache->write()
Output.php:154, think\console\Output->write()
Output.php:143, think\console\Output->writeln()
Output.php:124, think\console\Output->block()
Output.php:212, call_user_func_array()
Output.php:212, think\console\Output->__call()
Model.php:912, think\console\Output->getAttr()
Model.php:912, think\Model->toArray()
Model.php:936, think\Model->toJson()
Model.php:2267, think\Model->__toString()
Windows.php:163, file_exists()
Windows.php:163, think\process\pipes\Windows->removeFiles()
Windows.php:59, think\process\pipes\Windows->__destruct()
App.php:8, app\index\controller\Index->index()

(二)分析与调试

分为几个部分进行分析。

1.从Windows.removeFiles()到Model.toArray()

从Windows的__destruct开始看,

image.png

【一>所有资源获取<一】
1、电子书籍(白帽子)
2、安全大厂内部视频
3、100份src文档
4、常见安全面试题
5、ctf大赛经典题目解析
6、全套工具包
7、应急响应笔记
8、网络安全学习路线

close()中没有可以直接使用的点,removeFiless()中有file_exists()的判断,如果file_exists()的参数是一个对象,则会调用其对应类的__toString()方法,

image.png

think\Model中有很好的__toString()方法,其中调用了toJson,toJson中调用了toArray。

image.png

这里需要注意,Model是个抽象类,没法直接从抽象类创建对象,它的意义在于被扩展,

image.png

经过搜索,可以选择Pivot与Merge两个类作为具体实现,选择哪一个对主干不会产生太大影响,但会对PoC的写法产生细微差别(个别字段的public与private属性),这里先选择Merge。

进入Model.toArray之后,就该考虑如何进一步调用到Output.__call()

2.从Model.toArray到Output.__call()

从Model的toArray中,我们可以看到有若干个疑似可以利用的点,选择不同的触发点会对整个流程产生一定影响。此处选择$item[$key] = $value ? $value->getAttr($attr) : null;这一点。

image.png

接下来遇到一个很现实的问题,就是找到了这个点之后,怎么在$value有意义的前提下,保证程序可以在前面的若干行代码中不出错,进而顺利正常抵达这里。

(1)进入else

首先最高级的if和内部的大else前面的if和elseif较为直接,要求如下: t h i s − > a p p e n d 不 为 空 , this->append不为空, this>appendname不可为数组, n a m e 不 可 包 含 “ . ” 。 这 里 是 遍 历 name不可包含“.”。这里是遍历 name.this->append数组,而这个数组是我们可控的,则对应的 k e y 和 key和 keyname也都可控,故这里可以较为容易的走过。这一部分可以简单走过,重要的是else之中的隐藏的阻碍。

(2)parseName与进入if (method_exists($this, $relation))

首先跟进看Loader::parseName($name, 1, false);

image.png

功能是字符串命名风格转换,应该来讲没什么影响, r e l a t i o n 应 该 可 以 和 relation应该可以和 relationname直接划等号。

接下来看如何使method_exists($this, r e l a t i o n ) 这 一 条 件 为 t r u e , 这 要 求 我 们 找 一 个 M o d e l 或 其 子 类 中 存 在 的 方 法 名 , 由 此 可 见 , 上 一 小 步 中 的 relation)这一条件为true,这要求我们找一个Model或其子类中存在的方法名,由此可见,上一小步中的 relation)trueModelthis->append不能随意构造,应该放入一个合适的方法名。

(3)getRelationData

image

可以看到,在判断 t h i s 中 定 义 了 this中定义了 t

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值