本文翻译自:https://www.hackerone.com/blog/Guide-Subdomain-Takeovers
根据HackerOne的Hacktivity 版块(版块内有大量已公开/未公开的安全报告) 可以清楚地看到子域名劫持报告所占的份额。 自从Detectify 关于子域名劫持的精彩的系列报告以来,bug悬赏行业发现有关子域名劫持的报告迅速激增。子域名劫持的大概意思是,主站指向了一个已停用的子域名,而攻击者通过在第三方服务商注册,从而在子域名上提供危险的内容 。作为黑客和安全分析师,我每天都会处理这类问题。 我今天的目标是撰写一份指南,包含理解,查找,利用和报告子域错误配置。 本文假设读者对域名系统 (Domain Name System, DNS)有基本的了解,并知道如何设置子域(Subdomain)。
译注:本文中“子域”与“子域名”同义。
如果你之前从未听说过子域名劫持或希望再听一遍,我已经设计了一个示例场景来帮助理解基础知识。 对于这种情况,让我们假设example.com
是测试目标,运行example.com
的团队对此有一个bug悬赏计划。 在枚举属于example.com的所有子域时(我们将在稍后探讨如何枚举)黑客偶然发现了subdomain.example.com
,一个指向GitHub页面的子域名。 我们可以通过查看子域名的DNS记录来确定这一点; 在此示例中, subdomain.example.com
具有多个A记录,指向GitHub的自定义页面的专用IP地址 。
$ host subdomain.example.com subdomain.example.com has address 192.30.252.153 subdomain.example.com has address 192.30.252.154 $ whois 192.30.252.153 | grep "OrgName" OrgName: GitHub, Inc.
导航到subdomain.example.com
,我们会发现以下404错误页面。
黑客大多会从这一点开始入手。 此404页面表示顶级目录下没有提供任何内容,我们应该尝试将此子域加到我们的个人GitHub仓库。 请注意,这并不表示可以在所有应用上进行劫持。 某些应用会同时检查HTTP和HTTPS响应,而某些应用程序可能根本不受劫持攻击。
将子域添加到我们的GitHub项目后,可以在别人的网址subdomain.example.com
看到我们的GitHub仓库的内容——这说明我们已成功声明了这个二级域名。 出于演示目的,主页现在显示一张青蛙的图片。青蛙找虫(bug)。
二阶子域名劫持,我喜欢称之为“ 坏链劫持 ”。这个易受攻击的子域可以不属于目标,但是能够往目标的网站上提供内容。 具体一点的说,目标页面上所导入的多项资源,比如一连串的JavaScript脚本,其中就有一个来自已经被黑客劫持的子域。最终导致储存型跨站点脚本攻击,因为攻击者可以在目标页面上加载任意代码并使其在客户端执行。 我在本指南中专门列出此问题,是为了突出这样一个事实:作为黑客,我不会把自己束缚在目标主机的子域上。我会通过检查源代码并扩展活动范围到目标所依赖的所有主机上来寻找可被劫持的子域。
这也是为什么说,当你劫持一个子域名时,绝对值得投入时间去查看是否有其他页面从你的子域导入资源。
我们已经概述了在错误配置的子域上提供内容会产生什么样的后果,下一步是掌握查找易受攻击的子域所需的各种技术,技巧和工具。
在深入学习之前,我们必须首先区分爬虫爬取和暴力枚举。这两个过程都可以帮助你发现子域,但可能会有不同的结果。 爬虫爬取是一种被动侦察技术,使用外部的第三方服务和来源来收集属于特定主机的子域。 某些服务(例如DNS Dumpster和VirusTotal)可以检索过去已被爬取的子域,这可以让你不花费太多精力就能快速地收集和分类那些爬取结果。
DNS Dumpster上属于reddit.com子域的结果。
可供爬取的不只有索引页面,还要记住检查目标的GIT仓库,内容安全策略头部信息,源代码,问题跟踪器等等。来源列表是无穷无尽的,我不断去发现能增加爬取结果的新方法。 你会发现使用的技巧越奇特,就越有可能找到别人没有发现的东西。因此,要开动脑筋去创新,并在实践中检验你的想法,以此去刷各家的漏洞悬赏榜。
Ahmed Aboul-Ela的Sublist3r可以说是我能想到的最简单的子域利用工具。 这个轻量级Python脚本从众多搜索引擎,SSL证书以及DNS Dumpster这样的网站上收集子域。安装过程非常简单:
$ git clone https://github.com/aboul3la/Sublist3r.git
$ cd Sublist3r
$ sudo pip install -r requirements.txt
当暴力检索子域时,黑客会遍历一个词表,并根据响应确定主机是否可连接。 请注意,这点非常重要:始终检查目标是否启用了通配符。否则最终会出现大量误报。 通配符意味着所有子域都会返回一个会导致结果出现偏差的响应。应对的方法就是你可以通过向目标请求一个很可能尚未设置的看似随机的主机名来轻松检测通配符是否启用。
$ host randomifje8z193hf8jafvh7g4q79gh274.example.com
为了在暴力枚举子域名的同时获得最佳结果,我建议你创建自己的个人词汇表,其中包含你过去遇到过的或通常与你感兴趣的服务相关联的词汇。例如,我经常寻找包含关键字“jira”和“git”的主机,因为我发现易受攻击的Atlassian Jira和GIT实例比较常见。
如果你计划暴力枚举子域名,我强烈建议你查看Jason Haddix的词表 。 Jason不厌其烦地将各个子域发现工具的列表合并到了一个列表。
要想在查找子域时获得更多的结果,无论是爬取还是暴力枚举,都可以使用称为指纹识别的技术。 指纹识别允许你为目标创建自定义词表,从而揭示通用词表不能发现的属于目标的信息资产。
子域名劫持有各种各样的工具。 本节会介绍一些前文没提到的著名工具。
想递归暴力枚举子域?来看看Shubham Shah的Altdns脚本。 在通过Altdns对目标进行指纹识别后运行自定义词表可能会非常有益。 我喜欢使用Altdns生成词表,然后运行其他工具。
另一个由Shubham提供的工具, Commonspeak是一个使用Google的BigQuery生成词表的工具。 效果是生成反映当前趋势的词表。在科技日新月异的时代,这一点尤为重要。 如果你想更好地了解此工具的工作原理以及从哪里收集关键字, 请务必阅读https://pentester.io/commonspeak-bigquery-wordlists/ 。
SubFinder是一款将爬取和暴力枚举结合在一起的工具。 我自己使用SubFinder而不是Sublist3r作为我的通用子域发现工具。 为了获得更好的结果,请提供给SubFinder用于查找子域的各种服务的API密钥。
Massdns是一个超快的子域枚举工具。 如果其他工具耗时一刻钟完成任务,Massdns可以在一分钟内完成。 请注意,如果你打算运行Massdns,请确保为其提供有效解析器列表。 请阅读https://public-dns.info/nameservers.txt ,测试解析器,看看哪些返回最佳结果。 如果你不更新你的解析器列表,你最终会得到很多误报。
$ ./scripts/subbrute.py lists/names.txt example.com | ./bin/massdns -r lists/resolvers.txt -t A -o S -w results.txt
在寻找子域名劫持时,自动化是关键。 顶级BUG赏金猎人不断监测目标的变化,并不断关注他们可以找到的每个子域。 对于本指南,我认为没有必要专注于监控的搭建。 相反,我想坚持简单的技巧,既可以节省你的时间,又可以轻松实现自动化。
我最想自动化的任务是从主机列表中过滤掉活动的子域。 爬取子域的时候,某些结果会过时且无法使用。因此,我们需要确定哪些主机是活动的。 请记住,如果主机没有解析,并不一定意味着它不能被劫持,我们稍后将会详细说明。 使用host命令可以轻松完成此任务 ——不再处于活动状态的子域将返回错误。
while read subdomain; do if host "$subdomain" > /dev/null; then # If host is live, print it into # a file called "live.txt". echo "$subdomain" >> live.txt fi done < subdomain-list.txt
最终,我们将迄今为止的所有内容放在一起,我们会得到以下工作流程。
下一步是概览各个子域。 有两种选择:第一种是在所有子域上运行屏幕截图脚本; 第二种是将页面内容存储在文本文件中。
截图,我的首选工具目前是EyeWitness 。 此工具生成一个HTML文档,其中包含主机列表中的所有屏幕截图,响应body和header。
$ ./EyeWitness -f live.txt -d out --headless
对于某些情况,EyeWitness可能有点过于沉重,你可能只想通过向子域的顶级目录发送简单的GET请求,然后将页面内容存储。 对于这样的情况,我使用Tom Hudson的meg。 meg并行发送请求,然后将输出存储到纯文本文件中。 这使得它成为一种非常有效的轻量级解决方案,支持子域筛选,还支持使用grep命令查找关键字。
$ meg -d 10 -c 200 / live.txt
我们需要注意一个特殊情况,FransRosén在他的演讲“ 使用云提供商进行DNS劫持 - 无需验证 ”中强调了这一点。 当你遇到死的DNS记录时,不要总是认定你不能劫持该子域。 正如Frans所指出的那样, host
命令可能会返回错误,但是dig
命令会揭示死的记录。
好了,现在你控制了属于目标的子域。接下来你可以做什么? 在决定通过配置错误的子域进行欺骗攻击前,了解子域如何与主站和目标的核心服务进行交互至关重要。
subdomain.example.com
可以修改cookies的范围到example.com
。 这一点很重要,一定要记住,因为这能让你劫持受害者在主站上的会话。
通过output.jsbin.com,我们可以为jsbin.com设置cookie。
如果主站容易受到会话固定攻击并使用HTTPOnly cookies ,则可以设置cookie,随后当用户重新启动浏览器时,你的恶意cookie会把新生成的cookie顶下去,因为cookie按age排序。
跨域资源共享(Cross-Origin Resource Sharing, CORS)是一种允许主机共享页面内容的技术。 应用程序使用一组规则创建范围,允许主机在此范围内读取经过身份验证的数据。 某些应用程序允许子域发出跨域HTTP请求,并已经假设子域是可信实体。 当你劫持子域名寻找CORS 头部信息时—— Burp Suite Pro的扫描程序通常会选出它们 —— 记得去查看应用程序是否将子域名列入白名单。 这可能允许你从主应用程序上的经过身份验证的用户窃取数据。
与跨域资源共享类似, Oauth 流程也有一个白名单机制,开发人员可以指定应该接受哪些回调URI。 这里,危险再次出现:在子域名被列入白名单的情况下,你可以在Oauth流程中将用户重定向到你的子域名,从而可能泄露他们的Oauth令牌。
内容安全策略 (Content-Security Policies, CSP)是另一个应用程序的可信主机列表。这个列表的目的是限制哪些主机可以在应用程序的上下文中执行客户端代码。 如果想要最小化跨站点脚本的影响,这里的头部信息特别有用。 如果你的子域包含在白名单中,则可以使用子域绕过策略并在应用程序上执行恶意的客户端代码。
$ curl -sI https://hackerone.com | grep -i "content-security-policy" content-security-policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src www.youtube-nocookie.co m; connect-src 'self' www.google-analytics.com errors.hackerone.net; font-src 'self'; form-action 'self'; frame-ancestor s 'none'; img-src 'self' data: cover-photos.hackerone-user-content.com hackathon-photos.hackerone-user-content.com profi le-photos.hackerone-user-content.com hackerone-us-west-2-production-attachments.s3-us-west-2.amazonaws.com; media-src 's elf' hackerone-us-west-2-production-attachments.s3-us-west-2.amazonaws.com; script-src 'self' www.google-analytics.com; style-src 'self' 'unsafe-inline'; report-uri https://errors.hackerone.net/api/30/csp-report/?sentry_key=61c1e2f50d21487c 97a071737701f598
如“ Cure53浏览器安全白皮书 ”中所述,Internet Explorer,Edge和Safari支持X-Frame-Options
中的ALLOW-FROM
指令,这意味着如果你的子域被列入白名单,则可以构建目标页面,以此执行点击劫持攻击。
这一项不一定包含在你的安全报告中,但值得注意的是,某些密码管理器会自动在主站应用程序的子域上填写登录表单,这样毫无疑问会泄露账户和密码。
Rojan Rijal 演示了他如何通过在SendGrid上声明一个uber.com的子域来拦截电子邮件。
在你尝试报告子域名劫持之前,请确保你能够在子域名上实际提供内容。 但是,无论你做什么,都不要在索引页面上发布任何内容,即便它是如前所示的青蛙——一张人畜无害的图片。 最佳做法是在HTML注释中加一条隐秘的消息,指向一个隐藏路径的HTML文件。 这应该足以在向bug悬赏计划提交报告时证明你发现的问题。 只有在网站方授予许可后,你才能着手扩大渗透并实际证明漏洞的整体影响。 但在大多数情况下,站方应该已经意识到影响,并且你的报告应该包含有关子域名劫持的可利用性的信息。
在撰写关于子域名劫持报告的时候不必着急,因为这类报告的奖金虽然很高,但是,没有人能够抢先报告拿走你的奖金。因为你是(我希望是)唯一的控制子域名的人。
作者注:我只见过一个关于子域名劫持的重复报告,所以还是仍有那么一丢丢可能。但这种小概率情况恰好落在你身上的可能性相当小。
我们已经到了本指南的末尾,我期待在HackerOne上对你的子域名劫持报告进行分类。 在寻找子域名劫持时,请记住练习并应用本文中列出的技巧。
最后,我要感谢FransRosén , Filedescriptor , Mongo和Tom Hudson就子域名劫持和我交换意见。 我的白帽旅途中的很多发现都是基于他们的研究。