购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.9 反序列化漏洞

反序列化漏洞在渗透中扮演着很重要的角色,一些有名的漏洞起因均是反序列化,比如FastJSON反序列化漏洞、WebLogic反序列化漏洞等。在渗透活动中,渗透者除了常见的漏洞外,也会关注反序列化漏洞并寻找反序列化链。

1.9.1 什么是反序列化

反序列化是相对于序列化而言的,在计算机中序列化指的是将数据结构或者对象转换为方便存储或传输的数据,并且可以在之后还原,反序列化则与此相反。下面以一串代码来解释这个原理。

上述代码的运行结果如下。

可以看到在第二行,对象已经被序列化为一串字符串,其中开头的O是对象(Object),4表示该对象所属类的名称为4个字符,s是字符串(String)。下面展示序列化字符串还原的代码。

上述代码的运行结果如下。

由运行结果可以看出,该序列化字符串已经恢复为一个对象了。需要注意的是,代码中必须包含该类,否则反序列化会因为找不到该类而失败。

1.9.2 PHP反序列化

PHP中最常使用序列化的数据是对象,除了对象,数组也可以被反序列化,比如转换成JSON形式的数据。本节主要介绍对象的反序列化,这也是PHP反序列化漏洞的主要成因。

1.PHP反序列化的基础知识

我们先来分析序列化后的字符串。要想理解PHP反序列化漏洞产生的原因,就要先了解在反序列化的过程中发生了什么。

回顾1.9.1节序列化字符串还原的代码,代码输出字符串反序列化成为对象之后,输出name属性的值,这一步表明字符串已经通过反序列化成为对象。随后代码在对象销毁时执行了__destruct()方法,这类__开头的方法在PHP中被称为魔术方法。可以看出,PHP反序列化及对象销毁时会执行某些魔术方法,这就是PHP反序列化造成漏洞的原因。

2.PHP中的魔术方法

根据PHP官方文档介绍,魔术方法是一种特殊方法,当在对象上执行某些操作时,它们会覆盖PHP的默认操作。魔术方法的名称和功能如表1-8所示。

表1-8 魔术方法的名称和功能

(续)

从表中可以看出,魔术方法都是一些在特定条件下触发的方法。

在CTFHub上找到2020年网鼎杯朱雀组Web题目phpweb,创建环境并打开题目,查看网页源码可以看到存在一个表单,如图1-200所示。

图1-200 phpweb首页的表单

猜测这是一个函数调用功能,尝试调用eval、system等函数时发现提示黑名单,我们先读源码,POST提交func=file_get_contents&p=/var/www/html/index.php,可以得到源码,代码如下。

代码的主要逻辑为获取请求的func和p参数,并且设置了func的黑名单,调用call_user_func($func, $p)即调用了$func($p)函数。由于存在黑名单,因此我们没办法直接执行命令或者获取WebShell。代码中存在Test类,我们可以通过反序列化触发__destruct(),调用gettime()函数,直接执行call_user_func,绕过黑名单。接下来需要构造反序列化字符串,这个过程自然不是手工和随意构造,而是根据目标代码中存在的类来构造。我们新建一个payload.php文件,代码如下。

运行获得反序列化串如下。

提交Payload如下。

提交之后反序列化该字符串,从而执行system('find/-name "*flag*"2>/dev/null'),该命令用于查找系统中文件名带有flag的文件,输出结果如图1-201所示。

图1-201 phpweb首页的表单

得到flag文件位置之后,即可用file_get_contents函数将其读出。

总结一下这道题的考点:字符串反序列化为对象后,在对象销毁时触发魔术方法__destruct(),从而绕过黑名单限制。

除了__destruct(),还有一些常见的魔术方法,代码如下。

3.常见POP链利用

POP(Procedure Oriented Programming,面向过程的程序设计)链是反序列化安全中比较重要的一个概念,在实际场景中构成反序列化漏洞的调用链是非常复杂的,这样的调用链我们称之为POP链。接下来以Laravel POP链为例,带领读者体验一下在实际场景中如何利用POP链进行RCE。

Laravel是开源的PHP Web框架,由于其强大的功能、优雅的设计和简单的用法,深受开发者喜爱。Laravel中存在复杂的调用,利用这些复杂的调用可以开发很多POP链。

Laravel POP链的入口通常是lluminate、Broadcasting、PendingBroadcast类的__destruct()方法,如图1-202所示。通过寻找可利用的__call()魔术方法或dispatch()方法,调用call_user_func或call_user_func_array方法执行命令。

下面跟踪并复现一条完整的链,Laravel版本为8.5.9。首先,寻找dispatch()方法。\vendor\laravel\framework\src\Illuminate\Bus\Dispatcher.php中的class Dispatcher存在dispatch()方法,其实现如图1-203所示。

图1-202 PendingBroadcast类的__destruct()方法

图1-203 Dispatcher的dispatch()方法

其中$command和$this->queueResolver都是可控的,并且$this->commandShould-BeQueued还要求$command为ShouldQueue的实例,如图1-204所示。

因为上述代码中的变量都可以控制,所以可以进行RCE。构造反序列化Payload,代码如下。

图1-204 dispatchToQueue代码

代码输出的结果即为经过urlencode后的序列化字符串,如果找到可以反序列化的点比如unserialize,即可实现RCE。

从上面两个例子中可以看出,PHP的反序列化漏洞依赖于反序列化触发点和POP链,而POP链又依赖于各种魔术方法。反序列化漏洞由于利用起来比较复杂,开发者在开发时往往会忽略魔术方法使用的安全性,在渗透测试过程中利用反序列化漏洞往往会取得出其不意的效果。 09b+4vhbemtMC3bgmlYtcsZ0PyR1GK/UN2pglIBKDexjvmeWmeXdJJ1YpFsuhIII

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开