本文涉及知识点实操练习——绕过函数过滤(点击即可开始实操):本次实操练习通过宽字节方式绕过mysql_real_escape_string()、addslashes()这两个函数。
是否遇到过费劲九牛二虎之力拿了webshell却发现连个scandir都执行不了?拿了webshell确实是一件很欢乐的事情,但有时候却仅仅只是一个小阶段的结束;本文将会以webshell作为起点从头到尾来归纳bypass disable function的各种姿势。
从phpinfo中获取可用信息信息收集是不可缺少的一环;通常的,我们在通过前期各种工作成功执行代码 or 发现了一个phpinfo页面之后,会从该页面中搜集一些可用信息以便后续漏洞的寻找。
我谈谈我个人的几个偏向点:
版本号
最直观的就是php版本号(虽然版本号有时候会在响应头中出现),如我的机器上版本号为:
那么找到版本号后就会综合看看是否有什么"版本专享"漏洞可以利用。
DOCUMENT_ROOT
接下来就是搜索一下DOCUMENT_ROOT取得网站当前路径,虽然常见的都是在/var/www/html,但难免有例外。
disable_functions
这是本文的重点,disable_functions顾名思义函数禁用,以笔者的kali环境为例,默认就禁用了如下函数:
如一些ctf题会把disable设置的极其恶心,即使我们在上传马儿到网站后会发现什么也做不了,那么此时的绕过就是本文所要讲的内容了。
open_basedir
该配置限制了当前php程序所能访问到的路径,如笔者设置了:
随后我们能够看到phpinfo中出现如下:
尝试scandir会发现列根目录失败。
opcache
如果使用了opcache,那么可能达成getshell,但需要存在文件上传的点,直接看链接:
https://www.cnblogs.com/xhds/p/13239331.html
others
如文件包含时判断协议是否可用的两个配置项:
allow_url_include、allow_url_fopen
上传webshell时判断是否可用短标签的配置项:
short_open_tag
还有一些会在下文讲到
bypass open_basedir因为有时需要根据题目判断采用哪种bypass方式,同时,能够列目录对于下一步测试有不小帮助,这里列举几种比较常见的bypass方式,均从p神博客摘出,推荐阅读p神博客原文,这里仅作简略总结。
syslinkhttps://www.php.net/manual/zh/function.symlink.php
symlink ( string $target
, string $link
) : bool
symlink() 对于已有的 target
建立一个名为 link
的符号连接。
简单来说就是建立软链达成bypass。
代码实现如下:
首先是创建一个link,将tmplink用相对路径指向abc/abc/abc/abc,然后再创建一个link,将exploit指向tmplink/../../../../etc/passwd,此时就相当于exploit指向了abc/abc/abc/abc/../../../../etc/passwd,也就相当于exploit指向了./etc/passwd,此时删除tmplink文件后再创建tmplink目录,此时就变为/etc/passwd成功跨目录。 访问exploit即可读取到/etc/passwd。
glob查找匹配的文件路径模式,是php自5.3.0版本起开始生效的一个用来筛选目录的伪协议
常用bypass方式如下:但会发现比较神奇的是只能列举根目录下的文件。
chdir是更改当前工作路径。
利用了ini_set的open_basedir的设计缺陷,可以用如下代码观察一下其bypass过程:
该函数的第二个参数为一个文件路径,先看代码: 可以看到当文件不存在时返回值为false,因为不支持通配符,该方法只能适用于linux下的暴力猜解文件。
同样是基于报错,但realpath在windows下可以使用通配符进行列举,脚本摘自p神博客:
如命令执行事实上是不受open_basedir的影响的。
bypass disable function蚁剑项目仓库中有一个各种disable的测试环境可以复现,需要环境的师傅可以选用蚁剑的环境。
https://github.com/AntSwordProject/AntSword-Labs
黑名单突破这个应该是最简单的方式,就是寻找替代函数来执行,如system可以采用如反引号来替代执行命令。
看几种常见用于执行系统命令的函数
system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,``
当然了这些也常常出现在disable function中,那么可以寻找可以比较容易被忽略的函数,通过函数 or 函数组合拳来执行命令。
-
反引号:最容易被忽略的点,执行命令但回显需要配合其他函数,可以反弹shell
-
pcntl_exec:目标机器若存在python,可用php执行python反弹shell
原理
本质是利用bash破壳漏洞(CVE-2014-6271)。
影响范围在于bash 1.14 – 4.3
关键在于:
目前的bash脚本是以通过导出环境变量的方式支持自定义函数,也可将自定义的bash函数传递给子相关进程。一般函数体内的代码是不会被执行,但此漏洞会错误的将“{}”花括号外的命令进行执行。
本地验证方法:
在shell中执行下面命令:
env x='() { :;}; echo Vulnerable CVE-2014-6271 ' bash -c "echo test"
执行命令后,如果显示Vulnerable CVE-2014-6271,证系统存在漏洞,可改变echo Vulnerable CVE-2014-6271为任意命令进行执行。
详见:https://www.antiy.com/response/CVE-2014-6271.html
因为是设置环境变量,而在php中存在着putenv可以设置环境变量,配合开启子进程来让其执行命令。
利用
https://www.exploit-db.com/exploits/35146 将exp上传后即可执行系统命令bypass disable,就不做过多赘述。
原理
漏洞源于CVE-2016-3714,ImageMagick是一款图片处理程序,但当用户传入一张恶意图片时,会造成命令注入,其中还有其他如ssrf、文件读取等,当然最致命的肯定是命令注入。
而在漏洞出来之后各位师傅联想到php扩展中也使用了ImageMagick
,当然也就存在着漏洞的可能,并且因为漏洞的原理是直接执行系统命令,所以也就不存在是否被disable的可能,因此可以被用于bypass disable。
关于更加详细的漏洞分析请看p神的文章:CVE-2016-3714 - ImageMagick 命令执行分析,我直接摘取原文中比较具有概括性的漏洞说明:
漏洞报告中给出的POC是利用了如下的这个委托:
它在解析https图片的时候,使用了curl命令将其下载,我们看到%M被直接放在curl的最后一个参数内。ImageMagick默认支持一种图片格式,叫mvg,而mvg与svg格式类似,其中是以文本形式写入矢量图的内容,而这其中就可以包含https处理过程。 所以我们可以构造一个.mvg格式的图片(但文件名可以不为.mvg,比如下图中包含payload的文件的文件名为vul.gif,而ImageMagick会根据其内容识别为mvg图片),并在https://后面闭合双引号,写入自己要执行的命令
push graphic-context
viewbox 0 0 640 480
fill 'url(https://"|id; ")'
pop graphic-context
这样,ImageMagick在正常执行图片转换、处理的时候就会触发漏洞。
漏洞的利用极其简单,只需要构造一张恶意的图片,new一个类即可触发该漏洞:
利用
那么依旧以靶场题为例,依旧以拥有一句话马儿为前提,我们首先上传一个图片,如上面所述的我们图片的后缀无需mvg,因此上传一个jpg图片:
那么因为我们看不到回显,所以可以考虑将结果写入到文件中,或者直接执行反弹shell。然后如上上传一个poc.php:
访问即可看到我们写入的文件。那么这一流程颇为繁琐(当我们需要多次执行命令进行测试时就需要多次调整图片内容),因此我们可以写一个php马来动态传入命令:
喜闻乐见的LD_PRELOAD,这是我学习web时遇到的第一个bypass disable的方式,个人觉得很有意思。
原理
LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),它允许你定义在程序运行前优先加载的动态链接库。这个功能主要就是用来有选择性的载入不同动态链接库中的相同函数。通过这个环境变量,我们可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数库。一方面,我们可以以此功能来使用自己的或是更好的函数(无需别人的源码),而另一方面,我们也可以以向别人的程序注入程序,从而达到特定的目的。
而我们bypass的关键就是利用LD_PRELOAD加载库优先的特点来让我们自己编写的动态链接库优先于正常的函数库,以此达成执行system命令。
因为id命令比较易于观察,网上文章也大同小异采用了id命令下的getuid/getgid来做测试,为做个试验笔者换成了
我们先看看id命令的调用函数:
strace -f /usr/bin/id
Resulut:
close(3) = 0
geteuid32() = 0
getuid32() = 0
getegid32() = 0
getgid32() = 0
(省略....)
getgroups32(0, NULL) = 1
getgroups32(1, [0]) = 1
这里可以看到有不少函数可以编写,我选择getgroups32,我们可以用man命令查看一下函数的定义:
man getgroups32
看到这一部分:
得到了函数的定义,我们只需要编写其内的getgroups即可,因此我编写一个hack.c:、
#include
#include
#include
int getgroups(int size, gid_t list[]){
unsetenv("LD_PRELOAD");
system("echo 'i hack it'");
return 1;
}
然后使用gcc编译成一个动态链接库:
gcc -shared -fPIC hack.c -o hack.so
使用LD_PRELOAD加载并执行id命令,我们会得到如下的结果:
再来更改一下uid测试,我们先adduser一个新用户hhhm,执行id命令结果如下:
然后根据上面的步骤取得getuid32的函数定义,据此来编写一个hack.c:
gcc编译后,执行,结果如下:
可以看到我们的uid成功变为1,且更改为root了,当然了因为我们的hack.so是root权限编译出来的,在一定条件下也许可以用此种方式来提权,网上也有相关文章,不过我没实际尝试过就不做过分肯定的说法。
下面看看在php中如何配合利用达成bypass disable。
php中的利用
php中主要是需要配合putenv函数,如果该函数被ban了那么也就没他什么事了,所以bypass前需要观察disable是否ban掉putenv。
php中的利用根据大师傅们的文章我主要提取出下面几种利用方式,其实质都是大同小异,需要找出一个函数然后采用相同的机制覆盖掉其函数进而执行系统命令。
那么我们受限于disable,system等执行系统命令的函数无法使用,而若想要让php调用外部程序来进一步达成执行系统命令从而达成bypass就只能依赖与php解释器本身。
因此有一个大前提就是需要从php解释器中启动子进程。
老套路之mail
先选取一台具有sendmail的机器,笔者是使用kali,先在php中写入如下代码
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录