php-fpm未授权访问漏洞

目录

前置知识

Fastcgi简介

record结构

环境变量

PHP-FPM简介

例子

Nginx(IIS7)解析漏洞

漏洞原因

解决方法

在php-fpm中解析的过程

php-fpm未授权访问漏洞漏洞原因

payload构造


前置知识

Fastcgi简介

想要了解php-fpm就先要知道Fastcgi,Fastcgi其实是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。fastcgi协议则是服务器中间件和某个语言后端进行数据交换的协议。Fastcgi协议由多个record组成,record也有header和body一说,服务器中间件将这二者按照fastcgi的规则封装好发送给语言后端,语言后端解码以后拿到具体数据,进行指定操作,并将结果再按照该协议封装好后返回给服务器中间件。

record结构

typedef struct {
  /* Header */
  unsigned char version; // 版本
  unsigned char type; // 本次record的类型,因为fastcgi一个record的大小是有限的,作用也是单一的,所以我们需要在一个TCP流里传输多个record。通过`type`来标志每个record的作用,用`requestId`作为同一次请求的id。
  unsigned char requestIdB1; // 本次record对应的请求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;

语言端解析了fastcgi头以后,拿到contentLength,然后再在TCP流里读取大小等于contentLength的数据,这就是body体。

环境变量

当后端语言收到type为4的record后,就会把这个record的body按照对应的结构解析成key-value对,这就是环境变量。

PHP-FPM简介

FPM其实是一个fastcgi协议解析器,Nginx等服务器中间件将用户请求按照fastcgi的规则打包好通过TCP传给谁?其实就是传给FPM。FPM按照fastcgi的协议将TCP流解析成真正的数据。

例子

用户访问http://127.0.0.1/index.php?a=1&b=2,如果web目录是/var/www/html,那么Nginx会将这个请求变成如下key-value对,这就是环境变量,然后这个环境变量的作用不仅是填充$_SERVER数组,也是告诉fpm:“我要执行哪个PHP文件”。

{
    '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'
}

Nginx(IIS7)解析漏洞

下面以例子来解释一下这个漏洞,在volhub搭建好环境,在搭建好的环境下有一个图片码

然后在docker映射的端口访问这个图片马的路径后面再加一个不存在的路径如下,aaaa.php不存在

http://192.168.244.152:9090/uploadfiles/nginx.png/aaaa.php

然后在aaaa.php不存在的情况下图片马被以php方式执行了

漏洞原因

在php.ini文件中开启起了cgi.fix_pathinifo这个配置选项,这参数配置了以后可以自动修复路径。当当前文件找不到以后,php就会向上找文件,直到找到文件,在上面的例子中就是aaaa.php找不到后就去找nginx.png文件,找到了nginx.png后,以php方式执行。

解决方法

不开启cgi.fix_pathinifo这个配置选项

在php-fpm自配置文件路径中有一个安全字段security.limit_extensions这个字段可以规定php可以解析的文件,将这个字段设置成.php后没有办法解析其他的了

在php-fpm中解析的过程

用户请求http://192.168.244.152:9090/uploadfiles/nginx.png/aaaa.php时,nginx将会发送如下环境变量到fpm里:

{
    ...
    'SCRIPT_FILENAME': '/var/www/html/uploadfiles/nginx.png/aaaa.php',
    'SCRIPT_NAME': 'aaaa.php',
    'REQUEST_URI': '/uploadfiles/nginx.png/aaaa.php',
    'DOCUMENT_ROOT': '/var/www/html',
    ...
}

php-fpm未授权访问漏洞漏洞原因

(前置知识完了下面来看一下正主)

一些开发者为了方便将自己设备的9000端口开放在公网上,而且PHP-FPM默认监听9000端口,然后其他人就可以访问他PHP-FPM。

然后攻击者可以访问其他人的PHP-FPM后,攻击者可以构造fastcgi的数据,然后让对方来处理。

这时'SCRIPT_FILENAME'这个环境变量的值就很重要了,因为fpm时根据这个值来执行PHP,文件不存在就返回404

在fpm某个版本之前,我们可以将SCRIPT_FILENAME的值指定为任意后缀文件,比如/etc/passwd;但是后来就加了security.limit_extensions这个字段。就只可以解析php的文件了。

payload构造

这里使用脚本,在没有进行任何配置的时候脚本运行失败,这是因为security.limit_extensions这个字段被设置了只允许php执行,然后我们可以执行对方服务器的任意php代码,对方的服务器肯定会有php代码,因为在装php-fpm的时候就会带有php代码,但是好像意义不大,但是不急接着往下看

php配置文件中中有两个字段auto_prepend_fileauto_append_fileauto_prepend_file在执行目标文件之前,先包含auto_prepend_file中指定的文件;auto_append_file是告诉PHP,在执行完成目标文件后,包含auto_append_file指向的文件。

若是我们可以控制auto_prepend_file这个字段,且将这个字段者只为php://input,那我们在执行目标php代码前就可以执行POST的内容(注:还需要开启远程文件包含选项allow_url_include)

那么我们如何设置auto_prepend_file,这就又要看php-fpm的环境变量了。在php-fpm中又有两个环境变量就是用来设置php配置项的,PHP_VALUE可以设置模式

好准备工作做完了,现在开始使用脚本构造payload

构造后的payload ,那两个字段已经被设置了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值