浅析SSRF与文件读取的一些小特性
字数 1417 2025-08-25 22:59:02

SSRF与文件读取特性深度分析

0x00 前言

本文深入分析SSRF(Server-Side Request Forgery)与文件读取中的一些特殊行为特性,特别是file_get_contentscurl在处理URL时的差异,这些差异可能导致安全漏洞或绕过防御机制。

0x01 问题现象

当使用不同函数处理URL时,会出现以下差异:

  • 请求http://127.0.0.1/1.php?.jpg
    • 使用curl:访问的是1.php的内容
    • 使用file_get_contents:尝试访问名为1.php?.jpg的文件

这种差异源于URL解析方式的不同,下面将从PHP底层和libcurl实现角度分析原因。

0x02 file_get_contents底层分析

2.1 实现原理

file_get_contents在PHP中的实现位于/ext/standard/file.c,关键流程:

  1. 解析参数后调用php_stream_open_wrapper_ex
  2. 通过php_stream_locate_url_wrapper解析协议类型
  3. 根据协议找到对应的wrapper(包装器)

2.2 关键特性

  • 对于file://协议:

    • 需要绝对路径,格式为file:///path/to/file
    • 不会特殊处理?#后面的内容
    • 例如file:///flag.php?#123会尝试打开名为flag.php?#123的文件
  • 对于HTTP协议:

    • 会完整保留URL中的查询参数和片段标识符
    • 行为更符合标准URL规范

0x03 curl底层分析

3.1 libcurl实现

PHP的curl扩展基于libcurl实现,关键函数调用链:

  1. curl_init()初始化
  2. curl_easy_setopt()设置选项(包括URL)
  3. curl_easy_perform()执行请求

3.2 URL解析特性

libcurl在解析URL时:

  1. 对于file://协议:

    • 会忽略查询参数(?后内容)和片段标识符(#后内容)
    • 例如file:///flag.php?123实际访问的是flag.php
    • 实现位于lib/urlapi.ccurl_url_get函数
  2. 对于HTTP协议:

    • 保留完整URL路径但可能在某些情况下规范化处理

0x04 安全影响与利用场景

4.1 文件读取绕过

当应用程序同时使用两种函数进行文件读取时,可能产生不一致行为:

$url = $_GET['url'];
$file = $url . '.jpg';

// 第一种情况:使用file_get_contents
file_get_contents($url);  // 尝试读取"url?.jpg"
file_get_contents($file); // 尝试读取"url.jpg"

// 第二种情况:使用curl
curl_exec($url);  // 读取"url"内容
curl_exec($file); // 读取"url.jpg"内容

4.2 SSRF利用差异

  • file_get_contents

    • 严格遵循URL规范
    • 可能被用于读取带特殊字符的文件名
  • curl

    • 自动去除某些特殊部分
    • 可能绕过某些文件名过滤

0x05 防御建议

  1. 统一处理函数:避免混用不同函数处理相同URL
  2. 严格过滤:对用户输入的URL进行严格校验和规范化
  3. 协议限制:明确允许或禁止的协议列表
  4. 路径检查:确保文件路径不包含特殊字符
  5. 错误处理:统一错误处理逻辑,避免信息泄露

0x06 总结

  • file_get_contentscurl对URL解析存在本质差异
  • libcurl对file://协议的处理会忽略查询参数和片段
  • PHP的流处理更接近原始URL规范
  • 这些差异可能导致安全边界被绕过,需要特别注意

理解这些底层实现细节有助于开发更安全的代码和设计更有效的防御措施。

SSRF与文件读取特性深度分析 0x00 前言 本文深入分析SSRF(Server-Side Request Forgery)与文件读取中的一些特殊行为特性,特别是 file_get_contents 与 curl 在处理URL时的差异,这些差异可能导致安全漏洞或绕过防御机制。 0x01 问题现象 当使用不同函数处理URL时,会出现以下差异: 请求 http://127.0.0.1/1.php?.jpg : 使用 curl :访问的是 1.php 的内容 使用 file_get_contents :尝试访问名为 1.php?.jpg 的文件 这种差异源于URL解析方式的不同,下面将从PHP底层和libcurl实现角度分析原因。 0x02 file_ get_ contents底层分析 2.1 实现原理 file_get_contents 在PHP中的实现位于 /ext/standard/file.c ,关键流程: 解析参数后调用 php_stream_open_wrapper_ex 通过 php_stream_locate_url_wrapper 解析协议类型 根据协议找到对应的wrapper(包装器) 2.2 关键特性 对于 file:// 协议: 需要绝对路径,格式为 file:///path/to/file 不会特殊处理 ? 或 # 后面的内容 例如 file:///flag.php?#123 会尝试打开名为 flag.php?#123 的文件 对于HTTP协议: 会完整保留URL中的查询参数和片段标识符 行为更符合标准URL规范 0x03 curl底层分析 3.1 libcurl实现 PHP的curl扩展基于libcurl实现,关键函数调用链: curl_init() 初始化 curl_easy_setopt() 设置选项(包括URL) curl_easy_perform() 执行请求 3.2 URL解析特性 libcurl在解析URL时: 对于 file:// 协议: 会忽略查询参数( ? 后内容)和片段标识符( # 后内容) 例如 file:///flag.php?123 实际访问的是 flag.php 实现位于 lib/urlapi.c 的 curl_url_get 函数 对于HTTP协议: 保留完整URL路径但可能在某些情况下规范化处理 0x04 安全影响与利用场景 4.1 文件读取绕过 当应用程序同时使用两种函数进行文件读取时,可能产生不一致行为: 4.2 SSRF利用差异 file_get_contents : 严格遵循URL规范 可能被用于读取带特殊字符的文件名 curl : 自动去除某些特殊部分 可能绕过某些文件名过滤 0x05 防御建议 统一处理函数 :避免混用不同函数处理相同URL 严格过滤 :对用户输入的URL进行严格校验和规范化 协议限制 :明确允许或禁止的协议列表 路径检查 :确保文件路径不包含特殊字符 错误处理 :统一错误处理逻辑,避免信息泄露 0x06 总结 file_get_contents 和 curl 对URL解析存在本质差异 libcurl对 file:// 协议的处理会忽略查询参数和片段 PHP的流处理更接近原始URL规范 这些差异可能导致安全边界被绕过,需要特别注意 理解这些底层实现细节有助于开发更安全的代码和设计更有效的防御措施。