SSRF 攻击与防御:从原理到落地实践
1. 什么是 SSRF?
SSRF(Server-Side Request Forgery) 是一种常见的Web安全漏洞。当服务器提供了某种对外请求的功能,如“URL 参数直接转发请求”,攻击者就可以通过精心构造的URL,让服务器“自己”去访问特定的地址,从而达到以下目的:
- 扫描内网:探测企业内网中未暴露在公网的资产,如数据库、私有API等。
- 获取云元数据:例如访问
http://169.254.169.254/latest/meta-data
获得云服务器上敏感的配置信息或密钥。 - 侧向攻击:在更深层的漏洞场景下,如果服务器对内部网络拥有较高权限,攻击者还能利用 SSRF 辅助横向渗透其他机器。
1.1 典型利用场景
很多应用会提供一个“获取URL内容”的API,比如:
GET https://your-domain.com/fetch?url=http://example.com
如果没有对 url
参数做严格限制,攻击者就可以将请求指向内网:
GET https://your-domain.com/fetch?url=http://192.168.0.1:8080/admin
这时,后端服务器会向 192.168.0.1:8080
发起请求,“帮助”攻击者访问或扫描了内网地址。
2. 如何防御 SSRF?
2.1 核心原则
- 禁止直接传递用户输入的 URL
- 尽量使用后端白名单或 Token 验证,避免直接将用户提供的URL用来请求外部资源。
- 使用代理服务器
- 利用代理服务器(如 Squid)统一对外访问,并在代理层做访问控制(白名单、黑名单)。
- 网络隔离
- 服务端应与核心内网服务做分层隔离,避免一旦遭受 SSRF,能直接访问到更多敏感资源。
- 日志与监控
- 保持对外请求日志,监测异常请求行为。
下面重点介绍“使用代理服务器限制内部访问”的落地方案。
3. 使用本地代理限制内部访问
3.1 为什么要用本地代理?
当应用层可能需要访问外部API(例如调用第三方服务)时,我们可以将所有对外请求都“集中”通过一个本地代理服务器。
- 允许:访问特定安全域名(如
.openai.com
,.googleapis.com
); - 拒绝:访问局域网地址 (
127.0.0.1
,192.168.x.x
)、云元数据IP (169.254.169.254
) 等。
这样,当用户提交恶意参数(比如想扫描内网),请求会被代理服务器直接拦截。
3.2 代理部署示例
以 Squid 为例,假设我们有一个容器集群,只有 proxy_node
能够访问公网,其他服务都只能访问 proxy_node
。
拓扑思路:
[Web Service/LLM] --(internal network)--> [proxy_node(Squid)] --(internet)--> [外部API]
在 docker-compose.yml
中可能类似这样:
version: '3'
services:
web_app:
image: your-app:latest
networks:
- internal_network
# 假设web_app只与proxy_node通信
proxy_node:
image: ubuntu/squid:latest
networks:
- internal_network
# 监听某个端口,如 3128,对web_app提供服务
networks:
internal_network:
driver: bridge
3.2.1 配置 Squid
- Squid 配置文件
squid.conf
简化示例:# 允许 WebApp 网段访问 Squid acl localnet src 10.0.0.0/24 http_access allow localnet # 允许访问的域名(白名单方式) acl allowed_domains dstdomain .openai.com .exampleapi.com http_access allow allowed_domains # 拒绝其他域名 http_access deny all # 监听端口 http_port 3128
- 容器内执行:
这样就可以在容器内以前台模式运行 Squid,方便输出日志。squid -N -f /etc/squid/squid.conf
3.2.2 WebApp 访问外部 API
在应用配置中,将所有请求代理到 proxy_node
:
import requests
proxies = {
"http": "http://proxy_node:3128",
"https": "http://proxy_node:3128"
}
response = requests.get("http://api.exampleapi.com/data", proxies=proxies)
此时,如果有人试图向 http://192.168.0.1:8080
发起请求,Squid 配置会直接拒绝,避免了 SSRF 攻击导致的内网探测。
4. 其他 SSRF 防御手段
- 严格的输入校验与 Token 验证
如果必须提供某种“URL直通”功能,可以加上签名或专用令牌验证,并限制仅访问信任域名。 - 内网安全组
在云环境中,对服务器本身的安全组做最小权限配置,阻止其对内网段或特定端口的访问。 - WAF(Web Application Firewall)
部署专业的 WAF 规则(如针对内网地址的防护、云元数据地址限制等),进一步提升安全性。
5. 总结
- SSRF 是一种利用服务器端向外发送请求的漏洞手段,攻击者可以借此探测或攻击内网。
- 最佳防御策略:
- 禁止或严格限制用户可控的URL请求;
- 使用代理(如 Squid)集中管理、筛选允许访问的域名/IP;
- 保持网络隔离,记录访问日志,及时发现异常。
- 当下,越来越多的应用(尤其是 AI/LLM 平台)需要对外请求大量API,因此 “SSRF Proxy + 白名单” 这种组合方式在企业生产环境中非常常见,也相对高效可控。