j0k3r/safecurl

是 'curl_exec' 的直接替代品,旨在防止 SSRF 攻击。

维护者

详细信息

github.com/j0k3r/safecurl

源代码

问题

资助包维护!
j0k3r

3.0.1 2022-10-27 07:49 UTC

This package is auto-updated.

Last update: 2024-08-27 11:42:47 UTC


README

CI Total Downloads License

SafeCurl 旨在作为 PHP 中 curl_exec 函数的直接替代品。SafeCurl 会验证 URL 的每个部分,以白名单或黑名单的形式,以帮助保护免受服务器端请求伪造 (SSRF) 攻击。

有关项目的更多信息,请参阅博客文章 'SafeCurl: SSRF 保护,以及“捕获比特币”'

保护措施

将 URL 的每个部分分解,并对其与白名单或黑名单进行验证。这包括将域名解析为其 IP 地址。

如果您选择启用 "FOLLOWLOCATION",则任何重定向都会被捕获并重新验证。

安装

SafeCurl 可以通过 Composer 包含在任何 PHP 项目中。在 composer.json 文件中的 require 下包含以下内容。

"require": {
    "j0k3r\safecurl": "~3.0"
}

然后更新 Composer。

composer update

使用方法

只需替换 curl_exec 并将其包装在 try {} catch {} 块中即可。

use fin1te\SafeCurl\SafeCurl;
use fin1te\SafeCurl\Exception;

try {
    $url = 'http://www.google.com';

    $curlHandle = curl_init();

    //Your usual cURL options
    curl_setopt($curlHandle, CURLOPT_USERAGENT, 'Mozilla/5.0 (SafeCurl)');

    //Execute using SafeCurl
    $safeCurl = new SafeCurl($curlHandle);
    $response = $safeCurl->execute($url);
} catch (Exception $e) {
    //URL wasn't safe
}

选项

默认选项是不允许访问任何 私有 IP 地址,并且只允许 HTTP(S) 连接。

如果您希望添加自己的选项(例如,将任何请求到您控制的域的黑名单),只需获取一个新的 SimpleCurl\Options 对象,将其添加到白名单或黑名单中,并将其与方法调用一起传递。

域名使用正则表达式语法表示,而 IP、协议和端口则是标准字符串(IP 可以使用 CIDR 表示法 指定)。

use fin1te\SafeCurl\SafeCurl;
use fin1te\SafeCurl\Options;

$options = new Options();
$options->addToList('blacklist', 'domain', '(.*)\.fin1te\.net');
$options->addToList('whitelist', 'scheme', 'ftp');

$curlHandle = curl_init();

//This will now throw an InvalidDomainException
$safeCurl = new SafeCurl($curlHandle, $options);
$response = $safeCurl->execute('http://safecurl.fin1te.net');

//Whilst this will be allowed, and return the response
$safeCurl = new SafeCurl($curlHandle, $options);
$response = $safeCurl->execute('ftp://fin1te.net');

由于我们无法获取任何已设置的 cURL 选项(请参阅注意事项部分),要启用 CURL_FOLLOWREDIRECTS,您必须调用 enableFollowRedirects() 方法。如果您希望指定重定向限制,您需要调用 setMaxRedirects()。传递 0 将允许无限重定向。

$options = new Options();
$options->enableFollowLocation();

//Abort after 10 redirects
$options->setFollowLocationLimit(10);

URL 检查

URL 检查方法也是公共的,这意味着您可以在应用程序的其他地方使用之前验证 URL,尽管您可能希望捕获任何重定向。

use fin1te\SafeCurl\Url;
use fin1te\SafeCurl\Exception;

try {
    $url = 'http://www.google.com';

    $validatedUrl = Url::validateUrl($url);
    $fullUrl = $validatedUrl['url'];
} catch (Exception $e) {
    // URL wasn't safe
}

可选保护措施

除了标准检查之外,还有两个可用的检查。

第一个是防止 DNS 重绑定 攻击。这可以通过在 Options 对象上调用 enablePinDns 方法来启用。这个问题的一个主要问题是 - SSL 证书 无法 验证。这是由于在 Host 标头中发送了真实的主机名,并且 URL 使用了 IP 地址。

$options = new Options();
$options->enablePinDns();

第二个是禁用 URL 中的凭据使用,因为 PHP 的 parse_url 返回的值与 cURL 使用的不相同。这是一个临时修复。

use fin1te\SafeCurl\SafeCurl;
use fin1te\SafeCurl\Exception;
use fin1te\SafeCurl\Options;

$options = new Options();
$options->disableSendCredentials();

$curlHandle = curl_init();

//This will throw an InvalidURLException
$safeCurl = new SafeCurl($curlHandle, $options);
$response = $safeCurl->execute('http://user:pass@google.com');

注意事项

由于 SafeCurl 使用 gethostbynamel 解析域名,这不是 IPv6 兼容的,因此该类目前只能与 IPv4 一起使用。请参阅 问题 #1

如上所述,我们无法获取提供的 cURL 处理器上设置的任何 cURL 选项的值。因为 SafeCurl 自行处理重定向,它将关闭 CURLOPT_FOLLOWLOCATION 并使用 Options 对象的值。这也适用于 CURLOPT_MAXREDIRECTS