如何修复.NET Core中的Server-Side Request Forgery (SSRF)漏洞?
缓解.NET Core中SSRF漏洞的方案
你的代码存在SSRF漏洞的核心原因是:urlContent由外部输入控制,直接用于构造服务器侧的请求地址。攻击者可以通过构造恶意URL,让你的服务器访问内部私有服务(比如本地数据库、内网API)或第三方恶意资源,引发安全风险。
以下是具体的缓解措施:
1. 强制使用域名/IP白名单
维护一个预先批准的域名或IP范围列表,只允许请求这些地址,这是最有效的防护手段:
// 根据业务需求定义白名单 private readonly HashSet<string> AllowedDomains = new HashSet<string> { "trusted-domain.com", "api.allowed-service.net" }; private readonly List<IPAddressRange> AllowedIpRanges = new List<IPAddressRange> { IPAddressRange.Parse("203.0.113.0/24") // 仅允许业务需要的公网IP段 }; // 请求前验证逻辑 var targetUri = new Uri(TextHelper.RedirectUrlNull(urlContent)); // 验证域名 if (!AllowedDomains.Contains(targetUri.Host)) { throw new ArgumentException("请求域名未被授权"); } // 解析IP并验证范围 var ipAddresses = await Dns.GetHostAddressesAsync(targetUri.Host); foreach (var ip in ipAddresses) { if (!AllowedIpRanges.Any(range => range.Contains(ip))) { throw new ArgumentException("请求IP未在允许范围内"); } }
注意:如果业务不需要访问内网,务必禁止所有私有IP段(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、127.0.0.0/8等)。可以使用
IPAddressRangeNuGet包简化IP范围判断。
2. 过滤受限IP和协议
即使不使用白名单,也要至少禁止访问本地回环地址、私有IP段,以及危险协议:
// 检查是否为受限IP private bool IsRestrictedIp(IPAddress ip) { return ip.IsLoopback || IPAddressRange.Parse("10.0.0.0/8").Contains(ip) || IPAddressRange.Parse("172.16.0.0/12").Contains(ip) || IPAddressRange.Parse("192.168.0.0/16").Contains(ip) || IPAddressRange.Parse("169.254.0.0/16").Contains(ip); } // 验证URL协议和IP var targetUri = new Uri(TextHelper.RedirectUrlNull(urlContent)); if (targetUri.Scheme != Uri.UriSchemeHttp && targetUri.Scheme != Uri.UriSchemeHttps) { throw new ArgumentException("仅允许HTTP/HTTPS协议"); } var ipAddresses = await Dns.GetHostAddressesAsync(targetUri.Host); if (ipAddresses.Any(IsRestrictedIp)) { throw new ArgumentException("禁止访问受限地址"); }
3. 限制HttpClient的行为
禁用自动重定向(防止攻击者通过重定向绕过验证),并限制请求资源大小:
var handler = new HttpClientHandler { AllowAutoRedirect = false, MaxRequestContentBufferSize = 1024 * 1024 // 限制最大请求大小为1MB }; using var httpClient = new HttpClient(handler); // 后续请求逻辑...
额外建议:不要每次请求都创建新的HttpClient,通过DI注入单例实例,避免套接字耗尽问题。
4. 清理并验证输入URL
除了Uri.EscapeUriString,还要清理可能用于绕过验证的特殊字符,确保URL是合法绝对地址:
// 清理危险字符 urlContent = urlContent.Replace("@", "").Replace("%00", "").Trim(); var targetUri = new Uri(TextHelper.RedirectUrlNull(urlContent)); // 确保是绝对URI,防止相对路径被利用 if (!targetUri.IsAbsoluteUri) { throw new ArgumentException("必须提供绝对URL"); }
总结
优先采用白名单机制,结合IP过滤、协议限制和输入清理,能有效防范SSRF漏洞。所有验证逻辑必须在发送请求前执行,不要依赖客户端的输入验证。
内容的提问来源于stack exchange,提问作者Samuel
相关产品推荐
相关产品推荐

