Tabnabbing 악성 공격

eeensu·2026년 1월 26일

Javascript

목록 보기
42/44

개념

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. 공격자의 미끼 투척

  • 공격자는 평범한 웹사이트 A(커뮤니티 게시판, 블로그 등)에 글을 작성한다.
  • 이 글 안에 교묘한 링크를 포함시킨다. 예를 들어, "재미있는 고양이 동영상 보기" 같은 텍스트에 자신의 악성 사이트 B로 연결되는 링크를 건다.
  • 이 링크는 다음과 같이 되어있을 것이다.
    <p>
      완전 귀여운 고양이 영상 찾았어요! 꼭 보세요! <br />
      <a href="https://attacker-malicious-site.com" target="_blank">
        >> 고양이 영상 보러가기 <<
      </a>
    </p>

2. 사용자가 미끼를 물어버림

  • 사용자는 사이트 A에서 이 링크를 보고 무심코 클릭한다.
  • 브라우저는 새 탭을 열고 https://attacker-malicious-site.com (사이트 B)으로 이동합니다

3. 악성 코드의 실행

  • 이제 브라우저는 공격자가 만든 사이트B의 코드를 읽고 실행하기 시작한다.
  • 공격자는 바로 이 사이트B의 HTML 파일 안에 악성 js코드를 넣는것이다.
<!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. 탭이 납치 당함

  • 사용자는 새 탭에서 귀여운 고양이를 보며 잠시 정신이 팔릴 것이다. (고양이는 못참지..)
  • 그 1초 사이에, 사이트B에서 실행된 js 코드가 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. 사용자는 이 가짜 사이트에서 아이디와 비밀번호를 입력하여 정보를 탈취당할 수 있다.

또한, 만약 사이트에 XSS 취약점이 있다면, 공격자는 `rel` 속성이 안전하게 적용된 링크를 클릭하는 순간에 js로 조작하여 `rel` 속성을 제거하고 악의적인 동작을 추가할 수도 있습니다. 물론 이것은 탭내빙과는 별개의 보안 취약점이지만, 여러 공격이 연계될 수 있다는 점을 인지해야 한다,
profile
안녕하세요! 프론트엔드 개발자입니다! (2024/03 ~)

0개의 댓글