一篇文章带你读懂 TLS Poison 攻击(三)
2022-11-17 00:5:35 Author: 白帽子(查看原文) 阅读量:27 收藏

STATEMENT

声明

由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测及文章作者不为此承担任何责任。

雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。

NO.1 前言

本篇文章是《一篇文章带你读懂 XXX 攻击》系列的第二篇文章,主要讲述了 TLS Poison 攻击对应的三种攻击方式、一些可能算是“新”的 DNS Rebinding 技巧以及一些关于 IP 选择探索等内容。

使用《一篇文章带你读懂 XXX 攻击》的标题既是为了督促自己把一个攻击尽可能多的细节尽可能地搞懂,也是为了提升自己的写作能力以及表述水平。本文旨在帮助大家了解学习 TLS Poison 攻击,希望能够通过一篇文章让大家读懂 TLS Poison 攻击。但是,仅仅是网络协议便涉及到很多内容,仅靠本文是不可能完全读懂的,本文的内容也并非完全正确,所以也希望大家抱着怀疑的态度合理对文章提出质疑。

本文主要是对 Black Hat USA 2020 - When TLS Hacks You 议题的整理与复盘,该攻击是一种利用 TLS 协议特性结合客户端实现缺陷达到攻击内网应用的攻击方式,可以达到任意写入 Memcached 等内网服务的攻击效果,进而配合其他漏洞造成 RCE 等危害。

这是去年在 black hat USA 被提出的一项攻击方式,但作者在提出这个攻击方式后,由于种种因素,他放出来的 demo 并不能直接使用,所以我在对该项的研究复现中整理了很多攻击细节,以及一些可以拓展的地方,还有一些关于计算机科学知识的探索。

本文主要分成三部分,第一部分主要简单讲述一些必要的背景知识,第二部分会详细记录三种攻击方式的实现步骤,第三部分会讲述一些关于在复现过程中的一些思考以及相关探索的内容。如果还有后续的进展,我也会同步到自己的个人博客上,欢迎关注,以及前来交流:https://blog.zeddyu.info/

如果对该篇文章有任何疑问或质疑,欢迎来信:

echo emVkZHl1Lmx1QGdtYWlsLmNvbQ==|base64 -d

欢迎对协议安全等内容感兴趣的同学一起交流学习!

PS: 如无特殊说明,整个实验背景均基于 Ubuntu 20.04 LTS ,curl 7.68.0 build with OpenSSL/1.1.1f  ,后文提到的 IPv6 均指的是  IPv4-mapped IPv6 addresses 这类地址

由于内容较多,原文将会被分成四节文章在该平台上进行发布,本篇为该文章的第三节。

点击查看往期文章:
    一篇文章带你读懂 TLS Poison 攻击(一)
    一篇文章带你读懂 TLS Poison 攻击(二)

NO.2 TLS Poison

上一篇文章详细展开讲述了TLS Poison 攻击,今天让我们来继续讲述这一攻击方式。

The Optimization Method OF DNS Rebinding

就像我们前文所提到的,这个攻击主要取决于两个点,一个是 TLS Session Resumption ,另一个就是 DNS Rebinding 。一个好的 DNS Rebinding 可以起到事半功倍的效果。

我询问了一些 CTFer ,也查证了一些 DNS Rebinding 的工具,诸如 rbndr / ceye 等比较常用的工具,一般统一做法都是每次返回一个 TTL 较小的 A 记录,只不过每次返回的记录不同,大部分都是在用户指定的 A 记录当中随机概率返回一个。这样如果使用这些 DNS Rebinding 工具在这里就不是一个非常好的选择。

随后,@zhaojin 在 基于 A 和 AAAA 记录的一种新 DNS Rebinding 姿势–从西湖论剑2020 Web HelloDiscuzQ 题对 Blackhat 上的议题做升华 提到新的方法,似乎可以使用一个域名同时分配一个 A 记录跟一个 AAAA 记录,因为 curl 会优先使用 AAAA 记录,而当 AAAA 记录的 IPv6 无法建立连接时,会尝试跟 A 记录的 IPv4 进行建立连接。我觉得是个很有趣的想法,整个思路大致如下:

· 第一次让 curl 去访问恶意的 HTTPS 服务器,拿到一个恶意的 SessionID

· 然后使恶意的 HTTPS 服务器无法接收新的连接

· 这时恶意的 HTTPS 给出第一次返回的结果,使其进行同域名跳转

· 跳转时会尝试进行新连接,发现恶意的 HTTPS 服务器无法连接。

· 则会尝试连接这个域名下的其他记录所指向的地址,并带上 SessionID

在 CURL 中,对于一个域名,如果同时具有 A 记录和 AAAA 记录,那么 CURL 会去优先请求 AAAA 或者 A 记录所指向的地址,如果这些地址无法连接,则会尝试连接同时得到的 A 记录或者 AAAA 记录。

在某些情况下,会出现:

AAAA 记录地址不通,会连接到 A 记录地址上。

A记录地址不通,会连接到 AAAA 记录地址上。

但是比较遗憾的是,如果对于一个域名进行这样的设置,AAAA 记录指向 TLS VPS 的 IPv6 地址上,A 记录指向 127.0.0.1 地址,实际测试 当中, curl 总是优先 127.0.0.1 ,并且没有随机的做法;如果对于一个域名进行这样的设置,AAAA 记录指向 ::ffff:127.0.0.1 或者 ::1 地址上,A 记录指向 TLS VPS 的 IPv4 地址上,虽然似乎可以做到 curl 因优先 AAAA 记录与 TLS VPS 建立连接获得恶意 Session ID ,但是实际测试默认 memcached 配置,无法通过这两个(::ffff:127.0.0.1 或者 ::1)地址进行写入 memcached 。

虽然有些遗憾无法复现 @zhaojin 所说的这个方法,但是我觉得是个很有趣的想法,以及 @Ivan Komarov 提到 DNS 对于一个域名可以返回双 A 记录,也能有类似的效果,所以我们可以这样进行尝试:

· 首先,默认配置下, 我们也可以通过 0.0.0.0:11211 这个地址与 memcached 通信

· 对于返回的双 A 记录,一个配置为 TLS VPS IP ,另一个为 0.0.0.0 ,curl 每次都会优先使用 TLS VPS IP ,如果不能通信才会接着使用 0.0.0.0:11211

那根据已知信息,那么与上文的做法类似,我们是不是也可以让 curl 第一次建立链接,拿到我们分配的 payload 后,断开连接,让其第二次连接不通而去选择另外一个 IP 呢?

事实说明,我们也确实可以这么做。基于 @Ivan Komarov 提供的 DNS Server 以及 @zhaojin 使用的 proxy.py ,我们可以拉取我整理的仓库 https://github.com/ZeddYu/TLS-poison 进行实验。

这里 DNS VPS 的 setup 我们需要使用 client-hello-poisoning/new-custom-dns/alternate-dns.py 进行我们域名的解析:

python3 alternate-dns.py tls.example.com --ip x.x.x.x --mode static_zero

x.x.x.x 为你 TLS Server IP ,mode 有两种,rebinding模式则为普通的重绑定解析模式,static_zero则是我们这次测试的双 A 记录。

TLS VPS 的 setup 还是与之前一样,只不过这次我们需要把 TLS Server 的端口绑定在 11210 上,使用 proxy.py 将 11211 的流量转发到 TLS Server 上,而且该转发只转发一次,所以可以造成 curl 第二次连接失败,也就能让其切换到另一个 IP 进行连接了。

target/debug/custom-tls -p 11210 --verbose --certs /root/tls/fullchain.pem --key /root/tls/privkey.pem http

Ok. Let's have a try.

可以看到这里 curl 不需要再经过多次重定向,只需要一次重定向就可以稳定进行 SSRF ,也不再需要依靠 DNS Rebinding 的稳定性了。

Use The Optimization Method To Deal With TLS 1.2 Session Ticket

尽管我们可以使用 TLS 1.3 PSK 进行 Session Resumption ,但是根据 https://caniuse.com/?search=tls%201.3 的数据显示,目前 TLS 1.3 全球覆盖率为 91.12% ,而 TLS 1.2 的覆盖率为 98.4% ,并且目前淘宝、百度等知名主站均还没有完全支持 TLS 1.3 ,所以有些时候还是需要我们使用TLS 1.2 ,而作者又偷了一点懒,没有实现任何 TLS 1.2 相关的利用方式,而 @zhaojin 使用的 tlslite-ng 目前还并未支持 TLS 1.2 当中的 Session Ticket ,而又正好作者修改的 rustls 实现的功能比较完善,所以我只能硬头皮刚了一波 rust ,为原作者的 TLSServer 增加了基于 TLS 1.2 Session Ticket 的修改功能。

依旧使用我修改的仓库 https://github.com/ZeddYu/TLS-poison ,对于 DNS Server setup 还是使用优化的双 A 记录的方法,但是对于 TLS Server setup 我们需要改变一下:

target/debug/custom-tls -p 11210 --verbose --certs /root/tls/fullchain.pem --key /root/tls/privkey.pem --tickets --protover 1.2 http

使用参数--tickets,允许 TLS Server 使用 Session Tickets 进行 Session Resumption ;使用--protover 1.2参数,只允许 TLS Server 最高使用 TLS 1.2 版本。并在 redis 设置 ticket_payload ,这个与之前设置的 payload 值一样,是用来对 memcached 进行利用的,我们这里就区别于之前随便设置一下就可以了,例如set ticket_payload "\r\nset foo 0 0 41\nThis is a TLS 1.2 session ticket example.\r\n"

对于 Client ,我们不能再使用 curl ,因为其并没有实现 Ticket Session 插件...所以我选用了老版本 Chrome 70.0.3538.77 for Ubuntu 进行学习。(提醒这里不要用 Firefox ,因为作者在 PDF 中表示过 Firefox 没有这个“特性”)

依旧在 TLS Server 上使用 proxy.py ,接着确定准备好就可以在本地打开 chrome 访问自己 TLS Server 的地址:

因为 Chrome 的一个特殊机制,使用 Chrome 测试我们并不能像 curl 那样一次就能成功,这里我们最好使把 Chrome 的 Keep local data only until you quit your browser 选项打开以及设置每次打开 Chrome 时就打开我们的 TLS Server 地址,这样实验就比较方便了,多试几次我们就可以看到上图这个效果。

Use The Optimization Method To Deal With TLS 1.2 Session ID

那要是遇到只能用 curl/libcurl ,而且 TLS 1.3 又不支持的情况,那就只能通过 TLS 1.2 Session ID 来实现我们注入 payload 实现 SSRF 了,我们能做的就是使用双 A 记录的方法来提高攻击稳定性。

由于作者写的不是很好,并没有对 TLS 1.2 进行适配,而我也并不熟悉 rust ,只能勉强找到作者代码库的问题,大概就是由于作者在 main.rs#730 循环中每次都使用了新的 config ,如下代码所示:

loop {  poll.poll(&mut events, None)  .unwrap();
config = make_config(&args, session_id_generator.clone()); tlsserv.tls_config = config;
for event in events.iter() { match event.token() { LISTENER => { if !tlsserv.accept(&mut poll) { break; } } _ => tlsserv.conn_event(&mut poll, &event) } }}

导致了在 rustls/src/server/hs.rs#718 中每次根据client_hello.session_id.get_encoding()都取不到存储的 Session ID

// Perhaps resume?  If we received a ticket, the sessionid// does not correspond to a real session.if !client_hello.session_id.is_empty() && !ticket_received {  let maybe_resume = sess.config.session_storage  .get(&client_hello.session_id.get_encoding())  .and_then(|x| persist::ServerSessionValue::read_bytes(&x));
if can_resume(sess, &self.handshake, &maybe_resume) { return self.start_resumption(sess, client_hello, sni.as_ref(), &client_hello.session_id, maybe_resume.unwrap()); }}

所以我们只需要把 main.rs#734 以下两行进行注释即可:

  // config = make_config(&args, session_id_generator.clone());  // tlsserv.tls_config = config;

虽然可以 debug 找到问题所在,但是并不能完美地修正这个问题,只能做个临时的处理办法来解决这个问题,而且自己时间精力并不太足够,所以如果有同学有比较好的办法解决这个问题欢迎提 PR 修正这个问题!

然后在 redis 中修改 payload 为 32 字节长度:set payload "\r\nset foo 0 0 13\nI am so poor.\r\n"。好了,那就让我们来试一下吧!

虽然我们只能使用 32 字节的 Session ID ,但是对于 memcahed ,我们可以使用append命令进行追加,例如:set payload "\nappend foo 0 0 11\nSo so poor.\r\n"。并且因为我们注释了那两行,所以对于重新设置了的 payload ,我们需要重新启动一次 TLS Server

好了,以上就是我们关于 TLS Poison 漏洞复现的部分。

Attack Impact

在作者的报告中指出如下的 Client 对 TLS 会话进行了缓存:

作者还给出了在内网中易受攻击的服务:

到目前为止,我们已经讲述完了 TLS Poison 攻击的内容。下一篇的文章中,我会讲述在复现、探索 TLS Poison 攻击遇到的一些问题以及相应的探索,我觉得其中有一些会比攻击本身更值得研究。

RECRUITMENT

招聘启事

安恒雷神众测SRC运营(实习生)
————————
【职责描述】
1.  负责SRC的微博、微信公众号等线上新媒体的运营工作,保持用户活跃度,提高站点访问量;
2.  负责白帽子提交漏洞的漏洞审核、Rank评级、漏洞修复处理等相关沟通工作,促进审核人员与白帽子之间友好协作沟通;
3.  参与策划、组织和落实针对白帽子的线下活动,如沙龙、发布会、技术交流论坛等;
4.  积极参与雷神众测的品牌推广工作,协助技术人员输出优质的技术文章;
5.  积极参与公司媒体、行业内相关媒体及其他市场资源的工作沟通工作。

【任职要求】 
 1.  责任心强,性格活泼,具备良好的人际交往能力;
 2.  对网络安全感兴趣,对行业有基本了解;
 3.  良好的文案写作能力和活动组织协调能力。

简历投递至 

[email protected]

设计师(实习生)

————————

【职位描述】
负责设计公司日常宣传图片、软文等与设计相关工作,负责产品品牌设计。

【职位要求】
1、从事平面设计相关工作1年以上,熟悉印刷工艺;具有敏锐的观察力及审美能力,及优异的创意设计能力;有 VI 设计、广告设计、画册设计等专长;
2、有良好的美术功底,审美能力和创意,色彩感强;

3、精通photoshop/illustrator/coreldrew/等设计制作软件;
4、有品牌传播、产品设计或新媒体视觉工作经历;

【关于岗位的其他信息】
企业名称:杭州安恒信息技术股份有限公司
办公地点:杭州市滨江区安恒大厦19楼
学历要求:本科及以上
工作年限:1年及以上,条件优秀者可放宽

简历投递至 

[email protected]

安全招聘

————————

公司:安恒信息
岗位:Web安全 安全研究员
部门:战略支援部
薪资:13-30K
工作年限:1年+
工作地点:杭州(总部)、广州、成都、上海、北京

工作环境:一座大厦,健身场所,医师,帅哥,美女,高级食堂…

【岗位职责】
1.定期面向部门、全公司技术分享;
2.前沿攻防技术研究、跟踪国内外安全领域的安全动态、漏洞披露并落地沉淀;
3.负责完成部门渗透测试、红蓝对抗业务;
4.负责自动化平台建设
5.负责针对常见WAF产品规则进行测试并落地bypass方案

【岗位要求】
1.至少1年安全领域工作经验;
2.熟悉HTTP协议相关技术
3.拥有大型产品、CMS、厂商漏洞挖掘案例;
4.熟练掌握php、java、asp.net代码审计基础(一种或多种)
5.精通Web Fuzz模糊测试漏洞挖掘技术
6.精通OWASP TOP 10安全漏洞原理并熟悉漏洞利用方法
7.有过独立分析漏洞的经验,熟悉各种Web调试技巧
8.熟悉常见编程语言中的至少一种(Asp.net、Python、php、java)

【加分项】
1.具备良好的英语文档阅读能力;
2.曾参加过技术沙龙担任嘉宾进行技术分享;
3.具有CISSP、CISA、CSSLP、ISO27001、ITIL、PMP、COBIT、Security+、CISP、OSCP等安全相关资质者;
4.具有大型SRC漏洞提交经验、获得年度表彰、大型CTF夺得名次者;
5.开发过安全相关的开源项目;
6.具备良好的人际沟通、协调能力、分析和解决问题的能力者优先;
7.个人技术博客;
8.在优质社区投稿过文章;

岗位:安全红队武器自动化工程师
薪资:13-30K
工作年限:2年+
工作地点:杭州(总部)

【岗位职责】
1.负责红蓝对抗中的武器化落地与研究;
2.平台化建设;
3.安全研究落地。

【岗位要求】
1.熟练使用Python、java、c/c++等至少一门语言作为主要开发语言;
2.熟练使用Django、flask 等常用web开发框架、以及熟练使用mysql、mongoDB、redis等数据存储方案;
3:熟悉域安全以及内网横向渗透、常见web等漏洞原理;
4.对安全技术有浓厚的兴趣及热情,有主观研究和学习的动力;
5.具备正向价值观、良好的团队协作能力和较强的问题解决能力,善于沟通、乐于分享。

【加分项】
1.有高并发tcp服务、分布式等相关经验者优先;
2.在github上有开源安全产品优先;
3:有过安全开发经验、独自分析过相关开源安全工具、以及参与开发过相关后渗透框架等优先;
4.在freebuf、安全客、先知等安全平台分享过相关技术文章优先;
5.具备良好的英语文档阅读能力。

简历投递至

[email protected]

岗位:红队武器化Golang开发工程师

薪资:13-30K
工作年限:2年+
工作地点:杭州(总部)

【岗位职责】
1.负责红蓝对抗中的武器化落地与研究;
2.平台化建设;
3.安全研究落地。

【岗位要求】
1.掌握C/C++/Java/Go/Python/JavaScript等至少一门语言作为主要开发语言;
2.熟练使用Gin、Beego、Echo等常用web开发框架、熟悉MySQL、Redis、MongoDB等主流数据库结构的设计,有独立部署调优经验;
3.了解docker,能进行简单的项目部署;
3.熟悉常见web漏洞原理,并能写出对应的利用工具;
4.熟悉TCP/IP协议的基本运作原理;
5.对安全技术与开发技术有浓厚的兴趣及热情,有主观研究和学习的动力,具备正向价值观、良好的团队协作能力和较强的问题解决能力,善于沟通、乐于分享。

【加分项】
1.有高并发tcp服务、分布式、消息队列等相关经验者优先;
2.在github上有开源安全产品优先;
3:有过安全开发经验、独自分析过相关开源安全工具、以及参与开发过相关后渗透框架等优先;
4.在freebuf、安全客、先知等安全平台分享过相关技术文章优先;
5.具备良好的英语文档阅读能力。

简历投递至

[email protected]

END

长按识别二维码关注我们


文章来源: http://mp.weixin.qq.com/s?__biz=MzAwMDQwNTE5MA==&mid=2650246421&idx=1&sn=c11389e522f69bce74c00c09e02aea12&chksm=82ea56bcb59ddfaa8028dc15eef274f53421f515fdc463f6abae3c2790ec73eba4bc5dc5bb1d#rd
如有侵权请联系:admin#unsafe.sh