<a> 태그 "target=_blank" 와 rel="noreferrer noopener"

    반응형

    a태그

     

    React로 개인 수익형 웹페이지를 만드는 프로젝트를 진행하던 중에 유튜브, 블로그와 같은 외부 페이지에 접근하기 위해 <a> 태그를 사용했다. 리액트 애플리케이션 외부의 리소스로 이동하는 것이기 때문에 <a> 태그를 사용했는데 기존의 리액트 애플리케이션은 유지한 채 새로운 창이 뜨길 바랬고 속성값으로 "target=_blank" 값을 주었는데 경고 메세지가 출력됐다. 놓치고 있던 부분이었기 때문에 공부하고 정리하려고 한다.

     

    <a> 태그


    <a> 태그는 다른 페이지로 연결하는 데 사용되는 하이퍼링크를 정의하는 태그로 여러 속성값을 가진다. 여러 속성 값 중 target 속성값을 통해 href 속성값으로 지정된 링크를 여는 위치를 결정할 수 있다. 

     

    taget="_blank"


    <a> 태그의 속성 값으로 target="_blank"를 주게되면 새로운 브라우저 탭이나 창에서 href로 지정된 링크가 열린다. 필자는 이러한 기능으로 필자의 리액트 애플리케이션을 떠나지 않으면서도 새로운 브라우저로 다른 컨텐츠에 접근할 수 있도록 사용자 경험을 만들기 위해 사용했는데 아래와 같은 경고 메세지가 출력되었다.

    Using target=_blank without rel=noopener noreferrer is a security risk.....

     

    경고가 출력되는 이유


    경고 메세지는 target="_blank"rel="noreferrer noopener" 없이 사용하게 되면 보안상 문제가 생긴다는 것이다. 보안상 문제는 바로 Tabnabbing 피싱 공격이다.

     

    Tabnabbing 피싱 공격은?


    탭내빙이라 불리는 이 피싱공격은 여러 브라우저 탭이나 창을 사용하고 있으면 사용자가 눈치채지 못하는 사이에 사용자가 보고 있던 기존의 탭을 변조하는 공격방식이다. 예를 들어 A페이지에서 <a target="_blank">를 통해 B라는 페이지에 접근하게 되면 기존의 A페이지를 사용자의 정보를 입력받는 페이지로 변환해서 사용자의 정보를 탈취하는 피싱공격이다.

     

    Tabnabbing 피싱 공격 방식

    <!-- index.html -->
    <body>
        <h1>이것은 피해자 페이지입니다.</h1>
        <a href="attacker.html" target="_blank">보안 뉴스 보기</a>
    </body>

     

    <!-- attacker.html -->
    <head>
        <meta charset="UTF-8">
        <title>Attacker Page</title>
        <script>
            window.onload = function() {
                // window.opener를 이용하여 원본 페이지 조작
                if (window.opener) {
                    window.opener.location = './phishing.html'; // 원본 페이지를 가짜 페이지로 변경
                }
            }
        </script>
    </head>
    <body>
        <h1>이것은 공격자 페이지입니다.</h1>
    </body>

     

    <!-- phishing.html -->
    <body>
        <h1>당신의 정보가 필요합니다!</h1>
        <p>로그인하여 계속하기:</p>
        <form action="steal-info.php" method="post">
            <input type="text" name="username" placeholder="사용자명">
            <input type="password" name="password" placeholder="비밀번호">
            <button type="submit">로그인</button>
        </form>
    </body>

     

    예시로 위의 코드와 같은 형식으로 사용자의 정보를 받아오는 공격을 받을 수 있다. 하지만 크롬라우저에서 실행해 본 결과 정상적으로 동작하지 않았는데 그 이유는 기본적으로 최신 브라우저들이 새로운 탭이나 창을 열 때 원본 페이지에 대한 참조를 가지지 못하도록 하기 때문이라고 했다. 그래서 이 기본적인 동작을 확인할 수 있는 좋은 방법은 아래와 같다.

     

    • 브라우저 콘솔 창에서 window.open(url, target, windowFeatures)를 통해 새로운 탭이나 창을 연다.
    • 새롭게 열린 창 혹은 탭의 콘솔 창에서 window.opener.location = "https://www.google.com" 을 실행한다.
    • 이전 부모 창이 구글 창으로 바뀌는 것을 확인할 수 있다.

     

    rel 과 noreferrer, noopener


    위와 같은 방식으로 링크를 통해 사용자의 정보를 가져올 수 있는 공격 방식에 대응하기 위해 noreferrer과 noopener을 사용한다. rel 속성은 링크로 연결된 URL 과의 관계를 정하는 속성이다. 

     

    noopener   

    보안 목적으로 사용되는 값으로 기존에는 링크를 클릭함으로써 window.opener 속성을 이용해 기존의 페이지에 일부 접근할 수 있었고 이를 통해 정보를 탈취할 수 있었다. 하지만 현재는 최신의 브라우저에서는 target="_blank"를 사용할 때 따로 명시 해주지 않아도 rel="noopener"를 적용한 것과 같이 동작한다. 하지만 모든 사용자가 최신의 브라우저를 사용하는 것이 아니기 때문에 noopener을 사용하여 악용을 방지하는 것이 좋다.

     

    noreferrer

    링크를 통해 접근한 페이지에 기존의 정보를 가리는 목적으로 사용한다. 페이지 이동 시에 HTTP 요청 header에 리퍼러(Referer) 정보를 담아 전송하는데 이 리퍼러 정보는 이전 페이지에 대한 정보들이 담겨있다. 이전 페이지의 URL과 혹은 사용자의 정보가 담겨있을 수 있기 때문에 noreferrer를 통해 정보의 노출을 막는다. 

     

    이와 같은 이유로 <a>태그 target 속성값으로 "_blank"를 사용한다면 rel="noreferrer noopener" 을 사용하는 것이 권장된다.

     

    반응형

    댓글