本文共计4719字,阅读时间预计10分钟

HTTPS 劫持其实是一个老生常谈的话题,从上古时代的 HTTPS 降级(maybe sslstrip),到现在很稳定的安全工具burpsuitexray等,以及一些常见的网络调试工具 fiddler、charles、surge,很多都直接或者间接利用了 HTTPS 的 MITM 攻击。

在很多朋友尝试 HTTPS 中间人的时候,其实都有过这样的想法:“我挂在路由器上,让我所有的的 HTTPS 流量全都变成明文!”。但是往往受限于性能问题以及部署问题,导致了很多人“只是想想”。
与此同时,不管是 HTTP 还是 HTTPS 的劫持(点题了qwq),除了解决安全工程问题,其实还有更多别的用途:比如你连入了一个 WIFI,需要 Web 端认证,这个时候你的路由器本质就是在“劫持”你到认证页面,当你认证成功,路由器防火墙策略把你的流量放行,并停止劫持。
除了网络调试与安全测试之外,其实还有更多别的用途,比如劫持网络,把某个系统的升级软件、脚本替换成你自己的恶意软件下载地址来 Getshell。

毕竟劫持不仅可以劫持用户端,服务端返回数据也可以被劫持:操纵用户手脚还是蒙住用户的眼睛都可以。

核心原理:不安全的CA导致信任链崩坏

我们上一节提到的所有的劫持应用等,其实都有一个基础前提,就是“不安全的 CA 被信任了”;
如果没有进行这一部分基础知识的积累,很多人不会把 CA 的安全性、重要性想的太高,毕竟你直接信任了一个 CA,也并不会导致说马上被 getshell 掉,对吗?甚至很多安全从业人员对 CA 的态度也很暧昧;
之前在长亭科技工作的时候,进行很多校招或者社招面试,我都会比较喜欢问面试者 HTTPS 劫持的核心原理,答上来的人很少:大多数人要不就是上来给我背书,要不就是只知道怎么下载 Burpsuite的证书,怎么添加信任。但是问具体中间人细节实现的时候,大多数人都傻眼了。
简单来说就是:不安全的 CA 可以给任何网站进行签名,TLS 服务端解密需要服务端私钥和服务段证书,然而这个不安全的 CA 可以提供用户暂时信任的服务端私钥和证书,这就好比你信任了一个信用极差的人进入你的家,这个信用极差的人可以在你的家里乱翻乱拿无恶不作。
详细的内容限于篇幅我们不多说了,毕竟这也不是本文重点。
不能进行 HTTPS 劫持的场景
当然,为了防止你的 HTTPS 服务被劫持,你可以使用以下的操作进行加固,来防止劫持。

服务端证书锁定:SSL/TLS pinning

这种场景一般用于移动端 APP 的防劫持,Twitter,Google 系 APP 很多都在使用这项技术,核心原理是把服务端证书或其他凭证内置在客户端,在客户端访问服务端的时候,会验证服务端证书有没有被替换。
由于 SSL/TLS pining 强制验证服务端返回的证书中是否包含目标证书,如果我们可以弄到原本服务端证书,给他返回去是不是也可以绕过?理论上当然可以,但是这样,没有私钥的你也没有办法解密 TLS 流量了。

银弹?证书锁定带来的尴尬问题

如果仅仅只是塞一个证书锁定在客户端,那么客户端过期了的话,怎么办呢?那就只能强制用户更新客户端,这种 breaking 一般是不被允许的。
如果塞一个公钥到客户端,如果证书、公钥被吊销,或者私钥被泄露的话,仍然是需要用户强制更新客户端。
但是我相信任何处于业务快速膨胀期或者研发水平跟不上的 APP 都不会这么操作的,一般有很硬后台,很高安全性要求,有成熟研发体系和 PKI 体系的公司可能才会有这种需求或能力做这件事情。

最高安全等级:x509 双向认证

诸如 WPA2 企业级认证 EAP-TLS 的认证方式,很多系统都将 TLS 的双向认证作为最高标准、最高安全等级的认证方式。
同样的,对于 HTTP 服务,同样也可以签署开启了 X509 双向认证的 TLS 连接。
https://zh.wikipedia.org/wiki/%E5%85%AC%E9%96%8B%E9%87%91%E9%91%B0%E5%9F%BA%E7%A4%8E%E5%BB%BA%E8%A8%AD
日常生活中,很多商业产品都是通过 PKI 体系的证书来控制产品的授权。

高要求:PKI 体系构建和研发过程

当然,如果公司已经具备如下的系统 (PKI 的简单实现 - 截取 Palm SIEM 的部分功能)。
并且研发支持自动化申请签发证书,用户更新证书,APP 更新证书等高成本高规范的流程,PKI 确实可以带了很高的安全保障。

客户端缺陷:SNI 不明确

虽然大多数情况下,HTTPS 可以理解为 TLS + HTTP,但是仍然有一些细节需要注意。
SNI 是什么呢?简单来说,一个 HTTPS 服务器可能存在多个域名(同学们可以回忆一下 Apache 虚拟主机的配置这项功能),当进行 TLS 握手的时候,不同的网站对应的 TLS 服务端配置不一样,如果不携带想要访问哪个域名,那么服务器或中间件确实不知道应该转发到具体的哪个虚拟站点上,直接导致了 TLS 的混乱。
为了解决这个问题,ClientHello 中的 SNI 在 TLSv1.2 开始支持,我们可以设置 Server Name 这个字段,设置为网站域名。
同样的,MITM 也依赖 ServerName,因为 ServerName 可能直接决定了中间人要连接的目标是啥,如果没有 SNI,中间人则没有办法寻找到连接目标,同样的也没有办法对网站进行临时签名了。

疑问:HTTP 的 Host 不是有域名信息吗?为什么不能用?

这个问题答案很简单 HTTPS 中,TLS 是 HTTP 的前置条件,域名拿不到,没有办法进行 TLS 签名,所以只能依赖 ClientHello 中的 ServerName 了。

第二通道:HTTP 之上的加密

做过微信公众号后台或者尝试劫持微信的朋友都可能很容易理解这个问题,HTTP 传输的内容也是经过加密的,可以很轻松让中间人劫持变得没有意义。

小总结

当然防止 HTTPS 劫持的方案不只有这么多,其实会有很多种细节处理方案都可以导致 HTTPS 中间人劫持失效。
讲解中间人劫持的攻防其实是为了大家更深入了解学习,而并不只是总停留在表面操作。

常见方法

mitmproxy是一个好项目,能够很好地帮助大家理解 MITM 原理

https://docs.mitmproxy.org/stable/concepts-howmitmproxyworks/

但是缺陷也比较明显,mitmproxy 基于 Python,在高负载的情况下并不是特别理想,再加上源码保护等需求,一般 mitmproxy 并不是太适合在工程中或者商业产品中使用;但是大家用他来写个 Demo 或者 Poc 或者论文,基本是没啥问题的。

设置代理以劫持 HTTPS

使用 Charles,Fiddler,Burpsuite,xray 等的同学,可能对这再熟悉不过了,启动代理服务器,浏览器配置一个代理就可以抓包进行调试、漏洞测试了。
引用 mitmproxy 原理文档(入口:https://docs.mitmproxy.org/stable/concepts-howmitmproxyworks/)中的图来简单说明我们最常见的 HTTPS 劫持的方案实现:

1.先通过一个简单的 HTTP Connect 请求来连接代理服务器;

2.代理服务器返回 200,表明 Connect 管道建立完毕;

3.Client 开始进行 TLS 连接,中间人通过 SNI 来获知需要连接的目标是谁;

4.中间人连接真正的服务器;

5.中间人开始根据 SNI 和 CA 自动签发假的服务端证书,并返回给用户,并进行握手;

6.握手成功,客户端开始发送 HTTP 请求;

7.中间人开始做用户到真正服务器的流量互相转发(可劫持)。

遵循协议参考,基础协议

HTTP Proxy. 
https://www.ietf.org/rfc/rfc2068.txt 
Subject Key Identifier support for end entity certificate. 
https://www.ietf.org/rfc/rfc3280.txt (section 4.2.1.2)

核心实现代码与关键实现

整体流程实现

大家最关心的自动签发证书功能在哪呢?

在 Golang 中,为服务器生成 tls.Config 就可以升级 TLS

总结

针对这种最常见应用最广的劫持方案,我们到此介绍就结束了,如果这部分代码大家有所熟悉,那么 martian 这个库用起来会更好用,当然这件事情本来就不是特别困难;同样的,你可以根据 martian 开发一下,甚至写一个你自己的 xray 都是可以的。

透明代理劫持 HTTPS

其实我写这篇文章,主要是打算介绍这种劫持方案,何谓透明劫持?区别于依赖 HTTP Proxy 协议/功能的代理劫持,自然就是不需要设置代理,由路由器(当然也不止路由器),把流量设置到目标服务器上,目标服务器来进行 HTTPS 劫持。
优势就是不需要客户端配置,当然劣势也明显,需要路由设置(传输层劫持)。
1.客户端连接服务器;
2.路由器重定向客户端连接到中间人;
3.中间人通过 SNI 获知需要连接哪个具体的目标网站;
4.替换证书... 成功劫持 (同上,不做过多叙述了);
很简单,我们可以在路由器上通过 iptables 来重定向客户端连接。

如何实现?

其实关键点和上述放的代码基本类似,为了防止滥用我可能并不会直接放出可用代码,只在关键点做伪代码或代码节选,供大家参考和突破难点。
当前实现的版本比 mitmproxy 性能和可扩展性高很多,由于 Go 本身的性能相对还行,体验还是相对良好。

支持多协议 HTTPS/HTTP

关键点

我为什么不直接抄 Martian 的代码?

如果大家有使用过 Martian 这个库的话,可能会对这些代码很熟悉
我们在 martian 中需要通过 AddRequestModifier 对请求进行 Hook
实际在使用的过程中,写入网络的对象,多是经过 Golang http 标准库进行处理的,在某些时候,可能并不能保证和原本传输的内容一摸一样。需要 Fix/Patch 之类的操作。
  • 镜像场景
在关键的地方,我们使用 TeeReader 读出镜像流量直接对可用的 Bytes 进行转发,能最大程度保证不破坏内容同时也保证性能,由于镜像数据其实不关劫持流程什么关系,我们可以随意启动别的 Goroutine 来执行。
  • 劫持场景
如果劫持方式被设置了,我们本身的需求在于修改数据包的内容,那么我个人倾向于直接交由一个完整的 Bytes 给上游,返回一个修改后的 Bytes,而不做过多处理,虽然这一个步骤是同步的,上游可以封装他自己的任何对象,最后序列化的结果也是上游负责,最大程度保证尊重开发者意愿。

透明劫持的其他玩法(CA被信任)

不管是代理劫持 HTTPS 也好还是透明劫持 HTTPS,至少我们可以用它做很多事情,当然这些事情不一定是涉及到安全领域。
既然是中间人,我们就既可以扮演客户端也可以扮演服务器。

高效可用路由器解密 HTTPS 的方案

前段时间我们做了一件很有趣的事,在路由器上配置了一个 hostapd 然后开启了 https 透明劫持,通过 iptables 来控制想要劫持的具体网站(当然也可以劫持全部 https、http),确实爽了一把,后来我想,大概抓出来的流量我就存下来,抽空挨着测试,也并不需要 xray 这种实时进行安全测试。
当然除了进行安全测试之外,想要分析流量内容,分析敏感数据是否外传,审计流量也是完全可以做到的。我相信很多人或者公司,或多或少对自己或者自己员工都有一点好奇心对吧?
当然,想要实现这些东西不仅仅是劫持就完了,就算我把劫持框架开源了,仍然需要大量的基础设施需要完善。

IoT 设备连接 Wifi 劫持导致的 getshell

很早些年间,在进汽车安全测试的时候,车机也算是一种 IoT 设备吧,连接上 Wifi 之后,选择车机的自动升级功能或者下载 APP 功能的时候,我们可以轻松劫持掉下载链接,把下载链接替换成 msf 生成的安卓马儿,直接 Getshell。
当然,我们可以如法炮制很多种 Getshell 的方案,说着转眼就盯上了智能咖啡机.....
其实这种情形非常非常非常非常常见,大部分 IoT 厂商对中间人劫持是敏感的,但是他们选择的大多数方案是使用自签名证书,并且不让你能设置代理,如果自己有 PKI 体系并且开启了 X509 双向认证,那可能风险会大大降低。但是往往他们并不会这么做,虽然不让客户端设置代理,但是路由器可以设置代理啊,这就导致了透明代理成了非常有效的劫持手段。
而且由于上述原因最尴尬的情况很可能发生:大多数时候 IoT 设备都不会验证证书是否合理

所以 IoT 设备其实蛮尴尬的。

配合 DNS 劫持或者 ARP 劫持,内网直接透明劫HTTPS

这个当然也是老树开新花,很久很久以前,内网劫持 HTTPS 采用的方案是 ARP 劫持 + DNS 劫持 + HTTPS 降级。但是都 2020 年了,我们自然有了各种对抗,HSTS 和服务器的规范化配置,导致 HTTPS 降级越来越少,ssltrip 慢慢退出了历史舞台,但是好在我们也似乎不需要再使用 ssltrip,透明劫持可以很容易做到。
当然使用这种手段一般是我们无法控制路由器了。

小总结

其实玩法太多了,受限于文章篇幅和主题,我也不打算过多讲细节了
1.免代理低成本的被动扫描;
2.某些 APP 监控与舆情审计。

.....

安全启示

不要信任不认识的 CA,因为毕竟很多人对“不安全的 CA”认识也一直停留在嘴上和书本上。

对于个人

很多人有一些疑问,CA 信任这么重要,我信任了公司的根证书,那是不是意味着,我的流量只要想劫持,是一定可以劫持的?
这个答案是肯定的,认真看完本文之后你会发现这其实很危险,至少技术上是完全可行的,只是我的代码并没有放出来而已,同样大家都可以自己写一个这样的服务器出来。

对于开发者、公司、厂商

1.有能力做 PKI 体系一定要去实现;
2.防劫持不仅防的是数据泄露问题,也会一定程度上防止被 getshell 或者 rce;
3.安全非小事,开发运维需谨慎;
4.技术无罪,请用在正途。

======= 福福福福利!!=======

免费送xray高级版啦!

xray最近在评选网络安全2020金帽子年度评选,为了进一步宣传友好的免费xray社区,我们准备抽出十位可爱的白帽子获得xray高级版!希望各位朋友投出宝贵的一票啦!

我们诚邀您助力:优秀安全实验室「xray」和优秀安全产品「牧云」喔qwq





发布     👍 0 举报 写留言 🖊   
✋热门推荐
  • #成都消防[超话]#因为逐光而行,他们的背影“橙”为风景![羞嗒嗒][羞嗒嗒][羞嗒嗒]《关于我等得花都谢了的告白终于到了这件事》(买的是磨铁家哒)特别特别是看
  • 和姥姥看了两场辽宁vs广东的半决赛 今晚喊的嗓子都哑了 真的太激动了 直接被圈粉⭕的死死的 以后辽宁比赛我必定不错过 看到朋友圈里都是刷辽宁牛逼我真的太太太想流
  • 慈善不应该是富人, 良心发现时的施舍和恩赐, 而应该是每个人 从内心深处发出的对他人的同情与关爱。 慈善不应该是富人,良心发现时的施舍和恩赐, 而应该是每个人
  • 4、又是成长的一年,不一样的一年,新的身份,新的角色,愿一切都好!祝自己生日快乐!5、希望我以后的人生平安喜乐,得偿所愿。致自己:生日快乐!8、成长不期而遇,生
  • 1. 多年英语、小语种培训经验,值得信赖;2. 教育部门正规审批备案,诚信可查,真实可靠;3. 开设:雅思、托福、成人英语、四六级、日语、韩语、法语、德语、俄
  • #饭丰万理江[超话]#oggi杂志 4/15【今日のコーデ】\きれいめシンプル派の「今っぽい」おしゃれ/【ブルゾン×ニット×スカート】変わらないようでいて、進化
  • ”来有来的目的 走有走的意义一直都清楚“阶段性的陪伴” 所以也应该一直有离别的觉悟一个人挺好 无非就是自由中带点孤独终于知道什么是永远了 失去了就是永远我要熬
  • 最近有些居家办公或上网课的同学们反映 有跟猫猫狗狗 花花草草说话的并发症 我很慎重地安慰你们 这很正常 如果哪天你们发现它们开口跟你说话了 告诉我
  • 於是佢帶我去了個市集,一手扯住那個肥婆,問着把車賣了哪裡,問到了,話賣了去【大忍小忍村】那頭個汽車維修站,然後佢就立刻飛一樣嘅往那两村跑去,我就氣呼呼,扯住個肥
  • 准提菩萨有十八只手,更具有三目,其法力威猛,是一位感应甚强,对崇敬者至为关怀的大菩萨,她是莲华部诸尊之母,七俱胝佛母,七百亿诸佛菩萨之母。准提菩萨有十八只手,更
  • #小D爱读书# 【野草】——鲁迅◆ 题辞>> 当我沉默着的时候,我觉得充实;我将开口,同时感到空虚。◆ 复仇(其二)>> 钉杀了“人之子
  • 如此数日夜,忽有人于井口召坤姓名,谓坤曰:“我狐也,感君活我子孙不少,故来教君。他又找到了僧人,僧人见他还活着,不禁大吃一惊,再去看那井时,却仍完好如初,便对姚
  • 正常量的话一天一包就够了,最多不能超过两包这里面有车前籽壳&天然膳食纤维,能帮助我们时刻保持健康状态,还能为肠道消化排毒呢~我感觉我的皮肤都慢慢变好了怪
  • 我第一反应是他自己带不了两个,假期人多车多,万一出点事可怎么好呢。[单身狗]#生活的模样# 我的加百列大天使开花了像莲花一样,确实挺漂亮昨天的白班加上22:00
  • #上海##上海疫情# 上海能在这么短时间内迅速爆发,确实怪异图一美国临时对上海开放,非公民啥意思?美国电影里的剧情发生在现实:生物实验室制造病毒,全世界投毒,美
  •   会议指出,各位受聘政府法律顾问是政府的重要法律智库,大家要充分认识到自身在推进依法行政、法治政府建设中的重要作用,要以责无旁贷的使命感落实好法律顾问的各项
  • 】夕阳如血照映在赵敏脸庞上,是映衬,是烘托,也是一种比拟,赵敏的容貌可与太阳相比,夕阳虽不比朝阳热烈,但别有一番性感的风情,是黑夜来临前最后的光辉,亦是暗夜前的
  • 2月1日下午,吉林市龙潭区开展的第二届“乌拉满族过大年”系列活动启动仪式在龙潭区乌拉街满族镇韩屯村举行。2月1日下午,吉林市龙潭区开展的第二届“乌拉满族过大年”
  • 郭德纲和王惠结婚后,一直很恩爱,多年来,二人患难与共,感情更深,这次凌晨发文的细节就展现了有多用心,平常也透露着爱得多深。郭德纲和王惠结婚后,一直很恩爱,多年来
  • ”元贤《鼓山志序》载:“至万历戊申,郡绅谢在杭同布农徐兴公再为纂辑,则纲举目张,井然有纪,旁搜远揽,纤悉靡遗,大有功于是山者也。鼓山刻本很多都是作者亲自主持刊刻