本文涉及知识点实操练习-绕过函数过滤(复制链接做实验)
https://www.hetianlab.com/expc.do?ec=ECID172.19.104.182014092310094200001&pk_campaign=jinritoutiao-wemedia
是否碰着过费劲九牛二虎之力拿了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神博客原文,这里仅作简单总结。
syslink
https://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()
chdir是变动当前事情路径。
利用了ini_set的open_basedir的设计毛病,可以用如下代码不雅观察一下其bypass过程:
bindtextdomain
该函数的第二个参数为一个文件路径,先看代码:
可以看到当文件不存在时返回值为false,由于不支持通配符,该方法只能适用于linux下的暴力猜解文件。
Realpath
同样是基于报错,但realpath在windows下可以利用通配符<和>进行列举,脚本摘自p神博客:
other
如命令实行事实上是不受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 函数组合拳来实行命令。
反引号:最随意马虎被忽略的点,实行命令但回显须要合营其他函数,可以反弹shellpcntl_exec:目标机器若存在python,可用php实行python反弹shellShellShock
事理
实质是利用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,就不做过多赘述。
ImageMagick
事理
漏洞源于CVE-2016-3714,ImageMagick是一款图片处理程序,但当用户传入一张恶意图片时,会造成命令注入,个中还有其他如ssrf、文件读取等,当然最致命切实其实定是命令注入。
而在漏洞出来之后各位师傅遐想到php扩展中也利用了ImageMagick,当然也就存在着漏洞的可能,并且由于漏洞的事理是直接实行系统命令,以是也就不存在是否被disable的可能,因此可以被用于bypass disable。
关于更加详细的漏洞剖析请看p神的文章:CVE-2016-3714 - ImageMagick 命令实行剖析,我直接摘取原文中比较具有概括性的漏洞解释:
漏洞报告中给出的POC是利用了如下的这个委托:
<delegate decode="https" command=""curl" -s -k -o "%o" "https:%M""/>
它在解析https图片的时候,利用了curl命令将其下载,我们看到%M被直接放在curl的末了一个参数内。ImageMagick默认支持一种图片格式,叫mvg,而mvg与svg格式类似,个中因此文本形式写入矢量图的内容,而这个中就可以包含https处理过程。以是我们可以布局一个.mvg格式的图片(但文件名可以不为.mvg,比如下图中包含payload的文件的文件名为vul.gif,而ImageMagick会根据其内容识别为mvg图片),并在https://后面闭合双引号,写入自己要实行的命令
push graphic-contextviewbox 0 0 640 480fill 'url(https://"|id; ")'pop graphic-context
这样,ImageMagick在正常实行图片转换、处理的时候就会触发漏洞。
漏洞的利用极其大略,只须要布局一张恶意的图片,new一个类即可触发该漏洞:
利用
那么依旧以靶场题为例,依旧以拥有一句话马儿为条件,我们首先上传一个图片,如上面所述的我们图片的后缀无需mvg,因此上传一个jpg图片:
那么由于我们看不到回显,以是可以考虑将结果写入到文件中,或者直接实行反弹shell。然后如上上传一个poc.php:
访问即可看到我们写入的文件。那么这一流程颇为繁琐(当我们须要多次实行命令进行测试时就须要多次调度图片内容),因此我们可以写一个php马来动态传入命令:
LD_PRELOAD
喜闻乐见的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) = 0geteuid32() = 0getuid32() = 0getegid32() = 0getgid32() = 0(省略....)getgroups32(0, NULL) = 1getgroups32(1, [0]) = 1
这里可以看到有不少函数可以编写,我选择getgroups32,我们可以用man命令查看一下函数的定义:
man getgroups32
看到这一部分:
得到了函数的定义,我们只须要编写其内的getgroups即可,因此我编写一个hack.c:、
#include <stdlib.h>#include <sys/types.h>#include <unistd.h>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中写入如下代码
<?phpmail("","","","");
同样的可以利用strace来追踪函数的实行过程。
strace -f php phpinfo.php 2>&1 | grep execve
可以看到这里调用了sendmail,与网上的文章同样的我们可以追踪sendmail来查看其调用过程,或者利用readelf可以查看其利用函数:
strace sendmail
那么以上面的办法编写并编译一个动态链接库然后利用LD_PRELOAD去实行我们的命令,这便是老套路的利用。由于没有回显,为方便查看效果我写了一个ls>test,因此hack.c如下:
同样的gcc编译后,页面写入如下:
访问页面得到运行效果如下:
再提一个我在利用过程中走错的点,这里为测试,我换用一台没有sendmail的ubuntu:
但如果我们按照上面的步骤直接追踪index的实行而不过滤选取execve会创造同样存在着geteuid,并且但这事实上是sh调用的而非mail调用的,因此如果我们利用php index.php来调用会创造system实行成功,但如果我们通过页面来访问则会创造实行失落败,这是一个在利用过程中须要把稳的点,这也便是为什么我们会利用管道符来选取execve。第一个execve为php阐明器启动的进程,而后者即为我们所须要的sendmail子进程。
error_log
同样的除了mail会调用sendmail之外,还有error_log也会调用,如图:
ps:当error_log的type为1时就会调用到sendmail。
因此上面针对付mail函数的套路对付error_log同样适用,however,我们会创造此类挟制都只是针对某一个函数,而前面所做的都是依赖与sendmail,而像目标机器如果不存在sendmail,那么前面的做法就完备无用。
yangyangwithgnu师傅在其文无需sendmail:巧用LD_PRELOAD打破disable_functions提到了我们不要局限于仅挟制某一函数,而应考虑挟制共享工具。
挟制共享工具
文中利用到了如下代码编写的库:
那么关于__attribute__ ((__constructor__))个人理解是其会在共享库加载时运行,也便是程序启动时运行,那么这一步的利用同样须要有前面说到的启动子进程这一个大条件,也便是须要有类似于mail、Imagick可以令php阐明器启动新进程的函数。
同样的将LD_PRELOAD指定为gcc编译的共享库,然后访问页面查看,会创造成功将ls写到test下(如果失落败请检讨写权限问题)
0ctf 2019中Wallbreaker Easy中的出题点便是采取了imagick在处理一些特定后缀文件时,会调用ffmpeg,也便是会开启子进程,从而达成加载共享库实行系统命令bypass disable。
Apache Mod CGI
前面的两种利用都须要putenv,如果putenv被ban了那么就须要这种办法,大略先容一下事理。
事理
利用htaccess覆盖apache配置,增加cgi程序达成实行系统命令,事实上同上传htaccess解析png文件为php程序的利用办法大同小异。
mod cgi:
任何具有MIME类型application/x-httpd-cgi或者被cgi-script处理器处理的文件都将被作为CGI脚本对待并由做事器运行,它的输出将被返回给客户端。可以通过两种路子使文件成为CGI脚本,一种是文件具有已由AddType指令定义的扩展名,另一种是文件位于ScriptAlias目录中。
因此我们只需上传一个.htaccess:
利用
利用就很大略了:
上传htaccess,内容为上文所给出的内容上传a.test,内容为:PHP-FPM
php-fpm相信有读者在配置php环境时会碰着,如利用nginx+php时会在配置文件中配置如下:
那么看看百度百科中关于php-fpm的先容:
PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是一个PHPFastCGI管理器,对付PHP 5.3.3之前的php来说,是一个补丁包 [1] ,旨在将FastCGI进程管理整合进PHP包中。如果你利用的是PHP5.3.3之前的PHP的话,就必须将它patch到你的PHP源代码中,在编译安装PHP后才可以利用。
那么fastcgi又是什么?Fastcgi 是一种通讯协议,用于Web做事器与后端措辞的数据交流。
事理
那么我们在配置了php-fpm后如访问http://127.0.0.1/test.php?test=1那么会被解析为如下键值对:
这个数组很眼熟,会创造实在便是$_SERVER里面的一部分,那么php-fpm拿到这一个数组后会去找到SCRIPT_FILENAME的值,对付这里的/var/www/html/test.php,然后去实行它。
前面笔者留了一个配置,在配置中可以看到fastcgi的端口是9000,监听地址是127.0.0.1,那么如果地址为0.0.0.0,也即是将其暴露到公网中,倘若我们假造与fastcgi通信,这样就会导致远程代码实行。
那么事实上php-fpm通信办法有tcp也便是9000端口的那个,以及socket的通信,因此也存在着两种攻击办法。
socket办法的话配置文件会有如下:
fastcgi_pass unix:/var/run/phpfpm.sock;
那么我们可以轻微理解一下fastcgi的协议组成,其由多个record组成,这里摘抄一下p神原文中的一段构造体:
可以看到record分为header以及body,个中header固定为8字节,而body由其contentLength决定,而paddingData为保留段,不须要时长度置为0。
而type的值从1-7有各种浸染,当其type=4时,后端就会将其body解析成key-value,看到key-value可能会很眼熟,没错,便是我们前面看到的那一个键值对数组,也便是环境变量。
那么在学习漏洞利用之前,我们有必要理解两个环境变量,
PHP_VALUE:可以设置模式为 PHP_INI_USER 和 PHP_INI_ALL 的选项PHP_ADMIN_VALUE:可以设置所有选项(除了disable_function)那么以p神文中的利用办法我们须要知足三个条件:
找到一个已知的php文件利用上述两个环境变量将auto_prepend_file设置为php://input开启php://input须要知足的条件:allow_url_include为on此时熟习文件包含漏洞的童鞋就一览无余了,我们可以实行任意代码了。
这里利用的情形为:
利用
我们先直接看phpinfo如何标识我们可否利用该漏洞进行攻击。
那么先以攻击tcp为例,倘若我们假造nginx发送数据(fastcgi封装的数据)给php-fpm,这样就会造成任意代码实行漏洞。
p神已经写好了一个exp,由于开放fastcgi为0.0.0.0的情形事实上同攻击内网相似,以是这里可以考试测验一下攻击127.0.0.1也便是攻击内网的情形,那么事实上我们可以合营gopher协议来攻击内网的fpm,由于与本文主题不符就不多讲。
可以看到结果如图所示:
攻击成功后我们去查看一下phpinfo会看到如下:
也便是说我们布局的攻击包为:
很明显的前面所说的都是成立的;然而事实上我这里是没有加入disable的情形,我们往里面加入disable再考试测验。
pkill php-fpm/usr/sbin/php-fpm7.0 -c /etc/php/7.0/fpm/php.ini
把稳修正了ini文件后重启fpm须要指定ini。
我往disable里压了一个system:
然后再实行一下exp,可以创造被disable了:
因此此种方法还无法达成bypass disable的浸染,那么不要忘了我们的两个php_value能够修正的可不仅仅只是auto_prepend_file,并且的我们还可以修正basedir来绕过;在先前的绕过姿势中我们是利用到了so文件实行扩展库来bypass,那么这里同样可以修正extension为我们编写的so库来实行系统命令,详细利用有师傅已经写了利用脚本,事实上蚁剑中的插件已经能实现了该bypass的功能了,那么下面我直接对蚁剑中插件如何实现bypass做一个简要剖析。
在实行蚁剑的插件时会创造其在当前目录天生了一个.antproxy.php文件,那么我们后续的bypass都是通过该文件来实行,那么先看一下这个shell的代码:
定位到关键代码:
可以看到它这里向60882端口进行通信,事实上这里蚁剑利用/bin/sh -c php -n -S 127.0.0.1:60882 -t /var/www/html开启了一个新的php做事,并且不该用php.ini,因此也就不存在disable了,那么我们在不雅观察其实行过程会创造其还在tmp目录下上传了一个so文件,那么至此我们有情由推断出其通过攻击php-fpm修正其extension为在tmp目录下上传的扩展库,事实上从该插件的源码中也可以得知确实如此:
那么启动了该php server后我们的流量就通过antproxy.php转发到无disabel的php server上,此时就成功达成bypass。