目录
[2、DNS 重绑定](#2、DNS 重绑定)
[① 查看源码](#① 查看源码)
[② 源码对比分析](#② 源码对比分析)
[6、域名解析绕过法(失败)](#6、域名解析绕过法(失败))
本文通过CTFHub的SSRF DNS重定向 bypass关卡的渗透实战,探讨了SSRF与DNS重绑定技术的结合应用。SSRF通过伪造服务器请求访问敏感资源,DNS重绑定则利用DNS解析缺陷绕过IP过滤。文章详细分析了DNS重绑定工作原理,包括配置短TTL和双A记录实现IP切换。在实战环节,作者尝试了八进制、十进制、十六进制IP绕过及DNS重绑定方法,最终成功通过十六进制IP(0x7F000001)和DNS重绑定域名(7f000001.c0a80001.rbndr.us)获取flag。实验证明,DNS重绑定能有效突破常规IP过滤机制,是SSRF攻击的有力绕过手段。
一、SSRF与DNS重绑定
SSRF 和 DNS 重绑定是 Web 安全中两类密切相关的攻击技术:
- SSRF是 "服务器端的请求伪造",核心风险是服务器被利用访问敏感资源;
- DNS 重绑定是 "利用 DNS 解析缺陷的绕过技术",核心价值是突破 IP 过滤、同源策略等防御;
- 二者结合时,DNS 重绑定可成为 SSRF 的 "破防利器",绕过常规 IP 过滤,实现对服务器内网的深度攻击。
1、SSRF原理
SSRF(Server-Side Request Forgery,服务器端请求伪造)核心原理是攻击者利用服务器端程序的请求能力,伪造服务器发起的请求,访问服务器自身或内网中本不应被外部访问的资源,进而实现信息窃取、内网探测、远程代码执行等攻击目的。
简单来说:**正常用户让网站去访问另一个网站,但攻击者通过构造恶意参数,让网站(服务器)去访问它本不应该访问的内部系统或其他敏感资源。**若程序未对用户输入的 URL 进行严格校验,攻击者可构造恶意 URL,让服务器 "代劳" 发起请求,发起类似如下常见的攻击请求。
- 访问服务器本地的敏感端口(如
127.0.0.1:22
(SSH)、127.0.0.1:3306
(MySQL)); - 访问内网其他主机的资源(如
192.168.1.100/admin
(内网管理后台)); - 访问云服务的元数据接口(如 AWS 的
http://169.254.169.254/latest/meta-data/
,可获取 Access Key 等敏感信息)。
2、DNS 重绑定
(1)基本概念
DNS 重绑定(DNS Rebinding)是一种利用 DNS 解析机制的缺陷,绕过浏览器 "同源策略" 或服务器 "IP 过滤",实现对目标主机(如客户端本地、服务器内网)访问的攻击技术。其核心是通过控制 DNS 服务器,让同一域名在短时间内解析到不同的 IP 地址。
(2)DNS重绑定绕过
常规 SSRF 防御中,服务器会过滤127.0.0.1
、内网 IP 等敏感地址,但攻击者可通过 DNS 重绑定绕过该限制:
- 攻击者构造恶意域名(如
rebind.example.com
),让其先解析为 "允许访问的公网 IP"(通过服务器的 IP 过滤); - 服务器发起请求时,DNS 将该域名重新解析为 "敏感 IP"(如
127.0.0.1
或192.168.1.100
); - 服务器最终访问敏感 IP,实现 SSRF 攻击,此时常规的 "IP 过滤" 防御失效(因服务器校验的是第一次解析的 IP)
(3)工作原理
攻击者完全控制一个域名(例如 evil.com
)的 DNS 服务器。他可以进行如下配置:
-
设置极短的 TTL (Time-To-Live):例如 0 秒或几秒,告诉解析器不要缓存记录,每次都重新查询。
-
配置两条 A 记录:
-
第一次查询 :返回一个合法的、受攻击者控制的公网 IP (例如
1.2.3.4
)。这一步是为了通过应用程序的"白名单/黑名单"校验。 -
第二次查询 :返回一个目标内网 IP (例如
192.168.1.1
)。这一步是真正的攻击
-
-
绕过安全限制 :
- 对浏览器:利用 "同源策略" 仅校验域名不校验 IP 的特性,让脚本先通过公网 IP 加载,再通过 DNS 切换解析到目标 IP,实现对本地 / 内网服务的访问;
- 对服务器:若服务器仅校验 "域名是否合法" 或 "首次解析的 IP",则切换后的目标 IP 会被服务器默认访问,绕过 IP 过滤。
二、渗透实战
1、打开靶场
打开关卡如下所示,提示信息为"关键词:DNS重绑定。剩下的自己来吧,也许附件中的链接能有些帮助",提示本关卡可以利用DNS重绑定来绕过SSRF过滤检测。点击打开题目,此时系统自动创建Docker环境,下图蓝色部分的URL地址就是靶场环境。

复制靶场链接(challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800)并访问,如下所示被重定向到了?url=_中,完整的URL链接如下所示。
http://challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=_

2、尝试127.0.0.1访问
构造Payload为?url=http://127.0.0.1/flag.php,尝试通关127.0.0.1访问页面,完整URL如下所示。
http://challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=http://127.0.0.1/flag.php
通过浏览器访问如上链接后,页面提示"**"Hack ban Intranet IP"**",说明该Payload触发了过滤机制,提示ip地址127.0.0.1是被禁止的ip地址,具体如下所示。

3、file协议分析源码
(1)flag.php
使用file协议获取flag其源码,构造payload为?url=file:///var/www/html/flag.php,完整URL地址如下所示。
http://challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=file:///var/www/html/flag.php
访问URL地址后,使用右键查看源代码,具体内容如下所示。

这段代码的核心逻辑是通过验证请求的客户端 IP 地址,只允许本地(127.0.0.1
)发起的请求获取 Flag,其他来源的请求会被拦截并提示,详细注释后的代码如下所示。
<?php
error_reporting(0); // 关闭所有错误报告,防止信息泄露
if ($_SERVER["REMOTE_ADDR"] != "127.0.0.1") { // 检查客户端的IP地址
echo "Just View From 127.0.0.1"; // 如果不是本地回环地址,则拒绝访问
exit;
}
echo getenv("CTFHUB"); // 如果IP是127.0.0.1,则输出环境变量CTFHUB的值(这就是Flag)
?>
这段代码部署在服务器上(路径为 /var/www/html/flag.php
),实现强制的访问控制策略:
-
访问条件 : 只允许源IP地址为
127.0.0.1
(即服务器本机)的请求。 -
拒绝动作 : 如果客户端IP不是 1
27.0.0.1
,则输出Just View From 127.0.0.1
并终止脚本。 -
允许动作 : 如果客户端IP是
127.0.0.1
,则读取并输出系统环境变量CTFHUB
的值,这通常就是我们要寻找的Flag。
(2)index.php
① 查看源码
使用file协议获取flag其源码,构造payload为?url=file:///var/www/html/index.php,完整URL地址如下所示。
http://challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=file:///var/www/html/index.php
通过file协议访问URL地址后,使用右键查看源代码,具体内容如下所示。

这段代码的主要功能是:接收一个 url
参数,首先检查该参数是否存在,若存在则重定向;然后通过检查请求参数 url
中是否包含 127
、172
、10
、192
等内网 IP 相关字符来禁止访问内网,若未包含则使用 cURL 库向该 url
发起请求并获取响应。整体是为了限制对特定内网地址的访问,同时实现对合法外部 URL 的请求转发。详细注释后的代码如下所示。
<?php
// 关闭所有错误报告,防止敏感信息(如路径、数据库错误)通过错误信息泄露给攻击者。
error_reporting(0);
// 检查用户请求中是否设置了 'url' 参数
if (!isset($_REQUEST['url'])) {
// 如果没有提供 'url' 参数,则使用 HTTP 302 重定向到首页,并自动加上 `?url=_`
// 这里的 '_' 可能是一个默认值或占位符,但更可能是为了保持URL格式统一,提示用户需要输入参数。
header("Location: /?url=_");
exit; // 重定向后立即终止脚本执行
}
// 从用户请求(GET或POST)中获取 'url' 参数的值。用户完全控制这个输入。
$url = $_REQUEST['url'];
// 使用正则表达式对用户输入的 URL 进行黑名单过滤
// 匹配任何包含 "127", "172", "10", "192" 的字符串
// 目的:阻止攻击者直接使用内网IP地址(如 127.0.0.1, 172.16.0.1, 10.0.0.1, 192.168.0.1)进行SSRF攻击,访问内网服务。
if (preg_match("/127|172|10|192/", $url)) {
// 如果匹配到黑名单中的字符,输出 "hacker! Ban Intranet IP" 并立即退出,阻止后续操作。
exit("hacker! Ban Intranet IP");
}
// ------------------------------ 以下是危险的代码段 ------------------------------
// 初始化一个新的 cURL 会话
$ch = curl_init();
// 设置 cURL 会话的选项
// CURLOPT_URL: 设置要抓取的 URL。这里直接使用了用户控制的、经过黑名单过滤的 `$url`。
curl_setopt($ch, CURLOPT_URL, $url);
// CURLOPT_HEADER: 设置是否在输出中包含 HTTP 头。0 表示不包含,只返回响应体。
curl_setopt($ch, CURLOPT_HEADER, 0);
// 执行 cURL 会话。
// 这个函数会去请求 `$url` 指定的资源,并将获取到的响应体(Response Body)直接输出(echo)到用户的浏览器。
curl_exec($ch);
// 关闭 cURL 会话资源,释放内存。
curl_close($ch);
// 脚本结束
?>
② 源码对比分析
对比上一个关卡(302跳转bypass),少了自动跟随重定向的语句,即缺少如下语句,其余代码基本上都一样。不过少了这行代码,意味着本关卡不能使用302跳转方法进行绕过。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); // 关键危险配置!自动跟随重定向
4、分析绕过方法
- 八进制表示 :将 IP 地址转换为八进制,例如
127.0.0.1
可以表示为0177.0000.0000.0001
,因为正则表达式只匹配十进制数字字符串,这样可以绕过检测。 - 十六进制表示 :把 IP 地址转换为十六进制,
127.0.0.1
转换后为0x7F000001
,利用这种表示方式,服务器在解析时能识别为127.0.0.1
,但可以绕过正则检测。 - 十进制整数表示 :
127.0.0.1
对应的十进制整数是2130706433
,使用http://2130706433/
作为 URL 部分,能绕过对特定数字字符串的匹配。 - 特殊域名解析 :利用一些会解析到本地回环地址的域名,如
localhost
、127.0.0.1.xip.io
,localhost
默认解析到127.0.0.1
,而127.0.0.1.xip.io
无论子域名如何,都会解析到127.0.0.1
。 - DNS 重绑定:通过控制 DNS 服务器,将一个合法的域名解析到内网 IP 地址,然后在 URL 中使用这个域名,绕过对内网 IP 的直接限制。
5、数字IP绕过
(1)八进制绕过法(失败)
我们可以把127.0.0.1转化为八进制形式进行绕过,使用在线进制转换工具对127.0.0.1进行进制转换,运行结果如下所示,127.0.0.1转换为八进制值为0177.0000.0000.0001。

使用?url=http://0177.0000.0000.0001/flag.php来替换?url=http://127.0.0.1/flag.php,完整URL地址如下所示。
challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=http://0177.0000.0000.0001/flag.php
将构造好的 URL 复制到浏览器地址栏,按下回车发送请求,按理服务器会自动将 "2130706433" 解析为 127.0.0.1,绕过黑名单拦截(检查url
参数中是否包含 127
、172
、10
、192
这些常见的内网 IP 段特征字符串),不过从服务器的响应结果来看,其并识别八进制的127.0.0.1(0177.0000.0000.0001),故而响应提示Bad request,渗透失败。

(2)十进制绕过法(失败)
我们可以把127.0.0.1转化为十进制形式进行绕过,使用在线进制转换工具对127.0.0.1进行进制转换,运行结果如下所示,127.0.0.1转换为十进制值为2130706433。

若需手动验证,按以下步骤计算127.0.0.1对应的十进制值。
- 将 IP 的 4 个段(127、0、0、1)分别转为 8 位二进制:
127 → 01111111,0→00000000,0→00000000,1→00000001; - 拼接为 32 位二进制数:
01111111000000000000000000000001
; - 将 32 位二进制转为十进制:
01111111000000000000000000000001
= 2130706433。
使用?url=http://2130706433:80/flag.php来替换?url=http://127.0.0.1/flag.php,完整URL地址如下所示。
challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=http://2130706433:80/flag.php
将构造好的 URL 复制到浏览器地址栏,按下回车发送请求,按理服务器会自动将 "2130706433" 解析为 127.0.0.1,绕过黑名单拦截(检查url
参数中是否包含 127
、172
、10
、192
这些常见的内网 IP 段特征字符串),不过从服务器的响应结果来看,其并识别十进制的127.0.0.1(2130706433),故而响应提示Bad request,渗透失败。

(3)十六进制绕过法(成功)
我们可以把127.0.0.1转化为十六进制形式进行绕过,使用在线进制转换工具对127.0.0.1进行进制转换,运行结果如下所示,127.0.0.1转换为十六进制值为0x7F000001。

使用?url=http://0x7F000001/flag.php来替换?url=http://127.0.0.1/flag.php,完整URL地址如下所示。
http://challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=http://0x7F000001/flag.php
将构造好的 URL 复制到浏览器地址栏,按下回车发送请求,此时服务器会自动将 "0x7F000001" 解析为 127.0.0.1,绕过黑名单拦截(检查url
参数中是否包含 127
、172
、10
、192
这些常见的内网 IP 段特征字符串),如下所示已经成功获取flag,渗透成功。

6、域名解析绕过法(失败)
将?url=http://127.0.0.1/flag.php替换为?url=http://localhost/flag.php,用localhost代替127.0.0.1,完整的URL地址如下所示。
http://challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=http://localhost:80/flag.php
或
http://challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=http://localhost/flag.php
如下所示,成功获取到flag值。因为源码分析中正则仅检测url
中是否包含127
、172
、10
、192
这些字符串(均为内网 IP 段特征),但没有限制localhost
这个关键词 。而localhost
是域名系统中指向本地回环地址(127.0.0.1
)的特殊域名,其字符串中不包含上述被拦截的数字,因此能直接通过正则检测。

7、DNS重绑定绕过法(成功)
(1)配置DNS重绑定
打开 rebinder.html 页面,访问如下网址,配置DNS重绑定。
https://lock.cmpxchg8b.com/rebinder.html
如下所示A对应的IP地址就是要绕过的IP地址,本关卡需要写为127.0.0.1,对于B的ip地址,随即填一个的IP地址即可,这里使用默认的192.168.0.1。通过修该域名对应的IP,使一个域名对应两个IP,那么在多次的访问之下产生的访问效果是一样的实现IP绕过。

如上所示配置完A和B两个ip地址后,工具会生成唯一的子域域名7f000001.c0a80001.rbndr.us。
(2)ping域名
尝试命令行ping这个域名7f000001.c0a80001.rbndr.us,如下所示,符合DNS重绑定的需求,在两个ip地址192.168.0.1和127.0.0.1之间切换。

(3)利用DNS重绑定获取flag
使用生成的域名构造Payload:/?url=7f000001.c0a80001.rbndr.us/flag.php ,完整URL地址如下所示。
challenge-74fddaf2d4c00bb9.sandbox.ctfhub.com:10800/?url=7f000001.c0a80001.rbndr.us/flag.php
将构造好的 URL 复制到浏览器地址栏,按下回车发送请求,如下所示已经成功获取flag。

通过控制 DNS 解析,在校验时 返回一个合法 IP (192.168.0.1
) 以通过防护规则,而在实际请求时 则返回真正的内网目标 IP (127.0.0.1
),从而绕过基于 IP 黑名单/白名单的防御措施