용어 사전

클릭재킹이란? 다른 페이지 위에 겹친 투명한 페이지의 버튼을 누르게 만드는 공격

클릭재킹은 진짜 페이지를 공격자 사이트 위에 투명하게 겹쳐 사용자가 숨겨진 버튼을 누르게 만드는 공격입니다. 작동 원리와 CSP frame-ancestors, X-Frame-Options 방어를 설명합니다.

게시 2026-06-10 업데이트 2026-10-06 6분 읽기
이 페이지에서

클릭재킹은 보이는 페이지 아래에 숨겨진 페이지의 버튼을 누르게 만드는 공격입니다. 작동 원리와 확실히 막는 방법을 살펴봅니다(공격 절차는 다루지 않습니다).

무엇이 표적이 되는가

'한 번 누르면 끝나고, 가치 있는' 모든 것입니다.

표적이 되기 쉬운 것이유
송금·구매 확인한 번의 클릭으로 돈이 움직임
설정 변경(공개 범위, 연동 앱)이후의 탈취나 데이터 접근을 위한 발판
OAuth·권한 '허용'계정 연동을 조용히 승인
소셜 팔로우·좋아요·게시확산과 좋아요 조작에 악용

왜 통하는가

브라우저는 다른 사이트를 iframe으로 불러와 위에 쌓을 수 있습니다. 공격자는 그 iframe을 투명하게(opacity 0) 만들어, 사용자는 그 아래 배치된 미끼 UI만 보게 됩니다. 사용자가 '가짜 버튼'을 누르면, 바로 위에 겹쳐진 진짜 버튼이 그 클릭을 받습니다.

공격자 페이지: "경품에 당첨되셨습니다. 아래를 클릭!"
= 위에 겹쳐진 진짜 은행·설정 페이지의 투명한 iframe
↓ 사용자가 보이는 미끼 버튼을 클릭
바로 위에 있는 진짜 '확인' 버튼이 실제로 눌림
↓ 사용자 자신의 로그인 상태로
송금 / 설정 변경 / 동의가 '사용자의 행동'으로 완료됨
공격자는 진짜 사이트를 보이지 않게 쌓고, 미끼 UI만 보이게 합니다. 클릭은 투명한 진짜 페이지로 전달됩니다.

CSRF와 비슷해 보이지만, CSRF는 뒤에서 요청을 보내는 반면 클릭재킹은 사용자가 진짜 화면을 직접 조작하게 합니다. 그래서 CSRF 토큰만으로는 막을 수 없습니다.

실제 사례: 브라우저 플러그인의 권한 대화상자(2008년)

2008년 10월, Adobe는 여러 브라우저에 영향을 주는 클릭재킹 문제에 관한 보안 권고(APSA08-08)를 발표했습니다. 보도에 따르면 Flash Player의 설정 대화상자를 보이지 않게 겹쳐, 사용자가 모르는 사이에 사이트에 카메라와 마이크 접근을 허용하게 만들 수 있었습니다. Adobe는 수정된 Flash Player를 배포했고, 임시 대응으로 설정 관리자에서 '항상 거부'를 선택하라고 안내했습니다.

교훈은 송금 버튼만 표적이 되는 것이 아니라는 점입니다. '허용', '동의', '연결'처럼 한 번의 클릭으로 권한을 넘기는 화면은 모두 대상입니다. MITRE는 이 약점을 CWE-1021(렌더링된 UI 레이어나 프레임의 부적절한 제한)로 분류합니다.

방어: 다른 사이트가 내 사이트를 삽입하지 못하게 한다

1

CSP frame-ancestors 설정(가장 중요)

Content-Security-Policy: frame-ancestors 'self'를 추가하세요(내 오리진만 프레임에 넣을 수 있음). 아무도 삽입할 필요가 없다면 'none'이 가장 안전합니다. 명시적으로 허용하는 파트너에 한해서만 도메인을 나열하세요.

2

X-Frame-Options도 추가(하위 호환)

구형 클라이언트를 위해 X-Frame-Options: DENY(또는 SAMEORIGIN)도 함께 보내세요. 이렇게 하면 구형·신형 브라우저 모두에 대응할 수 있습니다.

3

중요한 행동에는 확인 단계를 추가

송금과 권한 부여에는 재인증, 확인 대화상자, 의도 확인을 두세요. 보이지 않는 오버레이로 끝까지 진행시키기 어려워집니다.

4

세션 쿠키를 SameSite로

SameSite=Lax/Strict는 크로스 사이트 자동 전송을 줄입니다. 그 자체로 클릭재킹의 완전한 해결책은 아니지만, '다른 사이트에서 시작된 행동'이라는 더 넓은 범주를 약화시킵니다.

X-Frame-Options와 CSP frame-ancestors의 차이

두 헤더 모두 다른 사이트의 삽입을 막지만 세부 사항이 다릅니다.

X-Frame-OptionsCSP frame-ancestors
값DENY(모두 차단) / SAMEORIGIN(같은 오리진만)'none' / 'self' / 허용 도메인 목록
여러 곳의 삽입 허용불가(ALLOW-FROM은 최신 브라우저에서 작동하지 않음)가능
meta 태그로 설정효과 없음효과 없음
둘 다 있을 때지원 브라우저에서는 무시됨우선 적용
역할구형 브라우저용 대비책현재의 주된 방어

둘 다 보낼 때는 의미를 맞춥니다. frame-ancestors 'none'에는 DENY를, frame-ancestors 'self'에는 SAMEORIGIN을 짝짓습니다.

흔한 설정 실수

  • CSP의 default-src로 충분하다고 생각한다. frame-ancestors는 default-src로 대체되지 않습니다. default-src 'none'이어도 frame-ancestors를 쓰지 않으면 삽입은 허용된 채로 남습니다
  • meta 태그에 넣는다: 이 경우 <meta http-equiv>는 효과가 없으므로 응답 헤더로 보냅니다
  • Content-Security-Policy-Report-Only로 둔다: 위반을 보고만 할 뿐 삽입을 막지 않습니다. 동작을 확인했다면 차단하는 헤더로 바꿉니다
  • 일부 페이지에만 설정한다: 홈페이지는 확인하고 로그인 페이지, 설정 페이지, 오류 페이지는 놓치기 쉽습니다. CDN이나 프록시가 헤더를 지우지 않는지도 확인합니다

자신의 사이트 점검 방법

1

헤더 점검 도구로 확인한다

보안 헤더 점검에 사이트 URL을 넣고 X-Frame-Options와 CSP frame-ancestors가 반환되는지 봅니다. 홈페이지뿐 아니라 로그인 후 설정 페이지, 송금이나 권한 부여 페이지도 확인합니다.

2

브라우저 개발자 도구로 확인한다

네트워크 탭을 연 상태로 페이지를 새로 고치고 HTML 응답의 헤더를 봅니다. 헤더가 두 번 보내지거나 서로 다른 값으로 보내지지 않는지도 확인합니다.

3

한곳에서 설정한다

한곳(nginx나 Caddy 같은 웹 서버, 리버스 프록시, 프레임워크)에서 모든 응답에 추가하면 누락과 중복을 함께 막을 수 있습니다. CSP를 새로 작성한다면 CSP 빌더로 frame-ancestors를 포함한 정책을 만들 수 있습니다.

이 사이트의 관점: 헤더 한 줄이 가장 효과적인 대책이므로 먼저 내 사이트부터 점검한다

클릭재킹 방어는 복잡한 코드가 아니라 삽입을 막는 한두 줄의 응답 헤더입니다. 프레임워크나 리버스 프록시(Caddy/nginx)에서 사이트 전체에 적용해 빠지는 곳이 없게 하세요. 가장 흔한 실패는 설정했다고 생각했지만 실제로는 빠져 있는 헤더이므로, 설정한 뒤에는 위의 방법으로 실제로 반환되는지 확인하세요.

출처(1차 자료)

  • OWASP, "Clickjacking Defense Cheat Sheet" — cheatsheetseries.owasp.org(frame-ancestors, X-Frame-Options, SameSite. ALLOW-FROM은 작동하지 않음, meta 태그는 효과 없음, 프레임 버스팅의 한계)
  • MDN, "CSP: frame-ancestors" — developer.mozilla.org(허용 값, default-src로 대체되지 않음, meta 미지원)
  • RFC 7034, "HTTP Header Field X-Frame-Options" — rfc-editor.org
  • IPA, '안전한 웹사이트 만드는 법 1.9 클릭재킹'(일본어) — ipa.go.jp
  • Adobe, "Security Advisory for Flash Player (APSA08-08)"(2008년 10월 7일) — adobe.com
  • Computerworld, "Clickjackers could hijack webcams, microphones, Adobe warns"(2008년 10월) — computerworld.com(카메라·마이크 권한 대화상자가 표적)
  • MITRE, "CWE-1021: Improper Restriction of Rendered UI Layers or Frames" — cwe.mitre.org

다음으로 읽기

분류 번호

CWE는 취약점의 원인이 되는 약점의 종류를, MITRE ATT&CK는 공격자의 기법을 분류한 번호 체계입니다. 둘 다 MITRE가 관리하며 취약점 정보와 탐지 규칙 분류에 널리 쓰입니다.

CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use

FAQ

Q클릭재킹으로 무엇이 가능한가요?
A

사용자가 '의도해서' 누른 클릭이 그 아래에 겹쳐진 진짜 페이지의 버튼에 떨어집니다. 한 번의 클릭으로 끝나는 중요한 행동, 즉 송금, 설정 변경, 권한 부여, 소셜 팔로우·좋아요, 동의 버튼이 악용됩니다. 비밀번호를 훔치는 것이 아니라, 이미 로그인된 사용자가 그 행동을 직접 하게 만듭니다.

Q가장 중요한 방어책은 무엇인가요?
A

다른 사이트의 프레임에 삽입되는 것을 거부하는 것입니다. 응답 헤더에서 CSP frame-ancestors 지시어를 'self'(또는 허용한 도메인만)로 설정하고, 하위 호환을 위해 X-Frame-Options: DENY를 추가하세요. 그러면 오버레이에 필요한 바탕 자체가 사라집니다.

QJavaScript 프레임 버스팅으로 충분한가요?
A

아닙니다. 'iframe 안에 있으면 빠져나간다'는 옛 스크립트는 우회 방법이 많고, JavaScript가 꺼져 있으면 도움이 되지 않습니다. 확실한 방어는 브라우저에 삽입을 거부하도록 지시하는 서버 헤더(frame-ancestors / X-Frame-Options)입니다.

QX-Frame-Options와 CSP frame-ancestors 중 무엇을 써야 하나요?
A

의미를 맞춰 둘 다 보내는 것이 표준적인 방법입니다. frame-ancestors는 삽입을 허용할 곳을 여러 개 지정할 수 있고, 둘 다 있으면 지원하는 브라우저는 frame-ancestors를 적용합니다. X-Frame-Options는 구형 브라우저용 대비책입니다. 'none'에는 DENY를, 'self'에는 SAMEORIGIN을 짝지으세요.

QHTML의 meta 태그로 설정할 수 있나요?
A

안 됩니다. frame-ancestors는 meta 요소에서는 효과가 없고, meta 요소의 X-Frame-Options도 무시됩니다. 둘 다 웹 서버, 리버스 프록시, 프레임워크에서 HTTP 응답 헤더로 보내야 합니다.

Q자사의 다른 사이트나 파트너가 페이지를 삽입해야 한다면?
A

frame-ancestors에 허용할 곳을 나열합니다(예: frame-ancestors 'self' https://partner.example). X-Frame-Options의 ALLOW-FROM은 최신 브라우저에서 작동하지 않으므로 허용 목록 용도로 쓰지 마세요. 허용은 실제로 삽입이 필요한 페이지와 도메인으로 한정합니다.