注意:本文分享给安全从业人员,网站开发人员和运维人员在日常工作中使用和防范恶意攻击,请勿恶意使用下面描述技术进行非法操作。

[TOC]

0x00 前言介绍

描述:子域名接管漏洞通常被滥用于以下几个目的:恶意软件分发、网络钓鱼/鱼叉式网络钓鱼、XSS 、身份验证绕过等等。由于某些证书颁发机构仅需要域验证,因此也可以轻松生成SSL证书。

1
sub.expample.com(常规域名) 60 IN CNAME anotherdomain.com.(规范域名)

子域名接管是注册不存在的域名以获得对另一个域的控制权的过程常见的情况如下:

  • 1.域名(例如sub.example.com)将CNAME记录用于另一个域(例如sub.example.com CNAME anotherdomain.com)。
  • 2.在某个时间点,anotherdomain.com到期并可供任何人注册。
  • 3.由于未从example.com DNS区域删除CNAME记录,因此注册anotherdomain.com的任何人都可以完全控制sub.example.com,直到删除DNS记录。

注意事项:

  • 使用子域名接管,攻击者可以从合法域发送网络钓鱼电子邮件,执行跨站点脚本(XSS)或破坏与域关联的品牌声誉。
  • 子域名接管不仅限于CNAME记录/NS记录/MX记录甚至A记录也会受到影响。

0x01 子域名接管原理

描述:我们在了解子域名接管的时候需要了解一哈DNS解析流程:

WeiyiGeek.

WeiyiGeek.

CNAME记录的域名的Web浏览器的行为流程:

WeiyiGeek.

WeiyiGeek.



子域名接管漏洞类型:

  • CNAME子域名接管: CNAME子域接管的主要类型之一是叫做互联网常规域名的规范域
  • NS子域名接管: 一个NS记录的规范域名的基本域可用于注册
  • MX子域名接管

(1)CNAME子域名接管漏洞的成因:

  • 因为域名(源域名)配置了CNAME,但是CNAME指向的域名并没有被注册。那么攻击者可以注册这个CNAME指向的域名,就可以控制了源域名。
  • 危害:绕过HttpOnly和Secure Cookie的安全配置,盗取用户的cookie
  • CNAME子域名接管的整个流程如下:
    • 1.源域名(sub.example.com)设置了一个CNAME且指向了sub.weiyigeek.github.io记录
    • 2.检查weiyigeek.github.io是否被注册,如果没有注册就可以注册创建恶意页面最终接管sub.example.com

(2)NS子域名接管漏洞的成因:

  • 域名的NS记录中如果有一个域名没有被注册那么这个域名就可能被接管。(查找类似SERVFAIL或的响应,REFUSED并根据其发出警报)
  • 例如:sub.example.com有两个NS记录,分别是ns1.vuln.com, ns2.novuln.com,
    • 如果攻击者注册了vuln.com这个域名,那么就有50%的几率受到攻击。
    • 如果DNS解析选择了ns1.vuln.com,那么攻击者可以返回一个钓鱼页面,并非原来sub.example.com的页面,并且会缓存很长的时间,攻击者可以设置TTL的时长。

(3)MX子域名接管漏洞的成因:

  • 由于MX记录仅用于接收电子邮件,因此在MX记录中获得对规范域名的控制仅允许攻击者接收发往源域名的电子邮件(邮件伪造)。
  • 虽然影响不如CNAME或NS子域名接管那么重要,但MX子域名接管可能会在鱼叉式网络钓鱼攻击和知识产权窃取中发挥作用。

原理解析案例:

  • 假如我拥有一个wolframe.eu用于测试目的的域名,通过更改dig谷歌DNS服务器@8.8.8.8此域的(权威)名称服务器,为四个AWS服务器之一来获得权威性答案:
    1
    dig ns [email protected] +nostats
    WeiyiGeek.

    WeiyiGeek.

  • 实际DNS区域是由AWS管理的(更具体地说是AWS Route53),比如上面指定NS记录指向的DNS服务器是不权威的,则得到的结果是不权威的答案(非权威性意味着它不是由权威DNS服务器(在此示例中为四个AWS之一)返回的,相当于是一个中间人的形式;
  • 您可以看见wolframe.eu本身只有一个A记录设置为1.1.1.1;所以一旦DNS请求*.wolframe.eu就会随机选择这上面这四个AWS名称服务器之一并返回A记录结果;

    WeiyiGeek.

    WeiyiGeek.

  • 采用DNSPython模块自定义DNS解析器

    1
    2
    3
    4
    5
    6
    7
    import dns
    import dns.rdatatype

    for NAMESERVER_IP in NAMESERVER_IPS:
    custom_resolver = dns.resolver.Resolver()
    custom_resolver.nameservers = [NAMESERVER_IP]
    q = custom_resolver.query(DOMAIN, dns.rdatatype.A)

总体而言,应通过以下过程扩展自动化:

WeiyiGeek.

WeiyiGeek.

注意事项:

  • Web浏览器隐式地信任放在DNS解析器返回的任何内容上。这种信任意味着当攻击者获得对DNS记录的控制时,绕过所有Web浏览器安全策略(例如,同源策略)。带来相当大的安全威胁,因为子域名接管会破坏域名的真实性,攻击者可以通过多种方式利用域名的真实性

0x02 子域名接管检查

描述:子域名接管检查漏洞主要是看 CNAME,因此我们可以把收集到子域名的CNAME找出来(当然MX/A也可以但是出现这样的机率是非常少的);
漏洞检查工具: EdOverflow的can-i-take-over-xyz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/bin/bash
#!Coded by Suleman Malik
#!www.sulemanmalik.com

cont(){
rm /tmp/cnames
rm /tmp/cname-ln
rm /tmp/fn-py
}
bl(){
echo -e "\033[0;31m-------------------------------------------------------------\033[0m"
}
ban(){
echo '''
________
/__ ___/
/ / ___ / ___ ___ ___ ___ __
/ / // ) ) //\ \ //___) ) // ) ) || / / //___) ) // ) )
/ / // / / // \ \ // // / / || / / // //
/ / ((___( ( // \ \ ((____ ((___/ / ||/ / ((____ //
'''
}
cont > /dev/null 2>&1
clear
ban
echo -e "\033[0;32m @sulemanmalik_3 v1\033[0m"
bl
echo "File Name:"
read inp
echo ''
echo ''
cot=0
lof=$(wc -l < $inp | sed 's/ //g')
while read dom
do
cot=$(($cot + 1))
echo -ne "\033[0;32mScanning Subdomains:\033[0m $cot/$lof\r"
cname=$( dig CNAME $dom | grep "CNAME" | tail -n1 | cut -c"29-" | sed 's/^.*E//' >> /tmp/cnames)
echo "$cot - $dom --> " >> /tmp/cname-ln
done < $inp
prog=$(awk 'NR==FNR{a[++y]=$0;next}{b[++x]=$0}
END{z=x>y?x:y;while(++i<=z){print a[i],b[i]}}' /tmp/cname-ln /tmp/cnames > /tmp/fn-py)
echo ''
echo ''
cat /tmp/fn-py
sleep 1
echo ''
bl
cont > /dev/null 2>&1

WeiyiGeek.

WeiyiGeek.


0x03 子域名接管利用案例

描述:关于子域名接管首先先得有能让你接管的子域名,所以我们针对子域名要进行收集,然后对比指纹查看是否有接管的可能。
常常使用dig、nslookup、host等命令进行收集查看:

1
2
3
$ nslookup c1h2e1.github.io
$ host c1h2e1.github.io
$ dig c1h2e1.github.io

记录一些典型案例:

案例1:feedpress子域名接管
参考案例:https://hackerone.com/reports/195350

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#podcasts.slack-core.com是CNAME'd to redirect.feedpress.me:
$ dig podcasts.slack-core.com

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;podcasts.slack-core.com. IN A

;; ANSWER SECTION:
podcasts.slack-core.com. 299 IN CNAME redirect.feedpress.me.
redirect.feedpress.me. 3599 IN A 5.135.16.40

;; Query time: 253 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)

思路:首先执行了dig命令发现解析了 redirect.feedpress.me 然而feedpress可以导致子域名接管,通过在Feed上创建我自己的帐户并且注册设置podcasts.slack-core.com作为我订阅的“自定义域名”,在它通过Feed传播之后最终成功的接管了域名podcasts.slack-core.com提供的内容。


案例2:Heroku子域名接管
描述:该漏洞是CNAME子域名接管漏洞类型案例;
页面特征:

WeiyiGeek.

WeiyiGeek.

利用条件:CNAME指向 herokudns.com的子域如果一个子域使用Heroku 服务的子域名,例如 vuln.example.com 显示如上错误页面,当通过子域名挖掘时,他就会产生子域名接管漏洞

vuln.example.com 60 IN CNAME vuln.example.com.herokudns.com

漏洞利用:
1.注册Heroku(https://signup.heroku.com/)
2.在Heroku上部署应用程序。
(1)安装git
(2)安装 heroku cli

1
curl https://cli-assets.heroku.com/install.sh | sh

(3)创建一个简单页面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cd ~
mkdir herokudeploy
cd herokudeploy
echo "{}" > composer.json
echo "Subdomain takeover PoC" > index.html
touch index.php

#编辑index.php
<?php header( 'Location: /index.html' ) ; ?>

#接下来,
git init
git add .
git commit -m "just simple poc"
heroku apps:create justsimplesubdomaintakeoverpoc

如果Heroku中不存在应用程序的名称,则将创建应用程序。此外如果您从未登录过Heroku,系统会要求您提供Heroku帐户电子邮件和密码。请登录然后将本地文件推送到Heroku仓库。

git push heroku master

您正在部署的应用程序可以在*.herokuapp.com中看到。
本教程中的示例变为:https://justsimplesubdomaintakeoverpoc.herokuapp.com
3.添加要覆盖的子域,然后添加域即可

WeiyiGeek.

WeiyiGeek.


案例3:Tumblr子域名接管
描述:该漏洞是CNAME子域名接管漏洞类型案例;
要在Tumblr中使用自定义域,我们需要添加A记录,如果使用的是主域则该记录将指向66.6.44.4,如果Tumblr自定义域位于子域上则添加CNAME,例如我的blog.site.com然后CNAME是您拥有的tumblr子域site.tumblr.com。
攻击过程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ curl -I www.leifroswold.com
HTTP/1.1 404 Not Found
Server: openresty
Date: Mon, 24 Sep 2018 15:14:30 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Vary: Accept-Encoding
Vary: Accept-Encoding
X-Rid: 57de79ef9b33ae549a1795eecfd68570
P3p: CP=Tumblr s privacy policy is available here: https://www.tumblr.com/policy/en/priva

#用dig查看他以前用过的tumblr用户名。
$ dig www.leifroswold.com
.....
;; ANSWER SECTION:
www.leifroswold.com. 942 IN A 66.6.44.4 #这里配置错误实际应该设置CNAME指向字节Tumblr域名

现在转到您的Tumblr博客设置然后更改域名,因为没有创建CNAME记录,我们可以使用任何用户名的tumblr子域。只需要添加想要定义的域然后保存即可;

WeiyiGeek.

WeiyiGeek.


案例4:Fastmail 子域名接管
描述:Fastmail也存在子域名接管漏洞。因为当我们设置自定义域时没有额外的验证。
漏洞特征:

WeiyiGeek.

WeiyiGeek.

利用条件:

  • 1.CNAME 可定义为 web.messagingengine.com
  • 2.A 记录 指向 66.111.4.53 66.111.4.54

漏洞利用:
第一步是添加要覆盖的自定义域。进入设置菜单,然后进入域。
第二步是创建网站。成功添加要覆盖的域后,现在我们创建公共站点。首先在左下角菜单中,选择“ 文件”,上传html文件。
第三步是单击 websites 设置域名,最终使用www.zafkiel.net接管 web.messagingengine.com。

WeiyiGeek.

WeiyiGeek.


总结可接管服务:
参考:https://github.com/EdOverflow/can-i-take-over-xyz/blob/master/README.md

WeiyiGeek.

WeiyiGeek.


WeiyiGeek.

WeiyiGeek.


WeiyiGeek.

WeiyiGeek.

补充:启发式测试以确定是否可以接管子域/域

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Engine 	Possible 	Fingerprint 	Reference
AWS/S3 Yes The specified bucket does not exist
Bitbucket Yes Repository not found
Campaign Monitor Yes Support Page
Cargo Collective Yes 404 Not Found Cargo Support Page
Cloudfront Yes Bad Request: ERROR: The request could not be satisfied https://blog.zsec.uk/subdomainhijack/
Desk No
Fastly Yes Fastly error: unknown domain:
Feedpress Yes The feed has not been found. https://hackerone.com/reports/195350
Freshdesk No Freshdesk Support Page
Ghost Yes The thing you were looking for is no longer here, or never was
Github Yes There isn't a Github Pages site here. https://hackerone.com/reports/263902
Gitlab No https://hackerone.com/reports/312118
Google Cloud Storage No
Help Juice Yes We could not find what you're looking for. Help Juice Support Page
Help Scout Yes No settings were found for this company: HelpScout Docs
Heroku Yes No such app
JetBrains Yes is not a registered InCloud YouTrack
Mashery No Unrecognized domain https://hackerone.com/reports/275714
Microsoft Azure Yes
Sendgrid No
Shopify Yes Sorry, this shop is currently unavailable.
Squarespace No
Statuspage Yes You are being redirected https://hackerone.com/reports/49663
Surge.sh Yes project not found https://surge.sh/help/adding-a-custom-domain
Tumblr Yes Whatever you were looking for doesn't currently exist at this address
Tilda No Please renew your subscription
Unbounce Yes The requested URL was not found on this server. https://hackerone.com/reports/202767
UserVoice Yes This UserVoice subdomain is currently available!
Wordpress Yes Do you want to register *.wordpress.com?
WP Engine No
Zendesk Yes Help Center Closed Zendesk Support


简要概述了CloudFront(虚拟主机架构)非常相似的其他云服务。

  • Amazon S3 - 以前简要提到了Amazon S3。用于访问存储桶的默认基本域并不总是相同,并且取决于所使用的AWS区域。AWS文档中提供了Amazon S3基本域的完整列表。与CloudFront类似,Amazon S3允许指定备用(自定义)域名以访问存储桶的内容。

  • Heroku - Heroku是一个平台即服务提供商,可以使用简单的工作流程部署应用程序。由于需要访问应用程序,Heroku使用herokuapp.com上形成的子域公开应用程序。但是也可以指定自定义域名以访问已部署的应用程序。

  • Shopify - Shopify提供了一种在云中创建和自定义电子商务商店的方法。访问商店的默认子域是在myshopify.com上构建的。作为之前描述的服务,Shopify允许指定备用域名。值得注意的是Shopify验证了正确的CNAME记录配置。但是,此验证不是域名所有权验证。Shopify仅检查备用域的DNS区域中存在的准确CNAME记录。因此,此验证不会阻止子域名的接管。

  • GitHub - GitHub是Git的版本控制存储库。GitHub还允许使用他们的GitHub Pages项目进行免费的虚拟主机托管。此Web托管通常用于项目的文档,技术博客或支持Web页面到开源项目。除github.io下的默认域名外,GitHub Pages还支持自定义域名。

  • Microsoft Azure - Microsoft Azure是一个更加突出的云提供商,类似于AWS。与上面提到的云服务相比,它不同,因为它不提供虚拟主机架构。简而言之,对于每个云服务,Azure都会创建自己的具有自己IP地址的虚拟机。因此,域名和IP地址之间的映射是明确的(一对一映射)。值得注意的是,由于这不是常规虚拟主机设置,因此不一定必须在资源设置中明确定义配置CNAME记录。Azure提供多种云服务,但本文中讨论的云服务具有cloudapp.net和azurewebsites.net的默认域。其文档描述了使用A或CNAME记录设置域名和Azure资源之间的链接(指向前面提到的两个域之一)。一个有趣的观察是,对于A记录,Azure使用TXT记录进行域所有权验证。但是,对于CNAME记录而言并非如此,因此即使在Microsoft Azure的情况下也可以进行子域接管。


案例5:Surge.sh 子域名接管
漏洞特征:

WeiyiGeek.

WeiyiGeek.

利用条件:
CNAME 可定义为 na-west1.surge.sh,A 记录 指向 45.55.110.124 (其中一个条件得到满足,我们就可以接管。)
例如:

1
2
3
4
5
6
7
8
9
10
11
dig agilesysadmin.com

; <<>> DiG 9.10.3-P4-Ubuntu <<>> agilesysadmin.com
;; global options: +cmd
.......
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;agilesysadmin.com. IN A

;; ANSWER SECTION:
agilesysadmin.com. 3599 IN A 45.55.110.124

漏洞利用
第一步,安装nodejs后,执行: sudo npm install --global surge

第二步,创建一个文件夹,上传自定义html文件

1
2
3
mkdir surge
cd surge
nano index.html

第三步,运行 sunger : surge path_project namadomain.
比如:surge /home/linuxsec/surge/ agilesysadmin.com
WeiyiGeek.

WeiyiGeek.


0x04 安全防御

建议:在绑定第三方域名解析记录的时候,需要了解其业务解析流程并进行CNAME安全配置,如果不使用第三方页面托管服务将需要取消其解析记录;


0x05 来源参考