j0k3r/httplug-ssrf-plugin
GitHub: j0k3r/httplug-ssrf-plugin
专为 PHP HTTPlug 库设计的 SSRF 防护插件,通过解析域名真实 IP 并结合黑白名单机制,有效阻断针对内网资源的非法请求。
Stars: 4 | Forks: 5
# HTTPlug 的服务端请求伪造 (SSRF) 防护插件

[](https://coveralls.io/github/j0k3r/httplug-ssrf-plugin?branch=master)
受 [SafeCurl](https://github.com/j0k3r/safecurl) 启发,旨在根据白名单或黑名单验证 URL 的每个部分,以帮助在使用 [HTTPlug](https://docs.php-http.org/en/latest/) 时防范_服务端请求伪造_攻击。
URL 的每个部分都会被拆解并根据白名单或黑名单进行验证。这包括将域名解析为其 IP 地址。
## 安装
可以使用 [Composer](https://getcomposer.org) 将其包含在任何 PHP 项目中。
```
composer require j0k3r/httplug-ssrf-plugin
```
## 使用
```
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\ServerSideRequestForgeryProtectionPlugin;
use Http\Client\Common\PluginClient;
use Http\Discovery\Psr18ClientDiscovery;
$ssrfPlugin = new ServerSideRequestForgeryProtectionPlugin();
$pluginClient = new PluginClient(
Psr18ClientDiscovery::find(),
[$ssrfPlugin]
);
```
如果 URL 无效,该插件会抛出 `Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Exception\InvalidURLException` 异常。
#### 选项
默认选项是禁止访问任何[私有 IP 地址](https://en.wikipedia.org/wiki/Private_network),并且仅允许 HTTP(S) 连接。
如果您希望添加自己的选项(例如将向您控制的域名发出的任何请求列入黑名单),只需获取一个新的 `Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Options` 对象,将其添加到白名单或黑名单中,并在方法调用时传递它。
域名使用正则表达式语法表示,而 IP、协议(scheme)和端口则是标准字符串(IP 可以使用 [CIDR 表示法](https://en.wikipedia.org/wiki/Cidr)指定)。
```
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Options;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\ServerSideRequestForgeryProtectionPlugin;
use Http\Discovery\Psr17FactoryDiscovery;
use Http\Discovery\Psr18ClientDiscovery;
use Http\Client\Common\PluginClient;
$options = new Options();
$options->addToList(Options::LIST_BLACKLIST, Options::TYPE_DOMAIN, '(.*)\.example\.com');
$pluginClient = new PluginClient(
Psr18ClientDiscovery::find(),
[new ServerSideRequestForgeryProtectionPlugin($options)]
);
// This will throw an Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Exception\InvalidURLException\InvalidDomainException
$request = Psr17FactoryDiscovery::findRequestFactory()->createRequest('GET', 'https://www.example.com');
$response = $pluginClient->sendRequest($request);
$options = new Options();
$options->setList(Options::LIST_WHITELIST, [Options::TYPE_SCHEME => ['https']]);
$pluginClient = new PluginClient(
Psr18ClientDiscovery::find(),
[new ServerSideRequestForgeryProtectionPlugin($options)]
);
// This will be allowed, and return the response
$request = Psr17FactoryDiscovery::findRequestFactory()->createRequest('GET', 'https://www.example.com');
$response = $pluginClient->sendRequest($request);
// This will throw an Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Exception\InvalidURLException\InvalidDomainException
$request = Psr17FactoryDiscovery::findRequestFactory()->createRequest('GET', 'https://www.example.com');
$response = $pluginClient->sendRequest($request);
```
#### 可选防护
除了标准检查外,还有两个可用的额外防护。
首先是防止 [DNS Rebinding](https://en.wikipedia.org/wiki/DNS_rebinding) 攻击。这可以通过在 `Options` 对象上调用 `enablePinDns` 方法来启用。但这有一个主要问题 —— SSL 证书**无法**被验证。这是因为真实的主机名是在 `Host` 头中发送的,而 URL 使用的是 IP 地址。
```
$options = new Options();
$options->enablePinDns();
```
其次是禁止在 URL 中使用凭证(credentials),因为 PHP 的 `parse_url` 返回的值与 cURL 使用的值不同。这是一个临时的修复方案。
```
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\Options;
use Graby\HttpClient\Plugin\ServerSideRequestForgeryProtection\ServerSideRequestForgeryProtectionPlugin;
use Http\Discovery\Psr17FactoryDiscovery;
use Http\Discovery\Psr18ClientDiscovery;
use Http\Client\Common\PluginClient;
$options = new Options();
$options->disableSendCredentials();
//This will throw an Http\Client\Exception\RequestException
$pluginClient = new PluginClient(
Psr18ClientDiscovery::find(),
[new ServerSideRequestForgeryProtectionPlugin($options)]
);
$request = Psr17FactoryDiscovery::findRequestFactory()->createRequest('GET', 'https://user:pass@google.com');
$response = $pluginClient->sendRequest($request);
```
#### 注意事项
由于该库使用 [`gethostbynamel`](https://php.net/manual/en/function.gethostbynamel.php) 来解析域名,而该函数不兼容 IPv6,因此该类目前仅适用于 IPv4。
标签:API密钥检测, Composer包, ffuf, HTTPlug, IP 地址批量处理, OpenVAS, PHP, SSRF防护, TypeScript, URL过滤, Web安全, 安全插件, 服务端请求伪造, 漏洞缓解, 白名单, 私有化部署, 私有网络保护, 网络安全, 蓝队分析, 输入验证, 防御规避, 隐私保护, 黑名单