同一个地址,四种写法
SSRF 攻击详解:DNS 如何被利用
服务端请求伪造(SSRF)指的是,攻击者让服务器代其发起一次 HTTP(或其他网络)请求,目的地由攻击者而非应用的开发者选定。一个典型的入口是:某个功能会抓取用户提供的 URL,比如图片导入、Webhook 目标、链接预览,而攻击者提供的 URL 指向的不是公开资源,而是内部基础设施。
DNS 在攻击中的位置
天真的防御做法,是检查所提供 URL 的主机名看起来是否像内部地址。这种做法很容易被绕过:攻击者注册一个公网域名,把它的 DNS 记录指向内部 IP,然后交给您的服务器一个看上去完全正常的主机名。您的校验看到的是域名而不是 IP,危险的部分要等 DNS 解析发生之后才会出现,而这一步往往深藏在实际发出请求的 HTTP 客户端库内部,远在任何前置校验步骤之后。
真正的防护是什么样的
- 在发出任何请求之前,自己显式地解析主机名,不要让 HTTP 客户端在您看不见的地方代为解析。
- 把每一个解析出的地址(是全部,一个域名可能返回多个)与私有/环回/链路本地/云元数据拦截名单逐一核对。
- 只要有任何一个解析出的地址不被允许,就拒绝该请求,而不是只检查返回的第一个。
- 在请求发出时再次校验,而不是只在输入时校验,以堵上另文所述的 DNS 重绑定漏洞,实践中 SSRF 与重绑定经常被组合使用。
云元数据端点在这里值得特别提一下:在大多数云服务商上,从虚拟机内部向某个特定的链路本地地址发起请求,可能返回凭据、实例元数据或配置信息,而这些内容本不应从机器之外访问到。SSRF 与元数据端点目标相结合,是现实中最常见、影响最大的攻击链之一,而它每一次都始于一个看起来平平无奇的域名。
只检查字符串、不检查地址的过滤器无效
一个 IP 地址的有效文本写法,比大多数校验代码考虑到的要多。如果过滤器只是对“127.0.0.1”或“localhost”做字符串匹配,下面这些替代写法就会原封不动地一路放行,因为它们看起来都不像被检查的那个字符串。
| 写法 | 示例 | 解析为 |
|---|---|---|
| 标准点分十进制 | 127.0.0.1 | 127.0.0.1 |
| 纯十进制整数 | 2130706433 | 127.0.0.1 |
| 八进制 | 0177.0.0.1 | 127.0.0.1 |
| 十六进制 | 0x7f.0.0.1 | 127.0.0.1 |
| 简写形式(少于 4 段) | 127.1 | 127.0.0.1 |
唯一可靠的防御,是先把地址解析成它真正的数值,再拿数值去对照拦截名单,本工具自带的解析器采用的正是这种方式,而不是对地址碰巧使用的写法做模式匹配。无论原始主机名的记录是以何种方式编码的,解析器返回的都是规范化之后的地址,这恰恰是先解析、再校验解析结果,比试图校验攻击者可能选用的各种原始字符串更稳健的原因。
重定向是另一种常见的绕过方式
即使系统能够正确解析并校验最初的 URL,仍然可能被 HTTP 重定向蒙混过关。对一个经过批准的公网 URL 发出的请求,可以用 302 响应指向某个内部地址,而自动跟随重定向的 HTTP 客户端(大多数库的默认行为)会毫不犹豫地发出第二次请求,完全不会重新执行第一次通过的那次校验。任何只在最前面校验一次、之后就让底层 HTTP 客户端自行处理重定向的 SSRF 防御,都存在一个与 DNS 解析所造成的漏洞形态完全相同的缺口,修复方法也同样:在跟随任何重定向之前,再次显式校验,而不要想当然地认为曾经通过一次的 URL 会一直指向安全的地方。
需要查看某个域名的公网 DNS 地址?使用 Domain IP Lookup 工具。
相关阅读
同一个域名,两个不同的答案
首次请求
解析为公网 IP
校验
通过,看起来安全
TTL 过期
数秒之后
第二次请求
解析为 127.0.0.1
什么是 DNS 重绑定?为什么值得关注
一个域名先解析到安全的公网地址,随后又解析到内部地址:DNS 重绑定让 DNS 本身成为攻击面。了解它的原理,以及唯一可靠的防御方法。
几乎每个 DNS 区域都会遇到的记录
什么是 CAA 记录?控制哪些 CA 可以签发证书
了解 DNS 证书颁发机构授权(CAA)记录如何指定被允许的证书签发机构,以及发布限制之前该如何规划,避免常见的 CAA 配置错误。
一次递归 DNS 查询,逐跳详解
浏览器
想访问 example.com
解析器
运营商 / 1.1.1.1
根 + TLD
谁负责 .com?
权威服务器
真正的答案
这条链路上的每一跳本身都是一次 DNS 查询,之后都会被缓存
DNSSEC 详解:DNS 应答如何被认证
了解 DNSSEC 签名、DS 与 DNSKEY 记录的作用,验证流程如何运作,以及配置失误为何会导致 SERVFAIL 响应。