SSRF 入门指南
● SSRF 入门指南
SSRF 全称 Server-Side Request Forgery,中文叫「服务端请求伪造」。这是 Web
安全里非常经典也非常高频的一类漏洞。
一、先用一个生活比喻理解它
想象你去一家餐厅点外卖代购服务:
- 你(攻击者)告诉服务员(服务器):“帮我去楼下便利店买瓶可乐。”
- 服务员是个"老实人",你说去哪他就去哪。
- 于是你改口说:“帮我去餐厅后厨的保险柜里拿点东西。”
- 服务员因为在餐厅内部,有权限进后厨,真的就去帮你拿了。
关键点在于:你自己进不去后厨(内网),但服务器能进。你就骗服务器替你去访问那些你本来碰不到的地方。
这就是 SSRF 的本质:利用服务器当"跳板/代理",去访问攻击者自己无法直接访问的资源。
二、为什么会产生 SSRF?
当一个 Web 应用提供了「让服务器主动去访问某个 URL」的功能时,就可能出问题。常见场景:
只要用户能控制服务器要访问的地址,而后端又没做好校验,SSRF 就来了。
三、一个最简单的漏洞代码
一个"图片代理"接口:传入 url,服务器去下载并返回内容
@app.route(‘/fetch’)
def fetch():
url = request.args.get(‘url’) # 用户完全可控
resp = requests.get(url) # 服务器直接去访问,没做任何检查
return resp.content
正常用法:
GET /fetch?url=https://example.com/cat.jpg
服务器去下载猫图,返回给你。没问题。
攻击用法:
GET /fetch?url=http://127.0.0.1:8080/admin
GET /fetch?url=http://192.168.1.1/
GET /fetch?url=http://169.254.169.254/latest/meta-data/
你把地址换成服务器内部才能访问的地址,服务器傻乎乎地帮你访问了,然后把结果返回给你。
四、攻击者能拿到什么?(危害)
1. 探测和访问内网
外网的你 ping 不到 192.168.x.x,但服务器在内网里。你可以让它逐个访问内网 IP
和端口,画出内网地图(哪些机器活着、开了哪些服务)。
2. 攻击内网服务
内网里的服务往往"不设防"(以为外面进不来)。比如未授权的 Redis、Elasticsearch、内部管理后台,通过 SSRF
就能直接打。
3. 读取云服务器的敏感元数据 ⭐(最经典、危害最大)
云主机(AWS、阿里云等)有一个特殊地址 169.254.169.254,叫元数据服务(Metadata Service)。访问它能拿到:
http://169.254.169.254/latest/meta-data/iam/security-credentials/
→ 返回临时访问密钥(AccessKey)!拿到后攻击者就能以这台服务器的身份操作整个云账号,危害极大。很多重大安全事故都源
于此。
4. 读取本地文件
如果代码用的库支持 file:// 协议:
file:///etc/passwd
直接读服务器本地文件。
5. 绕过防火墙、发起进一步攻击
借助服务器身份做端口扫描、攻击第三方等。
五、常被利用的"协议"和"地址"
SSRF 不只是 http://,危险的协议还有很多(取决于后端用什么库):
file:// 读本地文件 file:///etc/passwd
http/https 常规请求
gopher:// 超强!可构造任意TCP数据,能打Redis/MySQL等
dict:// 探测端口、打Redis
ftp:// …
其中 gopher:// 是攻击者最爱,因为它能让服务器发送任意字节流,相当于可以伪造出完整的 Redis 命令、HTTP POST
请求等,把"只能 GET 访问"升级成"能执行任意操作"。
六、绕过防御的常见花招(重点!)
很多开发者会想:“我把 127.0.0.1 和内网 IP 拉黑不就行了?” 但绕过方法非常多:
1. 换 IP 的写法(都指向 127.0.0.1):
http://127.0.0.1
http://0.0.0.0
http://localhost
http://0177.0.0.1 # 八进制
http://2130706433 # 十进制(把IP当整数)
http://0x7f.0.0.1 # 十六进制
http://[::1] # IPv6
2. 利用域名解析:
- 注册一个域名,把它的 DNS 解析记录指向 127.0.0.1 或内网 IP。校验时看着是正常域名,实际访问的是内网。
3. 302 跳转绕过:
- 让服务器访问 http://evil.com(校验通过),但这个地址返回一个 302 跳转 到
http://127.0.0.1/admin。服务器跟着跳转就中招了。
4. DNS Rebinding(DNS重绑定) ⭐ 高级:
- 校验时域名解析成一个正常外网 IP(通过检查),但等服务器真正发起请求那一刻,DNS 又解析成了内网
IP。利用"检查"和"使用"之间的时间差绕过。
5. 短网址、URL 特殊字符:
http://expected.com@127.0.0.1/ # @前面是"用户名",实际访问@后面的
http://127.0.0.1#expected.com
七、如何防御(开发者视角)
防御 SSRF 的核心思路是 “默认拒绝,只允许白名单”:
1. 白名单优先(最有效)
- 不要用黑名单(总有绕过)。只允许访问明确列出的域名/IP。
2. 校验要在解析后、请求时进行
- 先把域名解析成 IP,检查这个 IP 是不是内网地址,再用这个 IP 去请求(防 DNS Rebinding)。
- 屏蔽的 IP 段:
127.0.0.0/8 本地回环
10.0.0.0/8 内网
172.16.0.0/12 内网
192.168.0.0/16 内网
169.254.0.0/16 链路本地(含云元数据 169.254.169.254)
::1 / fc00::/7 IPv6 对应段
3. 禁用危险协议
- 只允许 http 和 https,禁掉 file://、gopher://、dict:// 等。
4. 禁止跟随重定向(或跟随后重新校验目标 IP)。
5. 网络层隔离
- 给这类"外联"服务单独部署,限制它的出网权限,连不到内网和元数据服务。
- 云上启用 IMDSv2(需要令牌才能访问元数据,能大幅缓解)。
6. 不要把响应原样返回给用户
- 减少信息泄露(比如报错信息、响应内容)。
八、一句话总结
▎ SSRF = 骗服务器替你去访问你本来够不着的地方(尤其是内网和云元数据)。
▎ 只要有"用户控制 URL、服务器去访问"的功能,就要警惕。防御的关键是 白名单 + 解析后校验 IP + 禁危险协议 + 网络隔离。