Bypassing Web Filters Part 3 Domain Fronting
在本系列的前两篇博文中,我们讨论了 SNI 欺骗和 Host
头欺骗。我们还了解到,一些供应商使用一种称为"域名前置检测"的技术来应对后者。但究竟什么是域名前置?这将在本篇博文中进行解释。
绕过网络过滤器博文系列:
-
绕过网络过滤器第一部分:SNI 欺骗 -
绕过网络过滤器第二部分:Host 头欺骗 -
绕过网络过滤器第三部分:域名前置 -
绕过网络过滤器第四部分:Host 头欺骗和域名前置检测绕过
内容分发网络 / 缓存服务器
让我们首先讨论 CDN 的用途。一个简单的 CDN 可能如下所示:
有 3 个内容服务器。这些服务器用于向用户提供内容。由于这些服务器性能不是很强,上行链路速度也很慢,它们无法为数百万用户提供文件服务。与其在内容服务器上增加更多服务器和带宽,不如在它们前面放置一个 CDN 服务器来分担工作。
内容服务器的 DNS 记录(例如 b.example.net
)指向 CDN 服务器(203.0.113.5
)。现在,当 Alice 想要访问 b.example.net
的文件时,请求会发送到 CDN 服务器的 IP 地址,SNI 和 Host
头都设置为 b.example.net
。只要这个域名在 CDN 上注册,服务器就会检查文件是否已经在其缓存中,如果没有,就从相应的内容服务器获取。
如果再次从 CDN 服务器请求相同的资源,资源将直接从缓存加载:
这节省了内容服务器的计算能力和带宽。CDN 服务器还可以同时存在于世界各地的多个位置,以获得更好的内容传递速度。
使用域名前置绕过简单的网络过滤器
域名前置是一种用于绕过审查和网络过滤器的技术 1。这种技术不仅可以用来绕过网络过滤器,还可以增强流量的合法性,使其能够无缝融入常规网络活动。
它利用了在 HTTPS 请求中可以在两个地方指定主机名的事实。一个是在 TLS 握手期间的 SNI,另一个是 HTTP 请求的 Host
头,正如我们在前两篇博文中已经看到的。
简单回顾一下,在合法的 CDN 场景中,用户的请求在 SNI 和 Host
头中都包含目标主机名(CDN 背后的服务器)。使用域名前置时,SNI 设置为一个合法的主机名(例如,允许访问的主机名),但 Host
头设置为不应直接访问的服务器。
为了使这种方法有效,处理此连接的服务器必须配置为正确评估 Host
头中的主机名并做出响应。这就是 CDN 发挥作用的地方,因为这本质上就是它们的工作。
想象你有以下情况,Alice 能够访问 CDN cdn.example.net
,而这个 CDN 又用于访问 legit.example.net
。然而,防火墙基于 SNI evil.example.com
阻止了对 evil.example.com
的访问:
攻击者现在可以使用 CDN 网络来"隐藏"他们的服务器。现在,Alice(或她电脑上的恶意软件)可以向允许的 CDN 服务器 203.0.113.5
发送请求,使用合法的 SNI legit.example.net
,但 Host
头设置为被阻止的服务器 evil.example.com
。由于 CDN 已相应配置,请求被转发到 evil.example.com
服务器,这使 Alice 能够访问这个原本被阻止的资源。
Host
头中使用恶意主机名最终的 IP、TLS 和 HTTP 数据包结构如下所示:
这看起来类似于 SNI 欺骗(参见本博文系列的第一部分),但连接是建立到合法的 CDN 系统,而不是直接连接到被阻止的主机。
使用 Fastly CDN 和 curl
的示例
选择你的 CDN
由于域名前置是一种众所周知的技术,它并不适用于所有 CDN。有几个 CDN 会检查 SNI 和 Host
头中的主机名是否不同,然后阻止这样的请求。例如,Azure2、Google3 或 AWS4 就是这种情况。相比之下,Fastly5(在撰写本博文时)不阻止域名前置。
恶意服务器配置
这是最简单的部分。在 evil.meta.securelogon.ch
上配置了一个提供一些内容的 Web 服务器:
$ curl https://evil.meta.securelogon.ch
<h1>Hello from Compass</h1>
在本示例中,假设对该服务器的访问被阻止。
Fastly 配置
让我们在 Fastly 上创建一个新的 CDN 服务。域名可以随意选择,例如 compass-test.global.ssl.fastly.net
①。这个域名稍后将用在 Host
头中。对于源站(origin),配置了我们控制的系统 evil.meta.securelogon.ch
②:
完成后,你将获得一个具有以下 DNS 记录的新域名:
$ dig compass-test.global.ssl.fastly.net +noall +short
199.232.17.194
现在可以使用这个域名来访问你的系统:
$ curl https://compass-test.global.ssl.fastly.net/
<h1>Hello from Compass</h1>
附注:在这一点上,我们已经实现了一个简单的绕过,因为我们新注册的域名可能没有被我们试图绕过的网络过滤器所阻止。然而,过滤器的操作者可以轻易地通过简单地阻止这个新域名来纠正这一问题(例如,因为它是新观察到的,或者只是很少被访问)。
让我们回到我们的设置。如果我们详细查看上面 curl
命令的请求,你可以看到 TLS 握手中的 SNI ① 和 HTTP 请求 ② 中的 Host
头 ③ 都包含 Fastly 主机名 compass-test.global.ssl.fastly.net
:
这是通过 CDN 访问资源的典型方式,还不能说明 Fastly 是否可以用于域名前置。为此,我们必须弄清楚 Fastly 是否也接受 SNI 和 Host
头不同的请求,以及是否提供正确的内容。
让我们使用我们之前配置的主机名作为 Host
头,并设置一个任意的 SNI(在这种情况下,甚至是一个非有效域名用于测试目的)。从下面的响应中可以看出,服务器确实是可访问的:
$ curl -k -H "Host: compass-test.global.ssl.fastly.net" --connect-to invalid::199.232.17.194: https://invalid/
<h1>Hello from Compass</h1>
请注意,在这个 curl
请求中,证书验证被显式禁用(-k
)。由于 Fastly 无法为 https://invalid
提供有效证书,否则我们的请求将会失败。
在 Wireshark 中,上述请求如下所示。TLS 握手中的 SNI ① 设置为 invalid
,但 HTTP 请求 ② 中的 Host
头 ③ 包含 Fastly 主机名 compass-test.global.ssl.fastly.net
:
这种行为告诉我们,Fastly CDN 服务:
-
不检查 SNI 和 Host
头中的主机名是否匹配 -
仅基于 Host
头提供内容
因此,Fastly CDN 满足域名前置的基本要求。
寻找可前置的域名
如前所述,域名前置旨在绕过网络过滤器,同时保持隐蔽性。隐蔽性主要与用作 SNI 的主机名有关。因此,我们现在必须寻找合适的域名。
让我们定义这些域名的要求:
-
主机名必须在目标 CDN(在我们的案例中是 Fastly)注册 -
主机名不能被相关的网络过滤器阻止 -
(额外加分)主机名在目标环境的上下文中不应引起怀疑
如果一个域名使用 CDN 来传递其内容,该域名的 DNS 记录会指向属于 CDN 的一个或多个服务器。有几个工具如 FindFrontableDomain6 可以帮助你检查一个域名是否在已知的 CDN 后面,还有包含众所周知的可前置域名的列表 7。但让我们手动操作,这样你就能看到背后的过程。
首先,你必须想出适合你正在测试的目标基础设施的现有主机名(记住,该域名应该被目标网络过滤器允许,理想情况下不应引起怀疑)。对于一家银行,你可以枚举一些金融网站的子域名。作为起点,你可以使用广泛使用的域名的公共列表,例如来自 GitHub 仓库之一 8 的列表,或者来自 DomCop9 的列表。为了与你的目标基础设施融合,你还可以枚举目标本身的主机名。
接下来,我们对这些主机名执行 DNS 查询,并检查 DNS 记录是否指向 Fastly CDN。以下命令使用 dnsx
10 来解析 DNS 条目。这很有用,因为 dnsx
还能显示使用的是哪个 CDN:
dnsx -silent -resp -cname -a -cdn < possible-hostnames.txt
[...]
amazon.com [A] [205.251.242.103]
amazon.com [A] [54.239.28.85]
creators.spotify.com [A] [151.101.194.133] [fastly]
creators.spotify.com [A] [151.101.66.133] [fastly]
creators.spotify.com [A] [151.101.2.133] [fastly]
creators.spotify.com [A] [151.101.130.133] [fastly]
dailymotion.com [A] [195.8.215.136]
deezer.com [A] [13.224.103.100] [cloudfront]
deezer.com [A] [13.224.103.83] [cloudfront]
de.wikipedia.org [A] [185.15.58.224]
[...]
paypal.com [A] [151.101.195.1] [fastly]
paypal.com [A] [151.101.3.1] [fastly]
paypal.com [A] [162.159.141.96] [fastly]
paypal.me [A] [151.101.65.21] [fastly]
paypal.me [A] [162.159.141.96] [fastly]
pbs.twimg.com [A] [104.18.37.127] [fastly]
pbs.twimg.com [A] [172.64.150.129] [fastly]
trello.com [A] [3.165.190.47]
[...]
很好,我们发现了几个解析到 Fastly CDN 的主机名。有时,CDN 会有多个暴露的系统,并非所有系统都可以用来访问相同的目标。为了检查我们的服务器域名 compass-test.global.ssl.fastly.net
是否可达,我们可以向所有发现的主机名发送 HTTP 请求,并验证是否能访问我们的自托管网站(内容为"Hello"):
$ grep fastly dnsx_top10m_all.txt | cut -d ' ' -f 1 | sort -u | while read host
do
curl -s -H "Host: compass-test.global.ssl.fastly.net" https://$host/ | grep -q "Hello" && echo $host
done
ameblo.jp
anchor.fm
creators.spotify.com
dictionary.com
linktr.ee
slate.com
smh.com.au
theatlantic.com
注意:这些主机名不需要解析到与我们的 Fastly 域名完全相同的 IP 地址,它们只需要是 CDN (Content Delivery Network) 的一部分即可:
dig creators.spotify.com +noall +answer
creators.spotify.com. 204 IN A 151.101.130.133
creators.spotify.com. 204 IN A 151.101.194.133
creators.spotify.com. 204 IN A 151.101.66.133
creators.spotify.com. 204 IN A 151.101.2.133
$ dig compass-test.global.ssl.fastly.net +noall +answer
compass-test.global.ssl.fastly.net. 36 IN A 199.232.17.194
使用 curl
进行域名前置
现在,我们可以将这些元素组合起来,构造一个请求,该请求在 SNI 中包含之前发现的主机名,同时在 Host
头中使用我们自己的 Fastly 域名。Curl 将 creators.spotify.com
解析为 IP 地址 151.101.2.133
并在 SNI 中包含此主机名。由于 CDN 服务器管理此主机名,它为 TLS 连接提供了有效证书。然而,我们获得的响应是由 Host 头中的恶意主机名决定的。
$ curl -v -H "Host: compass-test.global.ssl.fastly.net" https://creators.spotify.com/index.html
[...]
* SSL connection using TLS1.2 / ECDHE_RSA_CHACHA20_POLY1305
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: creators.spotify.com (matched)
[...]
* subject: CN=creators.spotify.com
[...]
* issuer: C=US,O=Certainly,CN=Certainly Intermediate R1
[...]
* Connected to creators.spotify.com (151.101.2.133) port 443
* using HTTP/1.x
> GET / HTTP/1.1
> Host: compass-test.global.ssl.fastly.net
[...]
< HTTP/1.1 200 OK
[...]
<h1>Hello from Compass</h1>
在 Wireshark 中,我们可以重现此连接的所有步骤。首先,对合法主机名 creators.spotify.com
执行 DNS 查询 ①。然后,使用 SNI 中的合法主机名建立 TLS 连接 ②。在封装的 HTTP 请求 ③ 中,Host
头 ④ 的值为 compass-test.global.ssl.fastly.net
:
Host
头中使用恶意主机名向 CDN 发送请求从网络角度来看,对目标主机 creator.spotify.com
的流量看起来是合法的。然而,实际上可以从另一个原本会被阻止的系统获取资源。
使用 AWS CloudFront 的非工作示例
如前所述,一些 CDN 会阻止域名前置。AWS CloudFront 就是一个例子。
为了演示这种行为,我们使用两个解析到相同 AWS CloudFront CDN IP 地址的主机名:
sort -k3 dnsx -silent -resp -cname -a -cdn < possible-hostnames.txt |
[...]
marketwatch.com [A] [18.165.183.55] [cloudfront]
nationalgeographic.com [A] [18.165.183.55] [cloudfront]
[...]
当发送请求时,如果 SNI (Server Name Indication) 与 Host
请求头 中的主机名不匹配,CloudFront 会检测到这种不匹配并阻止请求,同时返回以下错误信息:
$ curl --connect-to nationalgeographic.com::18.165.183.55: -H "Host: marketwatch.com." https://nationalgeographic.com/
[...]
<H1>421 ERROR</H1>
<H2>The request could not be satisfied.</H2>
The distribution does not match the certificate for which the HTTPS connection was established with.
[...]
域名前置保护和限制
网络过滤器可以通过比较 SNI 和 Host
头中的主机名是否相同来检测域名前置 - 类似于 Host 头欺骗。然而,仅通过查看 TLS 流量,无法识别正在访问另一个系统,因为目标 IP 地址和 SNI 中的主机名看起来都是合法的,甚至使用了有效的证书(与 SNI 匹配的证书)。
在本系列前面关于 Host 头欺骗的部分中,已经解释了 Fortinet FortiGuard 中这种检测机制的示例。其他产品,如 Paloalto PAN-OS 也配备了此功能 11:
总结
这是另一种值得在您的环境或下一次渗透测试中进行测试的绕过网络过滤器的技术。
域名前置与 SNI 欺骗非常相似,因为它涉及在 SNI 中伪造合法主机名。然而,在这种情况下,连接是建立到一个合法系统,其中 SNI 中的主机名与证书的 Subject/SANs 匹配,确保存在有效证书。
从攻击者的角度来看,这仍然不是万能的绕过方法。如果代理检查 TLS 流量并执行适当的检查,此类攻击可以被检测和防止。
然而,这些防御技术并非完美无缺,有时也可能被绕过。这将在下一篇博文中进行解释。
参考文献
-
通过域名前置实现抗阻塞通信(论文,包括演示和视频):https://www.bamsoftware.com/papers/fronting/↩︎ -
Microsoft:保护我们在 Azure 中的域名前置方法:https://www.microsoft.com/en-us/security/blog/2021/03/26/securing-our-approach-to-domain-fronting-within-azure/↩︎ -
Ars Technica:Google 禁用用于逃避审查的"域名前置"功能:https://arstechnica.com/information-technology/2018/04/google-disables-domain-fronting-capability-used-to-evade-censors/↩︎ -
Amazon CloudFront 请求的增强域保护:https://aws.amazon.com/blogs/security/enhanced-domain-protections-for-amazon-cloudfront-requests/↩︎ -
Fastly:https://www.fastly.com/↩︎ -
GitHub:rvrsh3ll/FindFrontableDomain:https://github.com/rvrsh3ll/FindFrontableDomains/↩︎ -
GitHub:vysecurity/DomainFrontingLists:https://github.com/vysecurity/DomainFrontingLists↩︎ -
GitHub:PeterDaveHello/top-1m-domains:https://github.com/PeterDaveHello/top-1m-domains↩︎ -
DomCop:https://www.domcop.com/top-10-million-websites↩︎ -
GitHub: projectdiscovery/dnsx:https://github.com/projectdiscovery/dnsx↩︎ -
Paloalto PAN-OS 文档,域名前置检测:https://docs.paloaltonetworks.com/pan-os/10-2/pan-os-new-features/content-inspection-features/domain-fronting-detection↩︎
原文始发于微信公众号(securitainment):绕过网络过滤器第三部分:域名前置
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论