php - 如何通过 PHP 中的路径信息传递 URL 来防止 SSRF?

标签 php csrf csrf-protection ssrf

使用 Acunetix 扫描我们的代码以查找漏洞后,我们遇到了以下脚本的问题:

"An HTTP request was initiated for the domain hit0yPI7kOCzl.bxss.me which indicates that this script is vulnerable to SSRF (Server Side Request Forgery)."

如何防止这种情况发生?

<?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;
}
?>

最佳答案

来源如果您的情况的问题是您的服务器将尝试从任何传递的网址获取数据。鉴于 url 参数内有 http://google.com,脚本将使用实际的 google 网站内容进行响应。

为什么它不好?例如,可能会被利用来绕过您的防火墙设置、访问服务器的内部网络或污染套接字连接,从而使您的服务器将无法连接或被连接并且变得无响应。

首先,您应该考虑是否真的想使用 PHP 提供静态文件。最有可能的是,这个责任可以委托(delegate)给网络服务器。甚至可以使用当前的网络服务器从第三方网站“提供”静态信息,因此您应该认真考虑删除该代码。

如果您 100% 确定要在这种情况下使用 PHP,则应该向您的代码添加限制。

  1. 添加域白名单,以便仅允许在 url 变量内使用可信域列表;
  2. 不要处理具有未知扩展名的文件。

在这种情况下,代码将如下所示:

<?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);

关于php - 如何通过 PHP 中的路径信息传递 URL 来防止 SSRF?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35896093/

相关文章:

java - Play 2.5 对某些请求禁用 csrf 保护

python - Flask-WTF CSRF token 丢失

ruby-on-rails - Rails 无法使用 X-CSRF-TOKEN header 验证 CSRF token 真实性 ajax

node.js - Nodejs 是否有类似于 ruby​​ 的表单助手来生成 CSRF token ?

python - 使用 Flask WTF-Forms 手动生成 CSRF token

php - 如何使用 zend 框架读取 Controller 上的 application.ini

php - Laravel 5.5 将变量传递给子 Controller 返回总是 null?

php - Laravel 的表特化

symfony-forms - 在 Symfony2.1 中手动更改或捕获无效 CSRF token 的消息

php - 如何在mysql中使用join命令获取搜索查询