通过 HttpClient 发送 Webhook 时防止 SSRF

问题描述 投票:0回答:1

我希望服务器应用程序将 webhook(即传出的 http-post 请求)发送到用户控制的 http(s) URL。该功能的简单实现很容易受到“服务器端请求伪造(SSRF)”的攻击,因为目标主机可能与服务器位于同一专用网络中。为了防止这种情况,我想将私有 IP 地址列入黑名单。 在经典 .NET 上,

HttpWebRequest

通过

ServicePoint.BindIPEndPointDelegate
 支持此功能,它接收客户端连接到的 IP 地址。然而在 .NET Core 中,
HttpWebRequest
被变成了
HttpClient
的包装器,并且这个回调被完全忽略。这将 SSRF 漏洞引入到以前安全的应用程序中。
但即使从已弃用的使用 

HttpWebRequest

迁移到直接使用

HttpClient
似乎也没有帮助。我在
HttpClientHandler
 中找不到任何在连接之前收到 IP 地址的回调。
在将原始 URL 传递到

HttpClient

之前将域解析为 IP 地址也无法可靠地工作。这很复杂,因为它需要处理多个返回的 IP 地址,并且容易受到

ToC/ToU
的影响,因为名称解析可能会为检查和请求执行返回不同的响应。这还需要手动处理 HTTP 重定向,因为还需要检查重定向目标的 IP 地址。 另一个想法是解析域,用 IP 填充要连接的主机,并在 http 主机标头中填充原始域(如果

HttpClient

甚至支持)。这还需要手动处理 HTTP 重定向,使其复杂且脆弱。

还可以选择在应用程序外部处理它(通过代理、防火墙等),但这也不是一个干净的解决方案,并且会增加基础设施成本和复杂性。

是否有一种合理的方法来支持使用

HttpClient

发送Webhooks而不会遭受SSRF?这感觉像是一个非常常见的用例,不需要复杂的解决方法。

    

c# .net-core ip-address dotnet-httpclient ssrf
1个回答
0
投票

我已经尝试过这种方式,并且能够在从中获取数据之前获取远程IP。

SocketsHttpHandler handler = new SocketsHttpHandler(); handler.ConnectCallback = async (context, cancellationToken) => { Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp); try { await socket.ConnectAsync(context.DnsEndPoint, cancellationToken).ConfigureAwait(false); var erp = socket.RemoteEndPoint; var remoteAddr = ((IPEndPoint)erp!).Address; var ipV4 = remoteAddr.MapToIPv4().ToString(); Console.WriteLine($"IP V4: {ipV4}"); var ipV6 = remoteAddr.MapToIPv6().ToString(); Console.WriteLine($"IP V6: {ipV6}"); //----> If the IPs is in black list, we can throw an exception here return new NetworkStream(socket, true); } catch { socket.Dispose(); throw; } }; var client = new HttpClient(handler); var response = await client.GetAsync("https://stackoverflow.com");

如果您执行 
ping stackoverflow.com

,则可以检查 IP。

    

© www.soinside.com 2019 - 2024. All rights reserved.