The reverse tabnabbing has weakened more

Reverse tabnabbing은 리스크가 높은 공격은 아니지만 피싱에서 충분히 사용될 수 있기 때문에 보안을 조금 더 신경쓴다면 분명이 체크하고 가야할 부분입니다. 해당 공격에 대한 설명은 아래 링크를 참고해주세요.

https://www.hahwul.com/cullinan/reverse-tabnabbing/

이 공격에 관련하여 최근에 변화가 있었고 제가 여러모로 정신이 없다보니 놓치고 있었네요 😭 오늘은 글로 정리하면서 Reverse tabnabbing에 어떤 변화가 있는지 가볍게 설명드리려고 합니다.

Attack mechanism

위에 링크에서 설명해두긴 했지만, reverse tabnabbing에 대해 간단히 이야기하자면 특정 조건에서 a, iframe 및 window.open() 등으로 생성된 child page가 parents page를 일부 제어할 수 있는 특성을 이용해 피싱 사이트로 parents page를 변경하는 취약점을 의미합니다. 여기서 말하는 특정 조건이란 앵커태그에서 target=_blank 와 같이 parents와 child가 연결된 경우를 의미합니다.

그래서 보통은 a, iframe등을 걸수 있거나 src 주소의 소유주체를 가진 경우, 그리고 target=_blank인 경우 취약하다고 이야기하죠.

example of poc

<a href="https://www.hahwul.com/phoenix/reverse-tabnabbing-1" target="_blank">Click me</a>

Old default of rel

파폭,크롬,사파리 모두 reverse tabnabbing 공격에 대한 대응 방안은 있었지만 그게 기본값으로 가져가진 않았었습니다. 그래서 새로 열린 창과 부모창 간의 연결을 제거하기 위해 rel=noopener 등을 통해서 child page에서 opener를 사용할 수 없도록 제한합니다.

Example of poc(child page)

<script>
  window.opener.location.href="https://www.hahwul.com/phoenix/reverse-tabnabbing-2"
</script>

rel=noopener가 걸려있다면 위와 같은 child page에서 opener를 사용할 수 없게 되지요.

Changed default of rel

Safari, Firefox가 먼저 시행되었고 가장 늦은 Chrome이 88 상위 버전부터 rel=noopener가 default 값으로 변경되었습니다.

Anchor target=_blank implies rel=noopener

To mitigate "tab-napping" attacks, in which a new tab/window opened by
a victim context may navigate that opener context, the HTML standard
changed to specify that anchors that target _blank should behave as if
|rel="noopener"| is set. A page wishing to opt out of this behavior may
set |rel="opener"|.

https://chromium-review.googlesource.com/c/chromium/src/+/1630010

그래서 태그에서 rel="opener" 로 직접 opener를 명시하지 않는한 기본적으론 noopener로 동작하게 되며 이는 많은 reverse tabnabbing이 무의미해진다는 것을 의미합니다. (최소 tag의 attribute를 제어할 수 있는 상황이거나, rel=opener가 명시된 경우만 유효하겠죠. 물론 저렇게 명시하며 사용할정도면 이 위험성에 대해 알고 있을 가능성이 높구요)

이제 안전한가요?

당연히 아닙니다. 그저 서비스에서 사용되는 별도의 제한없는 태그의 경우 거의 다 방어가 되겠지만 게시판, 메일 등 사용자가 HTML 코드를 사용할 수 있는 환경에선 여전히 유효한 취약점입니다. 다만 예전보다는 공격의 범위가 엄청나게 줄어든건 사실입니다. rel=opener와 사용자가 컨트롤 할 수 있는 부분들만 잘 체크해도 되겠네요 :D