Tabnabbing은 명백한 악성 피싱 공격의 한 종류이다. 사용자가 눈치채지 못하게 기존 탭의 내용을 바꿔치기하여 개인 정보를 탈취하는 교묘한 기법이다.
탭 내빙은 탭(Tab)과 납치하다(nabbing)의 합성어다. 공격 시나리오는 다음과 같다.
1. 사용자가 신뢰하는 사이트 A에 머물고 있다.
2. 사이트 A에 있는 외부 링크를 클릭한다. 이 링크는 target="_blank" 속성을 가지고 있어 새 탭에서 열린다.
3. 새 탭에서 열린 악성 사이트 B는, 자신을 열어준 원래 탭(사이트 A)의 주소를 가짜 로그인 페이지로 바꿔치기한다.
4. 사용자는 사이트 B에서의 볼일을 마치고 원래 탭 A로 돌아옵니다.
5. 탭 A는 "세션이 만료되었습니다. 다시 로그인해주세요."와 같은 가짜 로그인 화면으로 바뀌어 있다.
6. 사용자는 의심 없이 아이디와 비밀번호를 입력하고, 이 정보는 고스란히 공격자에게 넘어간다,
이 공격이 가능한 이유는 target="_blank" 로 링크를 열 때 발생하는 브라우저의 기본 동작 때문이다 <a> 태그에 target="_blank" 속성을 사용해 새 탭을 열면, 새로 열린 탭(사이트 B)은 window.opener 라는 javascript 객체를 통해 원래 탭(사이트 A)에 접근할 수 있는 권한을 가진다.
악성 사이트의 B의 스크립트는 이 window.opener 라는 객체를 사용하여 다음과 같은 코드를 실행할 수 있다.
// 악성 사이트 B에서 실행되는 코드
if (window.opener) {
// 원래 탭(사이트 A)의 주소를 공격자가 만든 가짜 로그인 페이지로 변경
window.opener.location.replace('https://fake-login-page.com');
}
이 악성 코드는 원래 사이트 A에 있는 것이 아니라, 사용자가 링크를 클릭해서 새로 열린 악성 사이트 B에 포함되어 있다.
1. 공격자의 미끼 투척
<p>
완전 귀여운 고양이 영상 찾았어요! 꼭 보세요! <br />
<a href="https://attacker-malicious-site.com" target="_blank">
>> 고양이 영상 보러가기 <<
</a>
</p>2. 사용자가 미끼를 물어버림
https://attacker-malicious-site.com (사이트 B)으로 이동합니다3. 악성 코드의 실행
<!DOCTYPE html>
<html>
<head>
<title>귀여운 고양이</title>
</head>
<body>
<h1>진짜 귀여운 고양이 영상</h1>
<img src="cute_cat.gif" alt="귀여운 고양이 움짤" />
<script>
// 페이지가 로드되자마자 이 스크립트가 실행됩니다.
if (window.opener) {
// 1초 후에 원래 탭(opener)의 위치를
// 가짜 로그인 페이지로 바꿔치기합니다.
setTimeout(function() {
window.opener.location.replace('https://fake-siteA-login.com');
}, 1000); // 사용자가 고양이 영상에 정신 팔릴 시간을 줍니다.
}
</script>
</body>
</html>
4. 탭이 납치 당함
window.opener 를 통해 원래 보고 있던 사이트 A 탭의 주소를 공격자의 가짜 로그인 페이지로 바꿔버린다.핵심은, 악성 코드를 "기존 코드" 에 넣는게 아니라 "악성 코드가 포함된 새로운 페이지를 사용자에게 열게 만드는 것" 이 공격의 핵심이다.
이 코드가 실행되면, 사용자가 보고 있던 원래 탭(사이트 A)은 순식간에 공격자가 만든 피싱 페이지로 리디렉션된다. 사용자는 아무런 경고도 받지 못하며, 주소창을 유심히 확인하지 않는 이상 알아차리기 어렵다.
주로 게시글, 또는 덧글 등에서 html 텍스트 에디터를 통해 작성할 수 있도록 개발을 할 수 있다. 이때 에디터에 링크 버튼을 구현해놓았을 때, 보안설정이 걸려있지 않으면 탭내빙 악성공격에 노출당할 수 있을 것이다. 이때, 링크를 여는 <a> 태그에 다음의 속성을 추가하면 100% 방어가 가능하다.
rel="noopener noreferrer"
탭 내빙 공격은 전적으로 window.opener 라는 js 객체를 통해 이루어진다 이 객체는 새로 열린 탭 B이 자신을 열어준 원래 탭A을 참조하고 제어할 수 있게 하는 연결고리이다.
rel="noopener" 속성의 역할은 이 연결고리를 원천적으로 끊어버리는 것이다. 이 속성이 적용되면 브라우저는 새 탭을 열 때 window.opener 객체를 null로 만든다. 악성 사이트 입장에서는 조종하려던 원래 탭의 주소를 잃어버리는 샘이니, 원래 사이트의 주소를 바꿀 방법이 아예 사라져버린다.
rel="noopener noreferrer"는 원래 탭(A)이 납치되는 것을 막아줄 뿐, 새로 열린 탭(B) 자체가 피싱 사이트인 위험을 막아주지는 못한다.
아래와 같이 공격 시나리오가 변경될 수 있는것이다!
1. 공격자는 탭내빙이 막힌 것을 알고, 그냥 새로 열린 탭 B를 원래 사이트 A와 똑같이 생긴 피싱 사이트로 만든다.
2. 사용자는 이 가짜 사이트에서 아이디와 비밀번호를 입력하여 정보를 탈취당할 수 있다.