主页 > 网络知识 > 绕过Disable Functions来搞事情(6)

绕过Disable Functions来搞事情(6)

[De1CTF2020]check in这道题利用的便是这个思路,常见于文件上传中。

通过攻击 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方面的知识了,下面我们再来继续补充一下。

Fast-CGI

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

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指定,其结构如下:

typedef struct { HEAD unsigned char version; //版本 unsigned char type; //类型 unsigned char requestIdB1; //id unsigned char requestIdB0; unsigned char contentLengthB1; //body大小 unsigned char contentLengthB0; unsigned char paddingLength; //额外大小 unsigned char reserved; BODY unsigned char contentData[contentLength];//主要内容 unsigned char paddingData[paddingLength];//额外内容 }FCGI_Record;

详情请看:

PHP-FPM

前面说了那么多了,那PHP-FPM到底是个什么东西呢?

其实FPM就是Fastcgi的协议解析器,Web服务器使用CGI协议封装好用户的请求发送给谁呢? 其实就是发送给FPM。FPM按照CGI的协议将TCP流解析成真正的数据。

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

{ 'GATEWAY_INTERFACE': 'FastCGI/1.0', 'REQUEST_METHOD': 'GET', 'SCRIPT_FILENAME': '/var/www/html/index.php', 'SCRIPT_NAME': '/index.php', 'QUERY_STRING': '?a=1&b=2', 'REQUEST_URI': '/index.php?a=1&b=2', 'DOCUMENT_ROOT': '/var/www/html', 'SERVER_SOFTWARE': 'php/fcgiclient', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': '12345', 'SERVER_ADDR': '127.0.0.1', 'SERVER_PORT': '80', 'SERVER_NAME': "localhost", 'SERVER_PROTOCOL': 'HTTP/1.1' }

这个数组其实就是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代码吗?答案是肯定的,但是前提是我们需要突破几个限制。

第一个限制

说点什么吧
  • 全部评论(0
    还没有评论,快来抢沙发吧!