<iframe>
은 다른 출처의 웹사이트를 페이지 내에 삽입할 때 흔하게 사용된다.
iframe은 css 설정을 통해 겹쳐지거나(Overlapping), 투명해지는(Transparent) 등 표현 형태를 조절할 수 있다.
클릭재킹은 악의적으로 iframe을 숨겨 사용자가 의도하지 클릭을 수행하도록 유도하는 공격이다.
사용자는 Like 버튼을 클릭하는 것으로 인식하지만, 실제로는 투명한 iframe으로 겹쳐져있는 다른 게시글의 Like를 클릭한다.
Professor Du's Class Rocks!
: 사용자가 Like 하고자 했던 게시글
Professor Du's Class Sucks!
: 실제 Like된 게시글
다음과 같이 top
의 opacity : 0.0
으로 설정하여 완전히 투명하게 설정
사용자가 클릭한 Like 버튼과 전혀 무관한 링크(친구 추가)가 겹쳐져 있어 Add friend 버튼을 클릭하게 됨
사용자에게 버튼을 순서대로 클릭하도록 하는 단순한 미니게임처럼 보이지만, 실제로는 각 버튼에 다른 클릭 재킹이 포함되어있을 수 있다.
사용자가 누르는 Like 버튼 위에 클릭재킹을 유도하는 iframe이 존재하지만, 매우 작게 만들어져 배치되어 있음
사용자는 진짜 사이트에 로그인하려고 하지만, 실제로는 공격자의 입력 폼에 아이디와 비밀번호를 입력함
iframe 기반 클릭재킹 공격에 대한 대응책은 무엇이 있을까?
(Client-side) JS 코드를 사용하여 겹쳐있는 iframe을 감지하는 방식이 대표적인 대응책이다.
이러한 방식을 Framekiller/Framebuster라고 한다. 다음 코드를 살펴보자.
<script type="text/javascrip">
if (top != self) top.location.replace(location);
</script>
top != self
: 현재 페이지가 iframe 안에서 로드되었는지 검사 (최상위 Window내에 존재하는지)
top.location.replace(location)
: 현재 페이지를 최상위 창(Window)에 다시 로드함으로써 iframe을 벗어나도록 함
자주 사용되는 프레임 버스터 로직은 다음과 같다.
프레임 킬러/프레임 버스터는 Client-side에서 사용하는 클릭재킹 대응책이므로, 여러가지 방식으로 이를 회피할 수 있다.
다음 코드를 살펴보자.
if(top.location != self.location) {
parent.location = self.location;
}
// Attacker top-frame:
<ifame src="attacker2.html">
// Attacker sub-frame:
<iframe src="http://www.victim.com">
프레임 버스팅 코드는 현재 페이지(self)가 최상위 창(top)안에 포함되는지 검사하며, 만일 포함된다면 top이 self가 아니라는 뜻이므로 self를 top으로 위치시키는 원리이다.
만일 공격자가 위와 같이 2중으로 ifame을 구성할 경우, 프레임 버스팅 코드로 top.location을 수정하지 못하게 됨.
다음 코드를 살펴보자.
<script>
window.onbeforeunload=function() {
return "Asking_the_user_nicely";
}
</script>
<iframe src="http://www.paypal.com">
onbeforeunload
는 사용자가 페이지를 떠날 때 경고창을 띄우는 함수이다.
frame busting 코드가 top.location을 바꾸려고 시도할 경우 사용자에게 알림이 떠 페이지를 벗어나지 않도록 유도할 수 있음.
if (top.location != location) {
if (document.referrer && document.referrer.indexOf("walmart.com") == -1) {
top.location.replace(document.location.href);
}
}
위 코드의 경우, 레퍼러에 walmart.com
이 포함되는 검사만 진행하기 때문에, 공격자가 walmart.com.badgy.com
과 같이 walmart
의 서브 도메인을 이용하면 우회가 가능하다.
sandbox
속성을 활용해 iframe 내부의 script 실행을 제한하여 프레임 버스터 코드가 실행되지 않도록 막을 수 있다.
Case 1 : script 허용까지 포함
Case 2 : script를 허용하지 않고 form 전송만을 허용
다만, sandbox
속성은 프레임 버스팅에만 활용하는 것은 아니다. 때에 따라 iframe의 보안을 유지하는 데 활용하기도 한다.
예를 들어, 다음과 같이 외부에서 오는 컨텐츠라고 할지라도 아무런 스크립트도 실행하지 않도록 설정하여 악의적인 외부 컨텐츠도 스크립트 격리가 가능하다.
Client-side 클릭재킹 대응책은 위와 같이 많은 파훼법이 존재한다. 따라서 Server-side 대응책이 보다 확실한 클릭재킹 방지 방법이다.
X-Frame-Options
는 서버측에서 설정하는 X-Frame-Header Option으로, 이를 활용해 클릭재킹 공격에 대응할 수 있다.
Deny
: iframe에 어떤 페이지도 삽입을 허용하지 않음
SAMEORIGIN
: 동일 출처에 대한 삽입만 허용
allow-from {URL}
: 특정 URL 페이지의 삽입만 허용
다만 이는 초창기에 활용한 방식이며, 현재는 사용하지 않는다.
웹 애플리케이션이 제한 규칙을 정의하는 방식으로, 여기서 사용되는 옵션들은 다음과 같다.
script-src
: 스크립트 소스의 허용 목록 지정
img-src
: 이미지 소스 허용 목록 지정
frame-ancestors
: <frame>, <iframe>, <object>, <embed>, <apple>
태그를 사용해 페이지를 포함할 수 있는 유효 부모 페이지를 지정
지정 예시는 다음과 같다.
Content-Security-Policy: {options} <suorce> ... <source>;
iframe A와 iframe B는 동일한 Origin, iframe C는 A,B와 다른 Origin을 갖는다.
부모 자식 접근 : 부모 페이지에서 iframe 내 DOM에 접근할 경우, 출처가 동일한 경우에만 가능
자식 부모 접근 : iframe 내부에서 부모 페이지에 접근할 경우, 출처가 동일한 경우에만 가능
자식 형제(Sibling) 접근 : 한 iframe에서 다른 형제 iframe에 접근할 경우, 출처가 동일한 경우에만 가능
즉, iframe의 SOP로 인해 접근에 대한 결과는 다음과 같이 나타난다.
Context integrity(콘텐츠 무결성)을 보장한다는 것은, 다음 두 가지를 보장한다는 의미이다.
(Visual Integrity, 시각적 무결성) 사용자가 인식하는 클릭 대상이 시각적으로 확인이 가능하며 투명하거나 겹쳐진 객체가 없어야 한다.
User Confirmation : 검증되지 않은 도메인에서 요청이 올 경우 확인창을 띄운다. 이는 간단하지만, UX 복잡성을 증가시킨다.
UI Randomization : 버튼, 메뉴 등의 위치를 무작위로 바꾸어 공격자가 위치를 예측하지 못하게 한다. 이는 사용자 클릭 실수 발생 확률을 높인다.
Visibility Detection on click : 클릭된 객체와 렌더링된 객체의 비트맵을 비교하여, 같지 않을 경우 거부하는 방어 기법이다. 이는 UX를 저하시키며, 부분적으로 겹쳐진(Partial overlay)의 경우 탐지가 어려울 수 있다.
(Temporal Integrity, 시간적 무결성) UI의 상태가 클릭 전과 후에 동일해야 한다. 즉, 사용자가 "버튼을 누른다"고 인식한 후 실제 클릭 순간까지 UI 변조 공격이 없어야 한다.
과거 시스템은 권한을 요청할 때 다음과 같은 방식을 사용했다.
Manifests : 앱이 설치될 때 필요한 권한을 미리 선언
Prompts : 앱이 실행 중일 때 팝업을 통해 사용자에게 권한 질의
최근에는 시간적 무결성 보장을 위해 Access Control Gadgets(ACG) 방식을 활용하는 추세이다.
ACG는 사용자가 명시적으로 권한을 부여하는 행동을 UI안에 자연스럽게 녹여낸 방식의 권한 제어 매커니즘이다.
사용자 주도 접근 제어는 사용자가 어떤 자원을 사용할 때, 그 자원을 요청하는 행동 자체가 곧 권한 부여 행위로 이어지도록 설계하는 방식이다.
ACG는 다음 조건을 만족시켜야 한다.
Display Isolation : ACG 버튼은 시스템이 관리하는 격리된 레이어에 표시되어 앱이 이 버튼의 픽셀을 조작하거나 위조할 수 없음
Complete visibility : ACG는 가려지면 안됨
Sufficient Display Duration : ACG는 일정 시간 이상 화면에 노출되어야 함. 즉, 사용 시점-확인 시점 간 공격(TOCTTOU)를 방지하여야 함
No confusion : 가장 상위에 존재한 애플리케이션만 ACG를 포함하여야 함