クリックジャッキング解説:Webの「見えない脅威」

Security

「無料クーポンかと思ったら、意図せずSNSをフォローしていた」「面白い記事を読もうとしただけなのに、気づいたら商品を購入していた」――そんな不思議な経験はありませんか?

その裏には、あなたのクリックを乗っ取り、意図しない操作をさせるクリックジャッキング(Clickjacking)という巧妙なサイバー攻撃が隠れているかもしれません。

この記事では、ユーザーを騙す「見えない罠」の仕組みから、具体的な被害事例、そして自分を守るための防御策まで、デモを交えながら徹底解説します。


クリックジャッキングの正体と仕組み

UI Redress攻撃とも呼ばれる「クリックの乗っ取り」

クリックジャッキングは、その名の通り「クリックを乗っ取る(Jack)」攻撃です。攻撃者が用意した偽のWebページ上に、透明化した別のサイトを重ねることで、ユーザーの操作をだまし取ります。

この手口は、Webサイトの見た目(UI)を偽装(Redress)することから、UI Redress攻撃 とも呼ばれます。

攻撃者は何を狙っているのか?

攻撃者が狙うのは、ユーザーがログイン状態で行う重要な操作です。例えば、以下のようなアクションが標的になります。

金銭的な被害: ネットショッピングでの意図しない商品購入や、有料サービスへの登録

SNSアカウントの操作: 勝手に「いいね!」や「フォロー」、投稿をさせられる

アカウント設定の変更: 気づかぬうちにパスワード変更や退会手続きをさせられる

権限の許可: アプリ連携(OAuth)の承認や、PCのカメラ・マイクへのアクセス許可

クリックジャッキングは、こうして行われる

クリックジャッキングは、Webページの基本的な技術である <iframe>CSS を悪用して実現されます。その手口を2つの層に分けて見てみましょう。

  • 裏のページ(おとり) ユーザーの興味を引く「景品が当たる!」「限定動画を再生」といった、無害に見えるボタンやリンクが配置されています。
  • 表のページ(ターゲット) <iframe> タグで読み込まれた、あなたのSNSやショッピングサイトなど。CSSの opacity プロパティで完全に透明化されています。

攻撃者は、この2つのページをピタリと重ね合わせます。あなたが「動画を再生」ボタンをクリックしたつもりが、その真下には透明な「商品購入」ボタンが隠れている、という仕組みです。

クリックジャックの実践!デモンストレーション

以下の2つのHTMLファイルを同じフォルダに保存し、clickjacking.htmlをブラウザで開いてみてください。
見た目は「見かけ上のボタン」が表示されています。しかしそのボタンをクリックすると、実際には透明にして隠した「本物のボタン」がクリックされます。

clickjacking.html(悪意がある攻撃者のページ)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Clickjacking PoC</title>
  <style>
    /* iframeを見かけ上のボタンの上にピッタリ重ねる */
    .frame-wrapper {
      position: relative;
      display: inline-block;
    }
    .fake-button {
      position: relative;
      z-index: 1;
    }
    iframe {
      position: absolute;
      top: 0;
      left: 0;
      width: 200px;   /* 本物ボタンのサイズに合わせる */
      height: 40px;
      opacity: 0.40;  /* 透明にする */
      z-index: 2;
      border: none;
    }
  </style>
</head>
<body>
  <h1>Clickjacking</h1>
  <p>このボタンを押してみてください:</p>

  <div class="frame-wrapper">
    <button class="fake-button">見かけ上のボタン</button>
    <iframe src="target.html"></iframe>
  </div>
</body>
</html>

攻撃者側のスタイルシートについて補足します。

  • position: absolute: iframeを偽ボタンと完全に重ねる
  • opacity: 0.4: iframeを透明にして存在を隠す(ここでは解説の為に半透明にしていますが、実際の攻撃では透明の0にします)
  • z-index: 2: iframeを偽ボタンより前面に配置して、クリックを横取りする

target.html(攻撃対象のページ。我々が守るべきページ)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Target</title>
</head>
<body>
  <button onclick="alert('ターゲットボタンがクリックされました!')">
    本物のボタン
  </button>
</body>
</html>

これは攻撃される側のページです。シンプルなボタンが1つあり、クリックすると「ターゲットボタンがクリックされました!」というアラートが表示されます。

clickjacking.htmlを表示。しかし表に透明化したtarget側の本物のボタンが存在している。

ボタンを押下するとtarget側のalertが反応!

何が起きているのか

  1. ユーザーには「見かけ上のボタン」という無害そうなボタンが見える
  2. しかし実際には、その上にtarget.htmlを読み込んだiframeが透明で重ねられている
  3. ユーザーが見かけ上のボタンをクリックすると、実際にはiframe内の「本物のボタン」をクリックしている
  4. 結果として、ユーザーの意図しない操作が実行される

デモ用htmlのボタン押下でalertの反応がない場合

上記の2つのhtmlファイルを同じフォルダに格納して、攻撃者側のhtmlをブラウザで開き、ボタンを押下しても、ターゲット側のalertが反応しない場合があります。
file:// スキームで開いている場合、iframe の挙動が制限される為と思われます。その場合は、次の手順で実行すると良いでしょう。

  1. コマンドプロンプトでカレントディレクトリを2つのhtmlファイルのパスにする
  2. python -m http.server 8000
    でポート8000番でサーバー起動する。
    python -m は、Pythonをモジュールとして実行するためのオプションです。
    http.serverはPythonの標準ライブラリとして組み込まれています。
  3. ブラウザで次のURLを開く
    http://localhost:8000/clickjacking.html
  4. ブラウザの「見かけ上のボタン」をクリック

→ iframe 内の target.html のボタンが押されて alert() が出るはずです。

実際にあったクリックジャッキングの怖い話

クリックジャッキングは、理論上の脅威ではありません。過去に何度も、私たちの身近なサービスで実際に被害が発生しています。

  • 事例1:SNSでの意図しない「いいね!」やシェアの拡散 最も有名なのが、2010年頃にFacebookやTwitterで多発した事例です。「無料ギフト券が当たる!」といった魅力的なボタンをクリックしたユーザーが、気づかないうちに特定のページに「いいね!」を押し、その情報が友達のフィードにまで拡散されてしまうというもの。攻撃者はこれを利用して、悪意のあるサイトへの誘導や、アフィリエイト収入を得ていました。
  • 事例2:不正なアプリ連携(OAuth)の承認 「このアプリと連携すると便利になります」という偽のポップアップを表示し、その裏に本物のGoogleやFacebookの「連携許可」ボタンを透明に重ねます。ユーザーが「閉じる」ボタンなどをクリックしたつもりが、実際には意図しないアプリに個人情報へのアクセス権(連絡先、投稿内容など)を与えてしまうのです。
  • 事例3:ブラウザ権限の乗っ取り さらに悪質なケースでは、Web会議ツールなどを装い、PCのカメラやマイクへのアクセス許可を求める画面を悪用します。ユーザーが偽の「会議に参加」ボタンをクリックすると、裏で本物の「許可」ボタンが押され、盗撮や盗聴につながる危険性がありました。

対応策:クリックジャッキングからWebサイトを守る

Webサイトをこの巧妙な攻撃から守るためには、サーバー側での適切な設定が不可欠です。主な対策はHTTPレスポンスヘッダーに特定の情報を追加すること。ここでは、現在主流の2つの方法を詳しく解説します。

対策1:X-Frame-Options

X-Frame-Options は、他のサイトがあなたのWebページを <iframe><frame><object> タグで埋め込むことをブラウザに制御させるための、古くからある信頼性の高いヘッダーです。いわば「うちのページは、他人のサイト内では表示させません」という意思表示です。

設定できる値は3種類あります。

  1. DENY 最も強力な設定です。どのサイトからの埋め込みも、一切許可しません。自サイト内のページからの埋め込みも拒否します。HTTPX-Frame-Options: DENY
  2. SAMEORIGIN 一般的に推奨される設定です。同一オリジン(同じドメイン、プロトコル、ポート)からの埋め込みのみを許可します。例えば、example.com のページは、同じ example.com の別のページ内でのみ <iframe> で表示できます。HTTP X-Frame-Options: SAMEORIGIN
  3. ALLOW-FROM uri 特定のURIからの埋め込みのみを許可します。ただし、このディレクティブは一部のブラウザでサポートされていないため、現在では利用は推奨されません。

対策2:Content Security Policy (CSP) の frame-ancestors

Content Security Policy (CSP) は、XSS(クロスサイトスクリプティング)など、さまざまな攻撃を防ぐための非常に強力で柔軟な仕組みです。その中にある frame-ancestors ディレクティブが、クリックジャッキング対策の現代的な標準とされています。

X-Frame-Options よりも、きめ細やかな設定が可能です。

  • 一切の埋め込みを拒否する場合 (DENY と同等)HTTPContent-Security-Policy: frame-ancestors 'none';
  • 同一オリジンからのみ許可する場合 (SAMEORIGIN と同等)HTTPContent-Security-Policy: frame-ancestors 'self';
  • 複数の特定のドメインを許可する場合 X-Frame-Options ではできなかった、複数のドメインからの埋め込みを安全に許可できます。パートナーサイトなど、信頼できる特定のサイトがある場合に非常に有効です。HTTPContent-Security-Policy: frame-ancestors 'self' https://partner-site.com https://another-trusted.jp;

💡 どちらを使えばいい? 現在では、CSPの frame-ancestors を利用するのがベストプラクティスです。ただし、古いブラウザとの互換性を最大限に確保したい場合は、X-Frame-Options: SAMEORIGIN も併せて設定しておくと、より堅牢になります。

(非推奨)フレームバスティングについて

以前は、JavaScriptを使ってページが <iframe> 内に埋め込まれていたら、強制的にトップページに遷移させる「フレームバスティング」という手法がありました。しかし、この方法は攻撃者によって容易に回避されてしまうため、現在では信頼性の低い対策とされています。


まとめ:あなたのサイトは大丈夫?最終チェックリスト

クリックジャッキングはシンプルな仕組みですが、ユーザーに大きな被害をもたらす可能性があります。最後に、あなたのサイトが安全かを確認するためのチェックリストです。

  1. HTTPレスポンスヘッダーを確認したか? すべてのページで、Content-Security-Policy: frame-ancestors 'self'; または X-Frame-Options: SAMEORIGIN (もしくは DENY)が設定されていることを確認しましょう。
  2. 重要な操作ページの設定は万全か? 特に、アカウント情報の変更、購入処理、退会ページなど、ユーザーの重要なアクションを伴うページでは、frame-ancestors 'none'X-Frame-Options: DENY といった最も厳しい設定を適用することを検討してください。
  3. 設定を定期的に見直しているか? セキュリティは「一度設定したら終わり」ではありません。新しい技術や脅威が登場する中で、サイトのセキュリティ設定が今も最適であるか、定期的に棚卸しする習慣が大切です。

正しい防御策を導入し、ユーザーが安心して使えるWebサイトを維持しましょう。

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