【问题标题】:How can I prevent SSRF via pathinfo passing a URL in PHP?如何通过路径信息在 PHP 中传递 URL 来防止 SSRF?
【发布时间】:2021-04-11 14:28:38
【问题描述】:
在使用 Acunetix 扫描我们的代码以查找漏洞后,我们遇到了以下脚本的问题:
"对域 hit0yPI7kOCzl.bxss.me 发起了一个 HTTP 请求
这表明该脚本易受 SSRF(服务器端
请求伪造)。”
如何防止这种情况发生?
<?php
$filename = strip_tags($_GET['url']);
if (substr($filename,0,4) !== 'http') {
die("Need a valid URL...");
}
$ext = pathinfo($filename, PATHINFO_EXTENSION);
switch ($ext) {
case "gif":
header('Content-Type: image/gif');
readfile($filename);
break;
case "png":
header('Content-Type: image/png');
readfile($filename);
break;
case "jpg":
default:
header('Content-Type: image/jpeg');
readfile($filename);
break;
}
?>
【问题讨论】:
标签:
php
csrf
csrf-protection
ssrf
【解决方案1】:
来源,如果您的问题是您的服务器将尝试从任何传递的 url 获取数据。鉴于它在url 参数内有http://google.com,脚本将响应实际的谷歌网站内容。
为什么不好?例如,这可能会被利用来绕过您的防火墙设置、访问服务器的内部网络或污染套接字连接,从而使您的服务器无法连接或无法连接并无响应。
首先,您应该考虑是否真的想用 PHP 提供静态文件。这个责任很可能会委托给 Web 服务器。它甚至可以使用当前的网络服务器从 3rd 方网站“提供”静态内容,因此您应该认真考虑摆脱该代码。
如果您在这种情况下 100% 确定要与 PHP 一起使用,则应在代码中添加限制。
- 添加域白名单,这样就只允许在
url变量内使用受信任的域列表;
- 不要处理扩展名未知的文件。
在这种情况下,代码将如下所示:
<?php
$whitelist = [
'some.whitelisted.com',
'other.whitelisted.com'
];
$extensionMap = [
'gif' => 'image/gif',
'png' => 'image/png',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg'
];
$filename = strip_tags($_GET['url']);
$host = parse_url($filename, PHP_URL_HOST);
if(empty($host) || !in_array($host, $whitelist)) {
header('HTTP/1.1 404 Not Found');
exit;
}
$ext = pathinfo($filename, PATHINFO_EXTENSION);
if(!isset($extensionMap[$ext])) {
header('HTTP/1.1 404 Not Found');
exit;
}
header(sprintf('Content-Type: %s', $extensionMap[$ext]));
readfile($filename);