PHP请求伪造攻击及防护(SSRF)

什么是服务器请求伪造(SSRF)

服务器请求伪造(Server-Side Request Forgery,简称 SSRF)是一种常见的 Web 安全漏洞。其核心原理是攻击者构造恶意攻击链接,传递给服务端并由服务端执行,从而实现对目标服务器所在内网的探测或攻击,突破外网对内网的访问限制,造成敏感信息泄露、内网服务被攻击等安全风险。

简单示例

1. 利用 file 协议查看服务器敏感文件

curl -v 'file:///etc/passwd'
curl -v 'http://www.yb.com:80/sec/ssrf.php?url=file:///etc/passwd'

2. 利用 dict 协议探测服务器端口状态

curl -v 'dict://127.0.0.1:80/info'
curl -v 'http://www.yb.com:8082/ssrf.php?url=dict://127.0.0.1:22'

SSRF 攻击相关参考

PHP 中的 SSRF 漏洞防御方案

1. 核心原则:严格限制用户输入

在没有特殊业务需求的情况下,切勿接收用户传递的待访问 URL。遵循“不相信任何用户输入”的安全原则,从源头杜绝攻击者构造恶意 URL 进行穿透访问的可能。

2. 配置层面:开启 open_basedir 限制

通过配置 PHP 的 open_basedir 参数,将 PHP 程序的文件访问权限限制在特定目录内,禁止其随意访问服务器的任意文件路径,可有效防止 file_get_contentscurlfopen 等文件操作函数访问服务器敏感文件。

配置方法

php.ini 配置文件中添加如下配置,限定 PHP 仅能访问 /data 目录(可根据实际业务需求调整目录路径):

open_basedir = /data

3. 业务必需场景:实施白名单+黑名单双重校验

若业务逻辑必须接收用户传递的 URL,需通过白名单机制明确允许的访问范围,同时结合黑名单拦截危险地址,具体实现代码如下:

<?php
declare(strict_types = 1);

// 获取用户传递的URL参数
$url = $_GET['url'];

// 解析URL信息,提取协议、主机、端口等关键字段
$urlInfo = parse_url($url);

// 1. 白名单配置:明确允许的访问规则
// 允许的请求协议(仅保留http/https,禁止file、gopher、ftp等危险协议)
$validSchemeList = ['http', 'https'];
// 允许的目标地址(根据业务需求限定合法域名)
$validHostList = ['www.baidu.com'];
// 允许的访问端口(仅开放http/https常用端口)
$validPortList = ['80', '443'];
// 允许的文件类型(根据业务场景调整)
$validTypeList = ['html', 'json', 'gif', 'png', 'jpeg', 'jpg'];

// 2. 黑名单配置:拦截内网及危险地址
$invalidHostList = ['127.', 'localhost', '192.', '10.']; // 内网地址特征

// 3. 校验逻辑:依次验证协议、端口、地址、文件类型
// 验证请求协议
if (!in_array($urlInfo['scheme'], $validSchemeList, true)) {
    die('访问协议非法');
}

// 验证访问端口
if (!in_array($urlInfo['port'], $validPortList, true)) {
    die('访问端口非法');
}

// 验证目标地址
if (!in_array($urlInfo['host'], $validHostList, true)) {
    die('请求地址非法');
}

// 验证文件类型
$visitType = pathinfo($url, PATHINFO_EXTENSION);
if (!in_array($visitType, $validTypeList, true)) {
    die('访问类型非法');
}

// 拦截内网地址
foreach ($invalidHostList as $invalidHost) {
    if (strpos($urlInfo['host'], $invalidHost) === 0) {
        die('访问地址非法');
    }
}

防御说明

1. 协议限制

仅允许 httphttps 协议,避免 file(读取文件)、gopher(隧道攻击)、ftp(文件传输)等危险协议带来的风险;

2. 端口限制

仅开放 Web 服务常用的 80(http)和 443(https)端口,减少端口探测和未授权访问风险;

3. 地址限制

通过白名单限定合法访问域名,同时拦截以 127.(本地回环)、192.10.(内网网段)等开头的地址,防止内网穿透;

4. 文件类型限制

仅允许业务必需的文件类型,避免攻击者请求恶意文件。