一、什么是服务器请求伪造(SSRF)
服务器请求伪造(Server-Side Request Forgery,SSRF)。
由攻击者构造的攻击链接传给服务端执行造成的漏洞,一般用来在外网探测或攻击内网服务。
简单示例:
利用file协议查看文件
curl -v 'file:///etc/passwd'
curl -v 'http://www.yb.com:80/sec/ssrf.php?url=file:///etc/passwd'
利用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攻击
https://joychou.org/web/phpssrf.html
https://www.cnblogs.com/flokz/p/weblogic_SSRF.html
https://www.cnblogs.com/flokz/p/ssrf.html
三、PHP中的SSRF漏洞防御
1、没有特殊必要的情况下,不要从用户那里接收要访问的url(不相信任何用户输入原则),防止用户自行构建 URL 进行穿透访问。
2、开启PHP的 open_basedir 配置,将 PHP 的访问限制在特定目录下,禁止PHP随意访问服务器任意路径
#在php.ini中设置,限定PHP的访问目录为/data
open_basedir = /data
开启 open_basedir 可以有效防止 file_get_contents、curl、fopen 等函数对服务器敏感文件的访问。
3、如果必须接收用户传递的 url,则可以使用白名单机制
<?php
declare(strict_types = 1);
$url = $_GET['url'];
// 请求url信息
$urlInfo = parse_url($url);
// 限制请求协议,仅允许http和https请求,防止类似file:///、gopher://、ftp://等引起的安全问题
$validSchemeList = ['http', 'https'];
// 限制允许请求到的地址
$validHostList = ['www.baidu.com'];
// 限制请求的端口为http常用的端口
$validPortList = ['80', '443'];
// 只允许用户访问特定的文件类型
$validTypeList = ['html', 'json', 'gif', 'png', 'jpeg', 'jpg'];
// 不允许访问本地指定的host(避免被用来获取内网数据)
$invalidHostList = ['127.', 'localhost', '192.', '10.'];
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('访问地址非法');
}
}