1,418文字の視覚的欺瞞:Unicode混同攻撃の実態とSSIMで見える「本当に危険な82文字ペア」

AI

title: “1,418文字の視覚的欺瞞:Unicode混同攻撃の実態とSSIMで見える「本当に危険な82文字ペア」”
date: 2026-02-26
category: Security
tags: unicode, security, homoglyph, ssim, visual-attack

はじめに:見えない脅威

Web開発者は皆、「SQLインジェクション」や「XSS」といった攻撃には馴染みがあるだろう。だが、「視覚的な類似性」を悪用する攻撃についてはどうだろうか?

例えば、この2つのドメインを見分けられるだろうか?

  • gοοgle.com(ギリシャ文字ο)
  • google.com(ラテン文字o)

一見して同じに見える。だが、前者はフィッシングサイトかもしれない。このような攻撃は「Homoglyph Attack(同形文字攻撃)」と呼ばれ、Unicodeの膨大な文字セットが温床となっている。

2026年2月、開発者Paul Tendoが1,418組のUnicode混同文字ペアを230種類のフォントで実際にレンダリングし、SSIM(Structural Similarity Index Measure)を使って定量化する実験を行った。その結果は衝撃的だった。

96.5%の混同文字ペアは実際には危険ではない。
だが、82ペアは「ピクセルレベルで完全に同一」だった。

本記事では、この実験の詳細と、Web開発者が知るべき実践的対策を解説する。

What:Unicode混同文字攻撃とは

Unicode Consortiumは、世界中の文字体系を統一的に扱うための標準を策定している。現在、Unicodeには15万文字以上が含まれている。

その中には、視覚的にほぼ同じに見えるのに、異なるコードポイントを持つ文字が多数存在する。これらは「Confusables(混同文字)」としてUTS #39で文書化されている。

主な混同文字の例

| 正規文字 | 混同文字 | スクリプト | 例 |
|———|———|———–|—–|
| a | а | キリル文字 | pаypal.com |
| e | е | キリル文字 | еmail.com |
| o | ο | ギリシャ文字 | gοοgle.com |
| 0 | О | キリル文字 | О0 |
| l | ӏ | キリル文字 | ӏogin |

これらを悪用した攻撃パターン:

  • フィッシングドメイン: 類似ドメインで偽サイトをホスト
  • IDなりすまし: SNSで類似ユーザー名を取得
  • コード難読化: 変数名に混同文字を使用して可読性を低下
  • How:実験手法

    confusable-visionツール

    Paul Tendoは、この問題を定量化するためにconfusable-visionというツールを開発した。

    処理フロー:

    1,418混同文字ペア
        ↓
    fontconfigで文字対応フォントを検索
        ↓
    8,881回のターゲットレンダリング(48×48グレースケールPNG)
        ↓
    235,625回のSSIM比較
        ↓
    スコア付きJSON出力
    

    なぜSSIMなのか

    SSIM(Structural Similarity Index Measure)は、2つの画像の類似性を測る指標で、-1から1の値を返す:

    • 1.0: ピクセル完全同一
    • 0: 構造的相関なし
    • -1: 反相関(ランダムノイズより似ていない)

    学習ベースのCNN(VGG16など)ではなくSSIMを採用した理由は明確だ:再現性。GPUも学習データもモデル重みも不要。誰でも同じ結果を再現できる。

    フォント発見

    230種類のシステムフォントを使用:

    | カテゴリ | 数 | 用途 |
    |———|—–|——|
    | standard | 74 | Latin主要フォント(Arial, Menlo, Georgia等) |
    | script | 49 | CJK、Indic、Thai等のラテン文字含有フォント |
    | noto | 103 | 非ラテンスクリプト用Noto Sans |
    | math | 3 | STIX Two Math等 |
    | symbol | 1 | Apple Symbols |

    Results:衝撃の統計

    ヘッドライン:96.5%は危険ではない

    | バンド | 数 | % | 説明 |
    |——-|—–|—–|——|
    | High (>= 0.7) | 49 | 3.5% | 本当に危険 |
    | Medium (0.3-0.7) | 681 | 48.0% | フォント依存 |
    | Low (< 0.3) | 611 | 43.1% | 視覚的に混同不可 | | No data | 77 | 5.4% | システムフォントに存在せず |

    中央値SSIM: 0.322 — 典型的な混同文字は、実際にはあまり似ていない。

    だが82ペアはピクセル完全同一

    平均SSIMは脅威を過小評価する。攻撃者は「少なくとも1つのフォント」で成功すればよい。

    例:キリル文字ԁ (U+0501) とラテン文字d

    • 平均SSIM: 0.781(中程度)
    • しかし8つのフォントでSSIM 1.000(ピクセル完全同一)

    Arial, Menlo, Cochin, Tahoma, Charter, Georgia, Baskerville, Verdana — これら全てで完全に区別不可能。

    最も危険なスクリプト

    #### キリル文字ホモグリフ:真の脅威

    キリル文字はラテン文字と多くの共通グリフを持つ。一部は同一のグリフを共有:

    • а → a
    • е → e
    • о → o
    • р → p
    • с → c
    • х → x

    これらは履歴的に同一のグリフから派生したため、多くのフォントで完全に区別不可能。

    #### ローマ数字:意図的なグリフ再利用

    ローマ数字(Ⅰ, Ⅱ, Ⅲ等)は多くのフォントでラテン文字Iと同じグリフを使用。これはバグではなく、設計上の決定

    #### ヘブライ語Paseq:予期せぬ発見

    ヘブライ語のPaseq(U+05C0)は、一部のフォントでラテン文字の縦棒(|)と完全に同一にレンダリングされる。これは予期せぬ発見だった。

    最も危険なフォント

    高危険率フォント

    フォントによって危険度が大きく異なる。一部のフォントは混同文字ペアの20%以上をピクセル同一でレンダリングする。

    低危険率フォント

    逆に、一部のフォントは混攻撃に対して非常に堅牢。独自のタイポグラフィックデザインが、異なるスクリプト間の視覚的差異を保持している。

    Web開発者への実践的対策

    1. IDN(国際化ドメイン名)の検証

    // Punycode形式に変換して確認
    function checkDomain(domain) {
      const punycoded = punycode.toASCII(domain);
      if (punycoded !== domain) {
        console.warn('非ASCII文字が含まれています:', punycoded);
      }
    }

    checkDomain('gοοgle.com'); // xn--ggle-6qda.com

    2. ユーザー名の正規化

    // UTS #39準拠の正規化
    const { confusables } = require('unicode-confusables');

    function normalizeUsername(username) { return username.normalize('NFKC') .split('') .map(char => confusables.get(char) || char) .join(''); }

    normalizeUsername('pаypal'); // 'paypal'(キリルа → ラテンa)

    3. 視覚的警告の実装

    // 混在スクリプト検出
    function detectMixedScript(text) {
      const scripts = new Set();
      for (const char of text) {
        const script = getScript(char); // Unicodeスクリプト判定
        scripts.add(script);
      }
      
      if (scripts.size > 1) {
        return {
          warning: '複数の文字体系が混在しています',
          scripts: Array.from(scripts)
        };
      }
      return { safe: true };
    }
    

    4. フォント選択の考慮

    危険率の低いフォントを優先的に使用。特に、ユーザー生成コンテンツを表示する領域では、フォント選択がセキュリティ上の決定となり得る。

    Why:なぜこの問題は解決されないのか

    互換性 vs セキュリティ

    Unicodeの歴史的互換性要件により、多くの「同一グリフ・異なるコードポイント」が標準化されている。これを変更すると、膨大な既存データが破損する。

    TR39の限界

    UTS #39のconfusables.txtは視覚的類似性を主張しているが、大規模な実証検証は行われてこなかった。多くのエントリはNFKC正規化下での意味的マッピングに基づいており、実際のレンダリング結果とは乖離がある。

    フォント依存性

    同一の文字でも、フォントによって全く異なるグリフでレンダリングされる。Webアプリケーションはエンドユーザーのフォントを制御できないため、完全な対策は困難。

    When:攻撃が成功する状況

  • ドメイン登録時: 視覚的に類似したドメインを取得
  • アカウント作成時: 正規ユーザー名の混同版を登録
  • コードレビュー時: 変数名の微妙な違いを見逃す
  • URL表示時: アドレスバーのドメインを目視確認
  • Where:影響範囲

    • Webブラウザ: ドメイン、URLパラメータ、フォーム入力
    • SNS: ユーザー名、ハッシュタグ、メンション
    • メッセージングアプリ: 送信者名、グループ名
    • コードエディタ: 変数名、関数名、識別子
    • 決済システム: 口座名義、送金先

    Conclusion:見えない脅威への対策

    Paul Tendoの実験は、Unicode混攻撃の実態を初めて大規模に定量化した。重要な知見:

  • 96.5%の混同文字は実際には危険ではない — 過剰な心配は不要
  • だが82ペアは本当の脅威 — 特にキリル文字ホモグリフ
  • フォント選択がセキュリティに影響 — UIデザインの新たな責任
  • SSIMによる定量的評価が可能 — 主観から客観へ
  • 推奨アクション

  • IDN/Punycode検証を導入
  • UTS #39準拠の正規化パイプライン構築
  • 複数スクリプト混在の警告UI実装
  • 定期的な混同文字データベース更新
  • 視覚的欺瞞は「見えない」攻撃だが、適切な対策で可視化し、無力化できる。開発者は今こそ、Unicodeの深淵を理解し、ユーザーを守る準備をすべきだ。

    参考リンク

    *この記事はReddit r/programmingで話題の投稿を基に、技術的背景と実践的対策を深掘りして執筆しました。*

    コメント

    タイトルとURLをコピーしました