您的位置 首页 php

提权之disable_functions(二)

前言

在第一篇文章中我们介绍了pentl_exec和LD_PRELOAD两种利用方式,在本篇文章中,我们将继续介绍其余几种利用方式,其中就有ShellShock、php-FPM等,下面来看具体分析。

bypass ShellShock(CVE-2014-6271)

利用条件

  • Linux 操作系统
  • putenv() main()或者error_log()函数可用
  • 目标系统的/bin/bash存在CVE-2014-6271漏洞 /bin/sh -> /bin/bash sh 默认shell是bash

原理

该方法利用的是bash中的⼀个老漏洞Bash Shellshock破壳漏洞,该漏洞的成因是Bash使用的环境变量是通过函数名称来调用的,导致该漏洞出现是以(){开头定义的环境变量在命令ENV中解析成函数后,Bash执行并未退出,而是继续解析并执行shell命令。而核心的原因在于输入的过滤中没有严格限制边界,也没有做出合法化的参数判断⼀般函数体内的代码不会被执行,但破壳漏洞会错误的将{}花括号外的命令进行执行PHP里的某些函数(例如:mail()、 imap_mail())能调用popen或其他能够派生bash子进程的函数,可以通过这些函数来触发破壳漏洞(CVE-2014-6271)执行命令。

利用

docker-compose up -d 尝试利用system命令失败,Ant虚拟终端已经完成了对shellshock的利用,直接执行命令:

或者手动上传文件到/var/tmp目录:

利用include函数包含利用:

bypass Apache Mod CGI

使用条件

  • Linux操作系统
  • Apache + php apache使用apache_mod_php Apache开启了cgi
  • rewrite Web目录给了AllowOverride权限
  • 当前目录可写

原理

早期的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文件进行配置,如下:

这样便会将当前目录下所有的.huahua文件当做CGI程序执行了。由于CGI程序可以执行命令,那我们可以利用CGI来执行系统命令绕过disable_functions。

利用方法

  • 创建.htaccess文件 (需要在其Linux环境下创建 因为编码问题);
  • 创建shell.hua文件(需要在其Linux环境下创建 因为编码问题)。
 #!/bin/sh echo Content-type:text/html echo"" echo&&whoami  

上传完成后,利用chmod(’shell.huahua’,0777);添加执行权限,然后访问shell.huahua 成功执行。

bypass PHP-FPM

Linux操作系统 PHP-FPM 存在可写的目录,需要上传.so文件。

既然是利用PHP-FPM,我们首先需要了解⼀下什么是PHP-FPM,研究过apache或者nginx的人都知道,早期的Web服务器负责处理全部请求,其接收到请求,读取文件,然后传输过去。换句话说,早期的Web服务器只处理Html等静态Web资源。但是随着技术发展,出现了像PHP等动态语言来丰富Web,形成动态Web资源,这时Web服务器就处理不了了,那就交给PHP解释器来处理吧!交给PHP解释器处理很好,但是,PHP解释器该如何与Web服务器进行通信呢?为了解决不同的语言解释器(如php、 python解释器)与Web服务器的通信,于是出现了CGI协议。只要你按照CGI协议去编写程序,就能实现语言解释器与Web服务器的通信。如PHP-CGI程序。其实,在上⼀节中我们已经了解了CGI以及Apache Mod CGI方面的知识了,下面我们再来继续补充⼀下 !

1)Fast-CGI

有了CGI,自然就解决了Web服务器与PHP解释器的通信问题,但是Web服务器有⼀个问题,就是它每收到⼀个请求,都会去Fork⼀ 个CGI进程,请求结束再kill掉这个进程,这样会很浪费资源。于是,便出现了CGI的改良版本——Fast-CGI。Fast-CGI每次处理完请求后,不会kill掉这个进程,而是保留这个进程,使这个进程可以⼀次处理多个请求(注意与另⼀个Apache Mod CGI区别),这样就会大大的提高效率。

2)Fast-CGI Record

CGI/Fastcgi其实是⼀个通信协议,和HTTP协议⼀样,都是进行数据交换的⼀个通道。HTTP协议是浏览器和服务器中间件进行数据交换的协议,浏览器将HTTP头和HTTP体用某个规则组装成数据包,以TCP的方式发送到服务器中间件,服务器中间件按照规则将数据包解码,并按要求拿到用户需要的数据,再以HTTP协议的规则打包返回给服务器。类比HTTP协议来说,CGI协议是Web服务器和解释器进行数据交换的协议,它由多条record组成,每⼀条record都和HTTP⼀样,也由header和body组成,Web服务器将这二者按照CGI规则封装好发送给解释器,解释器解码之后拿到具体数据进行操作,得到结果之后再次封装好返回给Web服务器。和HTTP头不同,record的header头部固定的是8个字节,body是由头中的contentLength指定,其结构如下:

3)PHP-FPM

前面说了那么多了,那PHP-FPM到底是个什么东西呢? 其实FPM就是Fastcgi的协议解析器,Web服务器使用CGI协议封装好用户的请求发送给谁呢? 其实就是发送给FPM。FPM按照CGI的协议将TCP流解析成真正的数据。

举个例子,用户访问 时,如果web目录是 /var/www/html ,那么Nginx会将这个请求变成如下key-value对:

这个数组其实就是PHP中 $_SERVER 数组的⼀部分,也就是PHP里的环境变量。但环境变量的作用不仅是填充 $_SERVER 数组,也是告诉fpm:“我要执行哪个PHP文件”。PHP-FPM拿到Fastcgi的数据包后,进行解析,得到上述这些环境变量。然后,执行SCRIPT_FILENAME 的值指向的PHP文件,也就是 /var/www/html/index.php 。

如何攻击

这里由于FPM默认监听的是9000端口,我们就可以绕过Web服务器,直接构造Fastcgi协议,和fpm进行通信。于是就有了利用Webshell直接与FPM通信来绕过disable functions的姿势。因为前面我们了解了协议原理和内容,接下来就是使用CGI协议封装请求,通过Socket来直接与FPM通信。但是能够构造Fastcgi,就能执行任意PHP代码吗?答案是肯定的,但是前提是我们需要突破几个限制:

  • 第⼀个限制

既然是请求,那么 SCRIPT_FILENAME 就相当的重要,因为前面说过,fpm是根据这个值来执行PHP文件的,如果不存在,会直接返回404,所以想要利用好这个漏洞,就得找到⼀个已经存在的PHP文件,好在⼀般进行源安装PHP的时候,服务器都会附带上⼀些PHP文件,如果说我们没有收集到目标Web目录信息的话,可以试试这种办法。

  • 第二个限制

即使我们能控制 SCRIPT_FILENAME ,让fpm执行任意文件,也只是执行目标服务器上的文件,并不能执行我们需要其执行的文件。那要如何绕过这种限制呢?我们可以从 php.ini 入手。它有两个特殊选项,能够让我们去做到任意命令执行,那就是 auto_prepend_file 和 auto_append_file 。auto_prepend_file 的功能是在执行目标文件之前,先包含它指定的文件。那么就有趣了,假设我们设置 auto_prepend_file 为 php://input ,那么就等于在执行任何PHP文件前都要包含⼀遍POST过去的内容。所以,我们只需要把待执行的代码放在POST Body中进⾏远程文件包含,这样就能做到任意代码执行了。

  • 第三个限制

我们虽然可以通过远程文件包含执行任意代码,但是远程文件包含是有 allow_url_include 这个限制因素的,如果没有为ON的话就没有办法进行远程文件包含,那要怎么设置呢? 这里,PHP-FPM有两个可以设置PHP配置项的KEY-VALUE,即 PHP_VALUE 和 PHP_ADMIN_VALUE。PHP_VALUE 可以用来设置php.ini, PHP_ADMIN_VALUE 则可以设置所有选项(disable_functions 选项除外),这样就解决问题了。所以,我们最后构造的请求如下:

该请求设置了 auto_prepend_file = php://input 且 allow_url_include = On ,然后将我们需要执行的代码放在Body中,即可执行任意代码了。

利用方法

服务器配置了FPM/Fastcgi

直接利用蚁剑中的bypass disablefunc插件

需要配置FPM/FCGI地址默认为unix://本地Socket ,但如果配置成TCP默认是127.0.0.1:9000

所以此处选127.0.0.1:9000

小结

绕过disable_function这是一个非常令人头疼的问题,具体体现在已经拿到了webshell,如果进一步攻击,其中也可能会遇到一些汇编等底层知识,这就需要更加深入且细致的研究。

文章来源:智云一二三科技

文章标题:提权之disable_functions(二)

文章地址:https://www.zhihuclub.com/78153.shtml

关于作者: 智云科技

热门文章

网站地图