Domain fronting基本介绍
导语:域前置技术已经出现有几年了,我一直都理解这个概念,但是从未真正理解它的工作原理。
域前置技术已经出现有几年了,我一直都理解这个概念,但是从未真正理解它的工作原理。直到最近,我跟Chris Truncer一起搞了个项目,他让我们设置域名前置,作为红队测试的一部分。也就是这时,我才不得不开始去认真琢磨和理解这个技术的内部共工作原理。幸运的是,Chris是一个非常不错的老师,它讲这个技术非常透彻,当我们一步一步去分析域前置的内部原理时,这个概念其实也非常简单。
在开始解释域名前置之前,我们先来回顾一下我们是如何获取网页的。
首先是网络请求
· 用户在浏览器里输入一个包含主机名的URL
· 操作系统在对主机名进行DNS查询
· 查到IP后,在两台主机之间建立TCP连接
现在有一个网络连接,应用程序启动并发送HTTP请求。在HTTP/1.0中,web服务器只能为每个IP地址提供一个web网站,因为它无法得知请求该网站的主机名。在HTTP/1.1中,引入了“host”头的概念,这让服务器能够基于提供主机名部署多个虚拟主机,也就是“命名虚拟主机”。服务器会根据已知的虚拟主机列表来检查所请求的主机名,然后选择正确的来提供服务。如果服务器不知道所请求的主机名,则使用默认站点来提供服务。
最基本的HTTP/1.1请求如下:
GET / HTTP/1.1 Host: digi.ninja
在浏览器发起的正常请求中,URL中的主机名应该与主机头中的主机名相匹配,但是也不一定是这样,因为没有任何措施来强制执行该链接。我们可以用curl来做一个演示,下面的这个请求将会与bing.com建立网络连接,但是通过主机头,最终会请求google这个网站。因为Bing并没有一个叫做google.com的虚拟主机,因此我们会得到一个报错:
$ curl -H "Host: google.com" bing.com <h2>Our services aren't available right now</h2><p>We're working to restore all services as soon as possible. Please check back soon.</p>06XZVXAAAAAD6lfm8665lRL+M0r8EuYmDTFRTRURHRTA1MTMARWRnZQ==
我们再来尝试通过英国Google域名来请求澳大利亚Google网站:
$ curl -H "host: www.google.com.au" www.google.co.uk <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title>...
这个请求成功了,因为UK Google服务器知道所有不同的虚拟主机,所以能够正确的转发请求并返回正确的内容。
现在我们已经了解了基础知识,我们来看看它是如何应用于域名前置的。
当我们在CDN(例如Amazon Cloudfront,Cloudflare,Microsoft Azure CDN或者是Google cloud CDN)上设置站点时,需要设置一个域名的CNAME记录来指向CDN服务器,并且有一个类似于“命令虚拟主机”需要在CDN web服务器上设置,这样它才能响应请求。该设置会提供一个“原始服务器”,会与入站的域进行配对,所以它才知道去哪里获取实际的内容并提供服务。
上面我们已经演示过,用来进行网络连接的主机名不一定要与所请求的网站相匹配,所以我们可以为部署在CDN上的一个站点使用主机名,但是在主机头中指向不同的站点。
那证书问题怎么办,使用不匹配的主机名和主机头不会出什么问题吗,不会造成证书警告或者泄露信息吗?当然不会。回到文章开头,设置的第一件事就是网络连接,这里就开始用到TLS了。一旦TCP连接成功建立,TLS就开始协商,并且全都是基于发起连接的主机名,主机头在应用层的流量中,并且在所有低层连接建立之前不会查看。我们可以继续使用Bing和Google的例子来演示,通过HTTPS来发起请求,同时使用curl来请求连接中的更多信息,如下:
$ curl -v -H "Host: google.com" https://bing.com * Rebuilt URL to: https://bing.com/ * Trying 13.107.21.200... * TCP_NODELAY set * Connected to bing.com (13.107.21.200) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Client hello (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=www.bing.com * start date: Jul 20 17:47:08 2017 GMT * expire date: Jul 10 17:47:08 2019 GMT * subjectAltName: host "bing.com" matched cert's "bing.com" * issuer: C=US; ST=Washington; L=Redmond; O=Microsoft Corporation; OU=Microsoft IT; CN=Microsoft IT TLS CA 5 * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Using Stream ID: 1 (easy handle 0x559a18d7f900) > GET / HTTP/2 > Host: google.com > User-Agent: curl/7.58.0 > Accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS updated)! < HTTP/2 400 < x-msedge-ref: 0OPdbXAAAAACPvltTXmg8T6Ynwb1og0T8TE9OMDRFREdFMDQyMABFZGdl < date: Thu, 07 Feb 2019 09:15:35 GMT < * Connection #0 to host bing.com left intact <h2>Our services aren't available right now</h2><p>We're working to restore all services as soon as possible. Please check back soon.</p>0OPdbXAAAAACPvltTXmg8T6Ynwb1og0T8TE9OMDRFREdFMDQyMABFZGdl
请求之后,会有很多的输出结果,但最重要的两行如下:
subject: CN=www.bing.com subjectAltName: host "bing.com" matched cert's "bing.com"
这表明正在使用Bing的证书协商TLS连接,没有警告,因为证书有效,并且在HTTP请求中发送主机头之前也没有涉及到Google。
我跟Chris遇到的情况是这样的,我们使用前置技术来获取某公司基于HTTPS的CC通信,该公司使用了web过滤器来判断主机头,这个主机头是用来发起请求的。他们没有进行SSL剥离,这一点十分重要,因为这样可以让他们了解HTTP流量并且让他们也可以根据主机头来进行判断。我们选择了一家托管在Cloudfront的公司,该公司名声还不错,我们希望可以通过他们的过滤器。我们在Cloudfront上设置好我们的C2站点,将它的源指向我们的真实服务器。自定义的beacon软件使用正常的主机名来进行网络连接,在主机头中使用恶意的主机名。对于公司的过滤器来说,我们是在与一个正常的,值得信任的网站通信,但是CDN看到并响应了C2站点的请求,这些请求将所有流量直接转发到我们的服务器中。
在这个例子中,我们讲到了如何隐藏C2流量,不过这个技术也可以用来绕过审核过滤器和其他类似的情况。绕过审核的方法跟上面的例子相同,除了有一点,就是要查看的站点,前置了一个可信任站点和自定应浏览器插件,或者是本地网络代理,是否替换了主机头为正确的值。
如果你管理着一个域名并且通过CDN提供服务,你可能会想,我应该怎么做来防止我的好名声被滥用?依我看,啥也做不了。因为HTTP工作方式本身是存在漏洞的,网络连接和应用程序流量之间断开连接也是存在问题的。当你将你的站点托管在与其他站点共享的平台时,一旦建立了网络连接,所有其他站点都是可以访问的。甚至没有任何日志,你可以用来进行检查,因为当CDN见到主机头时,所有的流量就都转发到恶意的站点去了,所有的日志也同样在它的账户中。你唯一能做的是查看DNS日志并且尝试统计网站流量和请求,如果你看到有很多请求,但是却没有多少流量,那么这肯定不正常。
如果你想自己设置云端前置域名,你可以参考我的一篇文章Cloudfront域名前置--有效案例。
相关文章:
发表评论