在 HackerOne 实时更新的公开漏洞推送 Hacktivity 消息中, 我们可以发现, 其中的子域名劫持漏洞 (Subdomain Takeover) 占比不少. 自从 2014 年 Detectify 实验室发布了 一系列子域名劫持攻击姿势 的文章之后, 众测行业出现了大量此类问题相关的上报漏洞.
子域名劫持漏洞的基本前提可以大致的解释为, 发生了错误配置情况, 对应主机指向了一个当前未在用的特定服务, 这样一来, 攻击者就能通过在该特定的第三方服务中注册账户, 声明对该子域的接管权限, 由此, 在该子域上部署网络服务, 实现对该子域有目的的利用. 作为一位白帽和安全分析师, 我每天都会遇到这类漏洞问题. 今天, 我就来和大家聊聊子域名错误配置导致的子域名劫持漏洞相关的理解, 挖掘, 利用和上报, 文章假设读者具备了一定的 DNS 知识和子域名设置基础.
子域名劫持漏洞介绍
如果你此前不了解子域名劫持漏洞, 想从基本原理听起, 我这里就设计了一个简单的实例场景. 在该场景中, 假设 example.com 是你在参与漏洞众测的目标网站, 经过对 example.com 的所有子域名进行枚举之后, 发现了其中一个子域名 subdomain.example.com, 该子域名错误配置指向了一个 GitHub 页面. 由此, 我们可以先来看看该子域名的 DNS 记录, 在这里假设该子域名所属的 GitHub 页面存在多条指向 GitHub 特定 IP 地址的 A 记录:
- $ 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 项目之后, 就能把它部署上我们自己的 web 内容了, 也就是说, 我们就能把子域名接管为我们自己所有了. 如下可以让 subdomain.example.com 指向任何你部署的网页内容:
二阶子域名劫持漏洞
这里所说的二阶子域名劫持漏洞, 有点像过期坏链劫持(Broken Link Hijacking), 这种情况下的子域名, 并不属于目标网站所有, 但却是用来运行目标网站的网页内容的. 也就是说, 如目标网站网页内容中某个资源需要从外部导入的第三方资源, 举例来说, 像 JS 文件一样, 那么, 攻击者就可以通过 JavaScript 的 Blob 对象类型进行导入, 从而声明对目标网站相关子域名的控制权限.
这种在网页页面的主机劫持可以导致存储型跨站漏洞, 攻击者可以针对目标网站页面, 利用这种模式来加载任意的客户端代码. 我在此提出这种威胁, 就是希望我们不要把想像力只限制在子域名身上, 还可以延伸到代码审查和目标网站的主机映射等方面.
像下图网站中, 存在导入的第三方资源 http://subdomain.example.com/script.JS , 那么, 能否存在 subdomain.example.com 可被劫持, 从而我可以变换 script.JS 实现对 example.com 的间接劫持呢?
当然, 也要说明的是, 如果你想对某个子网站域名进行劫持, 那么可以花点时间, 去看看该网站上各个页面中的第三方导入资源是否能被劫持利用.
子域名枚举和探测
现在, 我们对如何在错误配置的子域名上部署我们自己的网页内容有了大致了解, 接下来, 我就来介绍发现漏洞子域名的各种技术, 技巧和工具.
在深入之前, 我们需要区分检索 ( Scraping ) 和暴力猜解 (Brute Forcing) 的不同, 因为这两种方法都能帮助你发现子域名, 但最终结果却有所不同. 检索是一种被动的侦测方式, 它利用 DNS Dumpster 和 VirusTotal 等外部服务和资源, 来收集属于某个特定主机的子域名. 这种方式能快速检索出外部服务资源中之前加载过的子域记录, 算是一种不费太多精力的子域名发现方式. 如以下 DNS Dumpster https://dnsdumpster.com/ 网站中记录的 reddit.com 子域名情况:
检索 ( Scraping ) 方式中不仅中以包含索引页面, 还可以添加进目标网站的 Git 库, 内容安全策略头, 源代码和漏洞跟踪消息等反馈源, 只要你能想得到, 检索列表是非常之多的. 我就经常更新我自己的检索列表资源库, 反正你应用的技术越多越奇特, 那么最终你发现的结果也会与众不同. 所以, 从这一点来说, 在做漏洞众测时, 我们一定要具备创新精神.
Sublist3r 算是检索 ( Scraping ) 方式的一个简单子域名发现工具了, 它利用了轻量级的 Python 脚本, 从各种搜索引擎, SSL 证书和 DNS 记录网站中来收集目标子域名. 具体的安装和应用如下图所示:
- $ Git clone https://GitHub.com/aboul3la/Sublist3r.Git
- $ cd Sublist3r
- $ sudo pip install -r requirements.txt
暴力猜解子域名时, 我们可以依托字典进行迭代请求尝试, 然后根据其响应来判断子域名的有效性. 但请注意, 如果目标网站开户了泛域名 (Wildcard) 模式, 进行子域暴力猜解时, 可能会得到很多误报响应.
泛域名模式 (Wildcard) 也就是说, 所有的子域名解析都可能会对应到同一 IP 地址下, 如 a.example.com 和 ctk.example.com 都会解析到同一个 IP 地址. 使用泛域名, 可以让域名支持无限的子域名, 也可以防止用户输入错误的子域名, 而无法访问网站. 所以, 这个时候, 可以解析一个目标网站不可能使用的子域名, 依其响应来判断是否可以正常解析, 如果能正常响应, 则证明其开启了泛域名模式. 如下:
$ host randomifje8z193hf8jafvh7g4q79gh274.example.com
针对子域名暴力猜解, 我个人认为最好的方式就是, 根据你平时积累的经验, 或个人感兴趣的方式, 创建你自己的猜解字典. 例如, 我经常对 Atlassian Jira 系统和 Git 用例的漏洞挖掘较多, 所以我会在子域名猜解字典中添加进 "jira" 和 "Git" 等相关关键字.
如果你打算创建个人的子域名猜解字典, 我强烈建议你可以参考 Jason Haddix 的字典 , 他花了很多精力, 将各种子域名发现工具的不同列表合并成了一个广泛的字典列表.
指纹识别(Fingerprinting)
为了增加你的子域名发现结果, 不管是检索 ( Scraping ) 还是暴力猜解 (Brute Forcing) 方式中, 都可以采用一种名为指纹识别 (Fingerprinting) 的技术, 这种技术可以通过对目标网站的通用字典创建, 然后以此来显示出那些, 你用普通字典列表无法识别的属于目标网站的资产.
一些经典的子域名发现工具
在这里, 我要介绍一些好用的子域名发现工具:
Altdns https://GitHub.com/infosec-au/altdns
这是 Shubham Shah 开发的一个子域名递归暴力猜解工具, 你先要创建一个目标网站存在的子域名字典 subdomains.txt, 这就是你的通用 fingerprint 字典, 然后再创建一个递归置换字典 words.txt, 然后用 Altdns 命令:
./altdns.py -i subdomains.txt -o data_output -w words.txt -r -s results_output.txt
进行子域生成发现. 我喜欢用 Altdns 来生成字典列表, 然后再配合其它工具来运行发现.
Commonspeak
Commonspeak https://GitHub.com/pentester-io/commonspeak 也是 Shubham 开发的另外一个工具, 它通过 Google 的 BigQuery 查询记录来生成字典列表, 其中包含了当前每天更新的各类子域名, 非常及时快速. 你可以通过查看 这篇文章 , 来了解 Commonspeak 的字典收集和子域提取机制.
SubFinder
这是一个兼具检索 ( Scraping ) 和暴力猜解 (Brute Forcing) 的子域发现工具, 就我个人来说, 我用 SubFinder 比 Sublist3r 多, SubFinder 能从包含 API 接口在内的各种服务中来发现子域名, 最终结果也相对较好.
Massdns
Massdns 是一个非常快速的子域枚举工具, 其它工具可能用 15 分钟才能完成, 但用 Massdns 仅需一分钟. 但如果你想用 Massdns, 得先指定一个有效的 DNS 存根解析器( Resolver), 如这个 https://public-dns.info/nameservers.txt https://public-dns.info/nameservers.tx , 通过其中的 host 进行域名解析发现. 如果你长期不更新这个解析器列表, 结果也可能会出现误报.
$ ./scripts/subbrute.py lists/names.txt example.com | ./bin/massdns -r lists/resolvers.txt -t A -o S -w results.txt
流程自动化
在挖掘子域名劫持漏洞的过程中, 自动化非常关键. 顶级的白帽黑客总会长期关注目标网站的任何变动, 或是对目标网站的所属子域名进行持续的状态跟踪. 本文中, 我们不谈具体的跟踪关注手段, 相反, 我会介绍一些简单技巧, 以便能节省些许挖掘分析时间, 实现一定程度的自动化.
我喜欢用的第一项自动化任务是从一些主机列表中过滤出实时有效的子域名. 因为在子域名检索方法中, 最后的结果可能为有些子域名是过期的, 有些则是不可访问的, 因此, 我们需要检测出哪些主机对应的子域名是实时有效的. 请记住, 正如之后会看到的示例显示, 虽然一些主机不能有效解析, 但也存在被劫持可能. 这里的自动化, 我们就用 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
把所有检测和发现机制抽象化后, 可以表示为以下流程:
接下来需要对子域名有个大致的了解, 这里有两种显示模式, 一种为运行子域名截图脚本抓取所有子域名网站截图, 另一种为存储各个子域名网站的显示内容. 做子域名截图, 可以考虑工具 https://GitHub.com/FortyNorthSecurity/EyeWitness , 它能对目标列表子域名生成一个包含截图, 响应头和标头信息的 html 文件.
$ ./EyeWitness -f live.txt -d out --headless
可能有时候, 你只需要存储子域名网站的简单 GET 请求响应页面内容时, EyeWitness 就显得有点大材小用了. 这个时候, 我会用 Tom Hudson 开发的工具 https://GitHub.com/tomnomnom/meg , 它会向目标子域名发送简单的请求并把响应内容进行存储为明文, meg 相比 EyeWitness 显得更轻量级一些.
$ meg -d 10 -c 200 / live.txt
特殊情况
也存在一种特殊情况需要说明, Frans Rosén 大牛曾在他的演讲《 DNS hijacking using cloud providers - No verification needed 》中提到, 如果你遇到一些 dead DNS records(废弃的 DNS 记录), 不要就表面性地认为其不存在子域名劫持漏洞. 据 Frans Rosén 的观点, host 命令可能会出错, 但如果用 dig 命令的话, 可能就会发现一些 dead records.
漏洞利用
现在, 假设你可以控制目标网站所属的某个子域名, 那么, 接下来该做什么呢? 当你想用这个错误配置的子域名来实现某些可能的攻击场景时, 最关键的是需要去了解这个子域名与目标网站的核心服务存在些什么交互.
Cookies
利用子域名劫持漏洞, 针对可控制的子域名 subdomain.example.com 进行 Web 服务部署, 可以窃取用户隶属于 example.com 的 Cookie, 以此实现劫持受害者会话的目的.
利用在线前端编辑网站 output.jsbin.com, 我们可以对 cookie 进行编辑设置. 如果确定目标网站存在会话 ID 是确知不变的攻击风险(Session Fixation) https://en.wikipedia.org/wiki/Session_fixation , 并且使用了 HTTPOnly 类的 cookie, 那么你就可以对 cookie 进行设置, 当受害者启动浏览器后, 由于 cookie 的按序排列, 你这里的恶意 cookie 将会优先于对方的新生成的 cookie, 从而间接实现了对受害者身份的劫持.
CORS 跨域资源共享
跨域资源共享, Cross-Origin Resource Sharing (CORS), 允许 Web 应用服务器进行跨域的网页访问控制. 在 Web 应用创建的某个域中, 按照一组规则来允许某些网站可以访问提取包括认证数据在内的数据信息. 以某些子域名是可信域名的前提下, 一些 Web 应用还允许子域名执行跨域的 HTTP 请求. 当你挖掘子域名劫持漏洞时, 可以留意一下 COSR 头信息, 在 Burp Suite Pro 专业版中就有这个检测功能, 另外可以看看 Web 应用是否将子域名列入了白名单, 这些设置都可能实现对 Web 授权用户的数据窃取.
OAuth 授权白名单化
与跨域资源共享, OAuth 授权过程同样具备一个白名单机制, 藉此, Web 开发者可以指定指定哪个回调 URIs 是可以接受的. 这里的风险在于, 当存在劫持漏洞的子域名被列入这个白名单中时, 攻击者可以在 OAuth 授权过程中把用户会话重定向到先前那个存在劫持漏洞的子域名中, 以此窃取用户的 OAuth 授权信息.
内容安全策略(Content-Security Policies)
可以说, 内容安全策略是 Web 应用信任的另一个主机列表, CSP 的目的在于限制哪些主机可以在应用中执行客户端代码. 如果希望尽量减少跨站脚本的影响, 这种方式非常有用. 如果你可以劫持控制的子域名包含在白名单中, 你就可以绕过 CSP 限制, 在 Web 应用中执行恶意的客户端代码.
- $ 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 http://www.YouTube-nocookie.co/
- m; connect-src 'self' http://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' http://www.google-analytics.com/ ;
- style-src 'self' 'unsafe-inline'; report-uri
- 97a071737701f598
点击劫持(ClickJacking)
像《 Cure53 Browser Security White Paper 》中提到的那样, 在 X-Frame-Options 标头中, IE,Edge 和 Safari 都支持 ALLOW-FROM uri 机制, 表示该页面可以在指定来源的 frame 中展示, 也就是说, 如果你可劫持控制的子域名在该机制的白名单中, 那么就可以在目标网页应用中构建欺骗页面, 执行点击劫持 (ClickJacking) 攻击.
密码管理器的密码信息泄露
这一点可以不必在一些漏洞上报中进行考虑, 但也是我们值得关注的方面. 某些密码管理器, 如 LastPass 会在一些主网站所属的子域名网站中执行自动密码填充功能, 这相当于让网站设置了一个包含明文密码的非 httponly 类 cookie, 可以方便子域名劫持之后的深入利用.
拦截电子邮件
安全研究者 Rojan Rijal 曾发现了 Uber 基于 SendGrid 服务的某个可劫持子域名, 之后, 利用该子域名, 他成功拦截了 Uber 内部的公司电邮通信, 获取了 Uber 官方 $10,000 美金的奖励.(翻墙 - 点此 查看文字分析 , 点此 观看 PoC 视频 https://www.YouTube.com/watch?v=4dnJWAesPVE )
上报子域名劫持漏洞的注意事项
在你尝试上报子域名劫持漏洞之前, 应该注意以下事项:
请确保在你可劫持控制的子域名上部署了属于你自己的 Web 内容;
部署的 Web 内容尽量简单干净, 最好是一句话之类的标志, 连图片都不要放;
最佳方法就是在你部署的 Web 内容 HTML 文件注释中包含了某个隐秘消息即可, 在与厂商联系协调时, 这就足以证明漏洞问题;
如果厂商给你授权, 为了说明整体的威胁影响, 你可以进一步对这种子域名劫持漏洞做出测试;
大多数情况下, 如果你的漏洞报告中包含了子域名劫持漏洞的利用步骤, 厂商都会都会认可这种漏洞
子域名劫持漏洞属于高危漏洞, 在编写漏洞报告时, 请认真一点, 如果漏洞属实又不属于重复报, 那么恭喜你, 最终你可以获得厂商的大奖.
最后, 感谢我的一众白帽好友 Frans Rosén ,Filedescriptor,Mongo 和 Tom Hudson, 是他们的宝贵意见, 为我这篇文章奠定了基础.
来源: http://www.tuicool.com/articles/bmUrUnR