使用 Socks5 来劫持 HTTPS(TCP-TLS) 之旅
2023-4-27 18:11:42 Author: Yak Project(查看原文) 阅读量:18 收藏

|MITM 劫持的过程中,HTTP 协议并不是唯一选择。
实际在 MITM 使用过程中,BurpSuite 和 Yakit 提供的交互式劫持工具只能劫持 HTTP 代理的 TLS 流量;但是这样是不够的,有时候我们并不能确保 HTTP 代理一定生效,或者说特定的后端只支持 TCP 传输层代理(Socks5)代理,那么交互式劫持将失效,也没有办法获取到基于 Socks5 代理的 HTTP 通信。
因此我们做了一些简单的验证,去实现了基于 Socks5 协议的代理劫持,同时我们以一种更加简单高效的方式让 Socks5 的代理适配了传统的普通 MITM 交互式劫持中。
TLS 劫持的本质:证书信任链的崩坏
|内容引用自笔者在他处的 PPT 中的节选内容。
因为信任链是树形结构的,可以“推导”信任关系,那么被信任的 CA 签发的证书,也会被信任。
那么理所当然,我们得出结论:从原理上来讲,TLS 的劫持和 HTTP 代理甚至任何代理都没有半毛钱关系;从技术上来讲,HTTP 代理在其中的作用仅仅是提供了一个连接介质。
MITM-TLS 劫持时序:

回顾基于 HTTP 代理的 MITM 劫持

如果要实现一个正常的 HTTP 代理,我们需要处理两种情况:
1. 通过 Proxy-Connection 等直接 HTTP 头控制的非 TLS 劫持
2. 通过 CONNECT 控制的通用 HTTP 代理。
在第一种情况下,代理只需要去掉 Proxy 头,解析出对应的 Host 地址,发起明文 HTTP 链接即可。我们就不做过多解释;在第二种情况下,CONNECT 成功发起后,TCP 连接将被建立,中间人需要同时进行客户端的握手,同时尽可能还原信息去和服务端进行握手。实际上,从 TCP 连接建立开始就和 HTTP 代理没有任何关系了。实际上在 Socks5 代理中,从 TCP 连接开始建立之前和 HTTP 代理是不一样的,但是从 TCP 连接开始建立之后,如果我们要进行劫持,那么关于劫持的技术实现和现有 TLS 劫持技术是几乎一致的。

Socks5 可进行中间人攻击的代理实现

我们要实现这个技术,一般的 Socks5 服务器一般来说也是不好使的,所以我们需要花几分钟来学习一下一个简单好用的 Socks5 协议应该怎么实现。
Socks5 一般有三种模式:
1. TCP Forward: 最常见的模式,正向代理,转发客户端的所有连接
2. TCP Port Forward: 反向模式,映射远端一个端口,然后让客户端自行连接
3. UDP Forwarded:UDP 转发模式
一般的 Socks5 服务器和客户端都只支持第一种协议,因此我们以第一种协议为例,拆解一下通信过程,我们把通信过程分为:
1. 握手

2. 连接

Socks5 握手

|代码仅供参考。

Socks5 转发
当我们实现握手之后,我们发现拿到了 TCP 连接,那么正常来说,我们此时就有了决策点:
1. 如果我们正常无脑转发 TCP 到目标 TCP 连接中,那我们的 Socks5 就是一个 “正义” 的 Socks5 代理
2. 当我们劫持过程中,尝试预读(Peek)TLS Handshake ClientHello 的时候,我们就可以知道这个连接到底是不是 TLS 握手,要不要伪装了。具体的代码如下

Socks5 邪恶版本实现之后,我们就可以顺利劫持到 TLS 的原始内容了。

SNI 仍然不受任何影响

SNI 在 TLS Handshake ClientHello 中作为 TLS Extension 信息,他的存储结构其实并不是一个 string,而是一个 []string,我们仔细回想一下,劫持后的 TLS 握手发生的时间肯定至少应该在上一个 SNI 的解析出来之后,如果没有解析出来,那么应该读取 Socks5 连接的时候的目标 Addr。

工程问题:如何使用现有的基础设施?

经过上面的 proof of concept,我们顺利实现了 Socks5 代理的 TLS 劫持,但是我们发现他劫持的实际上并不是真正的 HTTP 请求,而是更加通用的 TCP 请求,这下遇到了问题了:“MITM 的基础设施一般都是用来处理 HTTP 请求的,那么接下来难道要完全重写一遍基础设施吗?”,我们发现,让这个小技术更好的造福用户和他的技术实现还是有很大差距的,那么真的束手无策了吗?

多协议端口复用(Socks5 与 HTTP 代理共存)
大家很多时候仍然记得我们在 Yakit 中的 “反连” 中实现了一个端口同时 Serve 多种不同的应用协议的功能;很自然地,我们知道 Socks5 的第一个字符 \x05 和 \x16(TLS) 并不冲突,因此 Socks5 其实也可和 HTTP 协议并存,因此 ClashX 等工具的本地代理你可以设置为 Socks5 代理,也可以设置为 HTTP 代理。
很自然的,我们为了减轻用户切换代理的负担,第一件事儿应该是让 Socks5 和 HTTP 共存。
1. 通过我们的 TCP Connection Peek 技术很容易实现这个功能
2. Facades 已经提供了长时间健康运行的证明,这个技术并不会额外增加负担
因为我们很快就解决了这个小问题

以退为进:巧妙利用二级代理

我们使用 Socks5 劫持 TLS 本质上是劫持了 TCP(HTTP 的传输层),并不是劫持了 HTTP,按理说并不能兼容 HTTP 代理,但是如果我们主动放弃除 HTTP 之外的其他协议,那么是否可以服用基础设施呢?既然决定自我退化,那么实际上这个 “劫持” 问题可以降级为:
“如果我能给 Socks5 转发的 TCP 连接增加一个二级代理,这个二级代理是有劫持功能的,那么是不是说也算是成功劫持?”
结合多协议复用技术,我们实现了如下有趣的技术内容
1. 我们预读了 HTTP 代理中的 Socks5 代理请求,手动进行了 Socks5 握手
2. 如果握手成功,我们将会把 TCP 连接当成 Socks5 代理连接来使用,同时让 Socks5 服务器启动新连接的时候设置同端口的 HTTP 代理;
3. HTTP 协议被 HTTP 代理直接劫持!完美兼容 Socks5 代理协议

最终实现

细心的同学在Yakit 的使用中发现:曾几何时MITM的提示词已经变成 http://127.0.0.1:8083 或 socks5://127.0.0.1:8083。

既然最近有对 MITM 的调整,那么也顺便来说一下 MITM 的其他变化。

国密 GM-TLS 支持
虽然大家在 yak 核心引擎中还能看到 martian 的影子,但是需要提醒的是,这个 martian 已经不是大家认识的 google/martian 了,我们对他进行了大量 Bug 修复,上下文控制以及 Socks5 支持,认证代理支持的修改,甚至我们还在他的基础上支持了国密算法的劫持套件,以助力对国内一些特殊站点的测试。
同时,支持 GMTLS 我们还支持多种选项
1. 国密 TLS 优先:当这个选项开启后,进行 TLS 劫持后连接时将优先进行 GMTLS 连接;
2. 仅国密 TLS:当这个选项开启后,将不再支持普通 TLS 的劫持功能。
当然,普通模式下,TLS 如果连接不成功,会自动进行 GMTLS 的备份连接,前提是需要开启 “国密劫持” 选项。

代理认证
当然,我们现在 MITM 劫持是可以开启认证的,用户可以输入用户名和密码以限制自己的 TLS 不会被其他人连接。
当我们在同一端口上进行了 Socks5 和 HTTP 代理的时候,将会同时对 Socks5 和 HTTP 代理启用认证。大家尽可放心使用。
虽然我们实现它的技术难度并不高,但是这却是一个非常有趣的技术点,在大家配置和使用的过程中已经发挥了巨大的作用。如法炮制,大家可以用同样的技术和思路为 BurpSuite 实现一个 Socks5 代理。

不断叠加与不断突破的版本更新

Yaklang 1.2.0-sp5
1. 增加了插件拉取错误的错误提示
2. 优化了更新插件商店的落成
3. 增加了 []any 类型的转换
4. 修复了 MITM 插件调试过程中,JS 被过滤的情况

5. 新增了 Web Fuzzer 的诸多配置信

Yakit 1.2.0-sp1
1、WebFuzzer响应包增加DNS耗时、代理、URL等字段
2、插件商店和CVE差量更新可设置代理
3、新增截屏功能
4、WebFuzzer关闭一级tab增加二次确认提示
5、修复插件调试时Console赋值问题
6、WebFuzzer增加设置禁用系统代理和DNS设置

7、MITM规则增加设置URI,丢弃包,重发包设置;优化编写规则交互


文章来源: http://mp.weixin.qq.com/s?__biz=Mzk0MTM4NzIxMQ==&mid=2247496277&idx=1&sn=9308b568aa04d82687bbe6823ebe5a8e&chksm=c2d18ef1f5a607e7c7fad83a01526c57fb036bf4e4fb06ecb14f99ac2997b664e55ecee3e5eb#rd
如有侵权请联系:admin#unsafe.sh