fin1te / safecurl
用于替换 'curl_exec' 的直接替换方案,旨在防止 SSRF 攻击。
Requires
- php: >=5.3.0
Requires (Dev)
- phpunit/phpunit: 3.7.*
This package is not auto-updated.
Last update: 2024-09-24 06:27:41 UTC
README
SafeCurl旨在作为PHP中curl_exec函数的直接替换方案。SafeCurl会验证URL的每一部分与白名单或黑名单,以帮助防止服务器端请求伪造攻击。
有关项目的更多信息,请参阅博客文章'SafeCurl: SSRF Protection, and a "Capture the Bitcoins"'。
保护措施
将URL的每一部分拆分并进行白名单或黑名单验证。这包括将域名解析为其IP地址。
如果您选择启用"FOLLOWLOCATION",则任何重定向都将被捕获并重新验证。
安装
SafeCurl可以通过Composer包含在任何PHP项目中。在composer.json
文件下的require
中包含以下内容。
"require": {
"fin1te\safecurl": "~1"
}
然后更新Composer。
composer update
使用方法
只需将curl_exec
替换为SafeCurl::execute
,并用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($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (SafeCurl)'); //Execute using SafeCurl $response = SafeCurl::execute($url, $curlHandle); } catch (Exception $e) { //URL wasn't safe }
选项
默认选项是不允许访问任何私有IP地址,并且仅允许HTTP(S)连接。
如果您想添加自己的选项(例如,将任何请求到您控制的域名的请求列入黑名单),只需创建一个新的SimpleCurl\Options对象,将其添加到白名单或黑名单中,并将其与方法调用一起传递。
域名使用正则表达式语法表示,而IP、协议和端口使用标准字符串(IP可以使用CIDR表示法指定)。
use fin1te\SafeCurl\Options; $options = new Options(); $options->addToList('blacklist', 'domain', '(.*)\.fin1te\.net'); $options->addToList('whitelist', 'scheme', 'ftp'); //This will now throw an InvalidDomainException $response = SafeCurl::execute('http://safecurl.fin1te.net', $curlHandle, $options); //Whilst this will be allowed, and return the response $response = SafeCurl::execute('ftp://fin1te.net', $curlHandle, $options);
由于我们无法访问已设置的任何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; try { $url = 'http://www.google.com'; $validatedUrl = Url::validateUrl($url); $fullUrl = $validatedUrl['url']; } catch (Exception $e) { // URL wasn't safe }
可选保护措施
除了标准检查外,还有两个可供选择。
第一个是防止DNS Rebinding攻击。这可以通过在Options
对象上调用enablePinDns
方法来实现。这个问题的一个主要问题是——SSL证书无法被验证。这是由于在Host
头中发送了真实的主机名,并且URL使用了IP地址。
$options = new Options(); $options->enablePinDns();
第二个是禁用URL中的凭据使用,因为PHP的parse_url
返回的值与cURL使用的值不同。这是一个临时解决方案。
$options = new Options(); $options->disableSendCredentials(); //This will throw an InvalidURLException $response = SafeCurl::execute('http://user:pass@google.com', $curlHandle, $options);
注意事项
由于SafeCurl使用getaddrbyhostl
来解析域名,它不兼容IPv6,因此该类目前只能与IPv4一起工作。请参阅问题#1。
如上所述,我们无法获取对提供的cURL句柄设置的任何cURL选项的值。因为SafeCurl会自己处理重定向,它会关闭CURLOPT_FOLLOWLOCATION
并使用Options
对象中的值。这也适用于CURLOPT_MAXREDIRECTS
。
示例
您可以在http://safecurl.fin1te.net/#demo找到现场示例。如果您对站点源代码感兴趣,它托管在fin1te/safecurl.fin1te.net。
悬赏
为了帮助使SafeCurl安全并准备好投入生产使用,已经设置了一个比特币悬赏。
在文档根目录中有一个比特币钱包,它只能通过127.0.0.1访问。如果您能够绕过保护并获取文件,您可以自由地拿走比特币。