注目

研究・分析 / RESEARCH / STORED XSS

Telegram DesktopのチャットHTMLエクスポートに保存型XSS — ボットが仕込んだ不可視のスクリプトが、書き出したHTMLファイルを開いた瞬間にメッセージを外部送信(修正版はv7.0.1)

セキュリティ研究グループのExPatchは2026年9月12日、Telegramのデスクトップ版クライアント「Telegram Desktop」のチャットHTMLエクスポート(書き出し)機能に、保存型クロスサイトスクリプティング(XSS)の脆弱性があったと公表した。攻撃者が用意したボットは対象グループへ参加する必要がなく、転送された1通のメッセージをきっかけに、書き出したHTMLファイルの中へ不可視のスクリプトを忍ばせられる。利用者がそのファイルをブラウザーで開くと、ファイルに表示されるメッセージが外部へ送信される。ExPatchによると、この脆弱なコードは約2年4カ月にわたり製品コードに存在し、2026年7月のコミット8457d13aで修正された。ベータ版v6.9.4と安定版v7.0.1以降に修正が含まれる。CVEは採番されていない。

攻撃手法
ソフトウェア

要点

  • セキュリティ研究グループのExPatchは2026年9月12日、Telegramのデスクトップ版クライアントTelegram DesktopのチャットHTMLエクスポート機能に、**保存型クロスサイトスクリプティング(XSS)**の脆弱性があったとする解析結果を公開した。
  • 原因は、チャットをHTMLへ書き出す処理のうち、インラインキーボード(メッセージに付くボタン)の文字列だけがHTMLエスケープされずに出力されていたことにある。ボタンの文字列に <script> タグを入れておくと、書き出したHTMLファイルではスクリプトとして実行される。
  • 攻撃に使うボットは対象グループへ参加する必要がない。URL型のボタンを含むメッセージは転送しても保持されるため、誰かが1回転送すれば標的に届く。ペイロードは履歴に残り、参加者がチャットを書き出してファイルを開いた時に動作する
  • 修正はコミット8457d13aで行われ、ベータ版v6.9.4(2026年7月3日公開)と安定版v7.0.1(同7月14日公開)以降に含まれる。ExPatchによると、修正前に作成したエクスポートファイルはアプリを更新しても危険なままで、再エクスポートかJavaScriptを無効にしての閲覧が必要になる。

ExPatchが公表した内容

セキュリティ研究グループのExPatch(脆弱性研究チーム)は2026年9月12日、Telegram DesktopのHTMLエクスポート機能に保存型XSSの脆弱性があったとする解析結果「The Ghost in the Chat: stored XSS in Telegram Desktop HTML export」を公開した。報告したのはDenis Rostilov氏とAleksander Rostilov氏である。両氏は、2026年6月1日にこの問題を発見し、同6月3日にTelegramの窓口([email protected])へ概念実証(PoC)と動画を添えて報告したと説明している。

脆弱性の深刻度は、ExPatchの評価でCVSS v3.1の8.2(High)(CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N)。ExPatchは攻撃ベクトルを「ローカル(AV:L)」と評価した理由も説明している。脆弱なコードはネットワークから直接届くものではなく、利用者が明示的に実行する「チャット履歴のエクスポート」というローカル処理だからだという。ネットワーク経由で届くのはペイロードを含むメッセージであり、その経路自体は問題なく処理されるという整理である。CVEは採番されていない

何が問題だったのか — ボタンの文字列だけエスケープされない

ExPatchによると、原因はTelegram DesktopのHTMLエクスポート処理(Telegram/SourceFiles/export/output/export_output_html.cpp)の1752行目にある。

この処理では、メッセージ本文や送信者名など、HTMLとして解釈されると困る文字列を出力する前に、HTMLで意味を持つ文字(<>&"')を実体参照へ置き換える関数 SerializeString() を通している。ところがインラインキーボードのボタン文字列には、この関数が適用されていなかった。その結果、ボタンの文字列に含まれるHTMLタグが、書き出したHTMLファイルでは生きたマークアップとして解釈される。<script>タグを入れれば、それがスクリプトとして実行される。

ExPatchは、問題の行が2024年2月21日に書かれ(コミット52c779bf、著者23rd)、同年3月8日に安定版v4.15.1として公開されてから修正されるまで、約2年4カ月間にわたり製品コードに存在していたと分析している。

Telegramのアプリ自体はHTMLを解釈しないため、アプリ上ではボタンの文字列はただの文字として表示される。ExPatchは、この「アプリでは普通に見える」ことが問題に気づきにくい理由だったと指摘している。アプリの表示と、書き出したファイルをブラウザーで開いたときの挙動が異なる点が、この脆弱性の特徴である。

攻撃の流れ — ボットはグループに参加しない

ExPatchが示した攻撃の流れは次のとおりである。

  1. 攻撃者はTelegramのBot APIで任意のボットを作成する。ボットは誰でも作成できる。
  2. ボットは、ボタンの文字列に不可視の文字(U+3164のHangul Fillerなど)を並べてスクリプトのタグを隠したメッセージを送る。アプリ上ではボタンが空か、URLだけが表示されているように見える。
  3. そのメッセージが、誰かの手で対象のグループへ転送される。URL型のインラインキーボードは転送しても保持されるため、ボットが対象グループに参加していなくても標的に届く。
  4. ペイロードは履歴に残る。ExPatchは「数カ月から数年、眠り続ける」と表現しており、メッセージが削除されるまで残るとしている。
  5. グループの参加者がチャットをHTML形式でエクスポートし、そのファイルをブラウザーで開くとスクリプトが動作する。開いた後に追加のクリックは不要で、ページの読み込み時に実行される。

ExPatchは、1通のメッセージが20万人規模のスーパーグループへ転送されれば、そのメッセージを含むエクスポートを行った参加者の環境でそれぞれ動作すると説明している。グループとスーパーグループでは、コンテンツ保護が無効であればどの参加者でも転送できる点が広がりやすさの理由である。一方、チャンネルへの転送には投稿権限が必要で、管理者アカウントの侵害や内部関係者の協力が前提になるとしている。

動作すると何が起きるか

ペイロードが動作した場合、ExPatchは次の影響を示している。

  • メッセージの外部送信:開いたエクスポートページに表示されているメッセージ(本文、送信者、タイムスタンプ)が外部のサーバーへ送信される。チャットのメタデータ(チャット名、種類、参加者数)やページ全体のテキスト、さらにはlocation.hrefから得られるローカルのファイルパスも送信対象になる。ファイルパスにはOSのユーザー名やフォルダー構成が含まれる。
  • ページの書き換え:スクリプトはDOMを自由に操作できるため、書き出したページを偽のTelegramの確認画面に置き換えられる。ExPatchの検証ではパスワード欄は読み取り専用のプレースホルダーで、送信先も自分の端末(127.0.0.1)に限定していたという。
  • 履歴の改ざん:タイムスタンプ、送信者名、メッセージ本文の書き換えや並べ替え、挿入、非表示ができる。ExPatchは、法務やコンプライアンスの場面でチャットの書き出しが証拠として使われる場合、ブラウザー上で記録が改変され得る点を問題として挙げている。ただし検証では、Telegramのサーバー側の履歴や、ディスク上の元のHTMLファイルを書き換えるものではないとしている。

ExPatchは、検証を研究者自身のアカウントとテスト用グループで行い、外部への送信先も自分たちの端末に限定していたと説明しており、実在のシステムを狙う完全な攻撃コードは公開していない。

修正と影響範囲

修正は、Telegram Desktopのコミット8457d13a「Fix escaping in HTML export of keyboards.」で行われた。GitHubの記録では、このコミットは2026年6月30日に作成され、7月2日にコミットされている。変更されたファイルはexport_output_html.cppの1つである。

修正の内容は次の2点である(ExPatchの解析とGitHub上の差分による)。

  • ボタンの文字列に SerializeString() を適用し、メッセージ本文と同じエスケープ処理を通すようにした。
  • コピー用ボタンのonclick属性に埋め込まれる文字列について、バックスラッシュと引用符をエスケープするようにした。こちらはJavaScriptの文字列リテラルへの注入をふさぐ追加の修正である。

この修正を含む最初のタグ付きリリースは、ベータ版v6.9.4(2026年7月3日にGitHubで公開)で、安定版としてはv7.0.1(同7月14日公開)が最初になる。

注意が必要なのは、アプリを更新しても、すでにディスク上にある古いエクスポートファイルは書き換わらない点である。ExPatchは、修正前のビルドで作成したHTMLエクスポートには今も動作するスクリプトが残り得るとし、JavaScriptを有効にしたブラウザーで開くと危険があるとしている。ファイルとして保存された古いエクスポートは、クライアント側の修正では保護されない。

公開の経緯 — ExPatchの説明とTelegramの回答

ExPatchは、修正が公開された後にこの解析を公表した。同グループは、修正前の公開は避け、修正後の公開日についてTelegramと調整したいと申し出たと説明している。

ExPatchによると、Telegramは2026年7月1日に報告を受け入れ、バウンティ(報奨金)を提示した。ExPatchは報奨金を辞退し、その相当額を慈善団体へ回すよう求めたという。公開時期については、Telegramはすでに対処済みの問題であっても公開には同意できないとする回答を示した。ExPatchが公開したメールの引用では、Telegramは「すでに対処した問題の公開であっても、情報が公開されれば悪意のある者が悪用を試み、Telegramの利用者に金銭的な被害を与える可能性がある」という趣旨を述べている。

Telegramのバグバウンティ・プログラムの公開ページには、対処される前に公開または第三者へ開示された脆弱性は報奨金の対象外になるという規定がある。ExPatchは、修正後の公開に承認が必要だという記載はないとしている。2026年9月11日時点で、Telegramはこの問題に関するセキュリティアドバイザリを公開しておらず、CVEも採番されていない。ExPatchは、修正は公開されたコミットとして存在するものの、利用者へ届く警告は出ていないと指摘している。

利用者と管理者が今できること(ExPatchの推奨)

ExPatchが示している対応は次のとおりである。対策は同グループの公表内容に限定して記載する。

  • クライアントを更新する:ベータ版はv6.9.4以降、安定版はv7.0.1以降へ更新する。
  • 修正前に書き出したHTMLエクスポートを見直す:更新後にチャットを再エクスポートするか、古いエクスポートファイルをJavaScriptを無効にした状態で開く
  • 修正日以前に作成されたHTMLエクスポートを開く際は注意する:特に大規模なグループのエクスポートは、個々のメッセージの出所を確認しにくい。

出典

この記事は、公開情報と編集部の調査・知見をもとに構成しています。内容は公開時点の情報に基づく解説であり、個別の環境への診断・対応を保証するものではありません。重要な判断では、記事内の出典や各提供元の最新情報もご確認ください。