目录
disable_function简介
在php-fpm下的php.ini配置文件中有这个么个字段disable_function,在这个字段中disable_function里面你想要禁用那个命令就把命令写在这里,上面写了system,system就被禁用了,修改完配置文件不要忘记重启服务
test.php的文件内容
访问test.php的没有反应,这就是system被禁止掉了,已经测试过了
在项目中各种函数都可能被禁用(会有一部分项目需要的函数被放通),所以当我们拿webshell缺无法执行命令,下面我们来看一下如何绕过
LD_PREELOAD(最好用的一个方法)
禁用的函数
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,dl,mail,system
服务器上有sendmail这个服务
mail函数,用来发送邮件
我们来看一下mail启动时的子进程
使用下面这个命令
root@ubuntu:/var/www/html# strace -f php web.php 2>&1 | grep execve
发现这个子进程里面调用了sendmail这样一个程序,php的mail是通过系统的sendmail来发送邮件的,这个sendmail在ubuntu中没有安装,在centos是自动安装的。
然后我们使用下面语句查看一下sendmail使用了那些函数
root@ubuntu:/var/www/html# readelf -s /usr/sbin/sendmail
调用了很多函数
上面函数我们要利用的函数就是getuid这个函数,这个是用来获取我们当前进程的uid
然后我们编写一个c语言代码进行准备工作
这个代码重新定义了getuid这个函数,这个目的就是用来替换和劫持
编译文件,.so文件是linux下的连接文件
root@ubuntu:/var/www/html# gcc -c -fPIC test.c -o hack && gcc --share hack -o hack.so
然后创建一个php文件并写入一段php代码,这个代码首先使用putenv设置LD_PRELOAD的参数然后调用test.so文件,让getuid覆盖系统getuid
然后执行这个php文件,我们去看/tmp/test下是否有文件生成,确实有且里面的whomi执行了
这个执行的逻辑就是当你调用mail这个函数,然后这个函数会调用sendmail这个服务,然后sendmail这个服务调用getuid这个函数,然后我们编写了LD_PRELOAD这个条目,当调用sendmail时会优先加载LD_PRELOAD这个条目里面的方法也就是我们刚刚编译的c语言文件,然后加载了我们编写好的payload,然后就会执行我们写入的命令。且我们这个命令是在系统层面调用所以可以绕过PHP。
不只mail可以触发sendmail,error_log也可以触发。我们只要有一个函数可以触发一个新的子进程,这个子进程里面可以调用函数那我们就可以劫持这个函数,然后我执行命令disable_function是限制不了我们的
服务器上没有sendmail这个服务
__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)它的语法格式为:__attribute__ ((attribute-list)) ,若函数被设定为constructor属性,则该函数会在main()函数执行之前被自动执行
类似的,若函数被设定为destructor属性,则该函数会在main()函数执行之后或者exit()被调用后自动执行,类似构造与析构函数,若它出现在共享对象中时,那么一旦共享对象被系统加载,立即将执行 __attribute__((constructor)) 修饰的函数,所以无需考虑劫持某一函数,只要能ld_preload并执行php调用新进程,就能劫持共享对象从而bypass disable function。
这个东西的步骤和sendmail差不多,也是写一个c文件然后编译后,想办法调用,这里同样是在创建一个子进程文件时调用,但是不需要劫持函数,只要有子进程chua
#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
__attribute__ ((__constructor__)) void preload (void){
unsetenv("LD_PRELOAD");
system("whoami > /tmp/leon");
}
例子:蚁剑靶场第一关
源码地址
GitHub - AntSwordProject/AntSword-Labs: Awesome environment for antsword testsk
开始测试
我们这里蚁剑整一下
我们先用蚁剑把webshell加载起来,然后去执行命令都无法执行,这就是系统命令被禁用了
这里禁用了mail和system等一些命令执行函数
我们想办法绕过
使用蚁剑的插件
这里有很多插件,咱只选自己需要的下载
(下面有个注入不死php webshell,这个不死是使用chattr给锁住了,有经验的管理员很容易就发现了,鸡肋)
我们安装绕过disable_function,并使用
这里是支持的命令,在这个里面我们可以看道有一些命令是被禁用的
选择模式选择LD_PRELOAD模式
这里显示创建了一个新的脚本
这个脚本就是流量转发的脚本,将流量转发到127.0.0.1的62837端口
使用上面的脚本进行连接
这个将流量转发到新的php进程上面,php -n -S是不在使用原来的php.ini重新创建一个进程,重新创建一个web服务,然后我们刚刚创建的.antproxy文件来连接新的web服务,使用的是php的默认配置,自然就不受原来php.ini里面的disable_function限制
结果
执行命令,可以执行
flag也拿到了
我现在在测试用户的系统的时候我发现他是用php做的,然后我拿到了他的webshell后,发现它禁用了php多个命令函数然后我尝试去绕过它,我就用了这个方法对这个进行了绕过。他没有禁用putenv和mail这几个函数,然后我用它写入了我的恶意代码,在执行的时候就进行了上面的操作。
Apache Mod CGI
禁用的函数
pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,dl,mail,system,putenv
这个禁用的函数比上面多了一个putenv,所以没有办法使用LD_PREELOAD这种方法了
这次使用的方法是利用.htaccess,我们通过上传.htaccess来利用apache的mod_cgi来绕过php的限制
利用条件
目录下有写权限
apache 使用 apache_mod_php
apache支持php都是使用模块的方式支持,所以apache支持php都是这个模式apache_mod_php
Web 目录给了 AllowOverride 权限
(AllowOverride 是Apache服务器中的一个指令,用于控制特定目录下的.htaccess文件的使用权限。.htaccess文件通常用于重写URL(这里的意思就是比如你有一个资源是web.php然后你不想让别人知道这个是php文件,你可以修改成web.html)、设置自定义错误页面、改变文件类型等。
AllowOverride 可以设置为以下值:
All:允许使用所有的.htaccess指令。
None:不允许使用.htaccess文件中的任何指令。
特定指令列表:只允许使用列表中的指令。)
启用了mod_cgi
这个一般情况是不可能的,因为这个东西可以直接执行命令的
使用
首先上传一个.htaccess文件然后,这里就是可以将.test的后缀文件的文件都当作cgi-script来执行
Options +ExecCGI
AddHandler cgi-script .test
之后上传shell.test
#!/bin/bash
echo&&cat /etc/passwd
然后他就会以cgi的模式去执行里面的代码
php-fpm
环境搭建
直接docker拉取蚁剑靶场第5关
原理
这里是利用了php-fpm的未授权访问漏洞,然后让利用的那两个字段变成上传自己的文件,提前加载了.so文件,然后新生成了一个子进程,原理和第一个相差不大
测试
这里使用蚁剑来测试一下
创建副本文件(方便对照)
将副本文件所连接的文件修改
结果
测试成功
Json Serializer UAF
利用json序列化中的堆溢出触发,借以绕过disable_function,影响范围是: 7.1 – all versions to date 7.2 < 7.2.19 (released: 30 May 2019) 7.3 < 7.3.6 (released: 30 May 2019)
测试
这个脚本是使用蚁剑上的,下面两个同理在蚁剑上也有脚本
未使用脚本
使用脚本
GC UAF
利用的是PHP garbage collector程序中的堆溢出触发,影响范围为7.0-7.3
这里不做演示
Backtrace UAF
影响版本是7.0-7.4
这里不做演示
FFI扩展
原理
php>7.4,开启了FFI扩展ffi.enable=true,我们可以通过FFI来调用C中的system进而达到执行命令的目的
这里使用的是c语言的system命令和php的php.ini没关系
代码脚本
<?php
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("whoami >/tmp/1");
echo file_get_contents("/tmp/1");
@unlink("/tmp/1");
?>
测试
环境蚁剑靶场8
测试首先连接
开启插件选择的模式就是FFI
结果
执行成功