Client Side Template Injection
1. 서론
Client Side Template Injection은
이용자의 입력값이
client side template framework에 의해
템플릿으로 해석되어
렌더링될 때 발생한다.
개발의 편의성을 높여주는 프레임워크지만
잘못된 방식으로 사용할 경우,
XSS 취약점까지 연계하는 것이 가능하다.
2. Client Side Template Injection
2-1 Vue - Vue.js
오픈소스 자바스크립트 프레임워크로
이용자 인터페이스나
Single Page Application을 빌드할 때 사용된다.
Figure 1. Vue 예제
<script src="https://unpkg.com/vue@3"></script>
<div id="app">{{ message }}</div>
<script>
Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
{{ }}로 감싸진 부분이
Vue 템플릿 부분이다.
해당 템플릿 내에서
문자열을 표시하거나
자바스크립트 표현식을 실행할 수 있다.
Figure 2. 취약한 Vue 예제
<script src="https://unpkg.com/vue@3"></script>
<div id="app">
<?php echo htmlspecialchars($_GET['msg']); ?>
</div>
<script>
Vue.createApp({
data() {
return {
message: 'Hello Vue!'
}
}
}).mount('#app')
</script>
입력받은 GET 메소드의 msg 파라미터를
그대로 출력하지만,
htmlspecialchars 함수를 통해
꺽쇠 문자가 모두 인코딩되기 때문에
일반적인 XSS 공격은 불가능하다.
하지만 출력되는 값이
Vue의 템플릿으로 사용될 수 있기 때문에
Template Injection이 발생한다.
2-2 Vue Template Injection
Vue Template Injection이
발생하는지 확인하는 간단한 방법은
템플릿을 이용해 산술 연산을 수행해 보는 것이다.
{{1+1}} 템플릿을 입력했을 때 2가 출력된다면
Template Injection이 발생하는 것으로 확인할 수 있다.
Template Injection이 발생할 때
이를 임의 자바스크립트 코드 실행으로 연계하는 방법으로
보통 생성자 (constructor)를 이용한다.
Vue 템플릿 컨텍스트에서 대표적으로
{{_Vue.h.constructor}}를 이용해 접근할 수 있다.
Figure 4. Vue Template Injection 공격
{{_Vue.h.constructor("alert(1)")()}}
2-3 Angular JS
Angular JS는
타입스크립트 기반의 오픈소스 프레임워크이며
CLI 도구에서 다양한 기능을 제공하기 때문에
개발을 편리하게 해주는 프레임워크 중 하나이다.
Figure 5. Angular JS 예제
<!doctype html>
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<div>
<label>Name:</label>
<input type="text" ng-model="yourName" placeholder="Enter a name here">
<hr>
<h1>Hello {{yourName}}!</h1>
</div>
</body>
</html>
Vue와 마찬가지로
{{ }}로 감싸진 부분이 AngularJS 템플릿 부분이며,
해당 템플릿 내에서
문자열을 표시하거나,
자바스크립트 표현식을 실행할 수 있다.
Figure 6. Angular JS 취약한 예제
<!doctype html>
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
</head>
<body>
<?php echo htmlspecialchars($_GET['msg']); ?>
</body>
</html>
2-4 Angular Template Injection
Vue와 마찬가지로
산술 연산이 실행된 결과가 출력되는지의 여부로
Template Injection을 탐지할 수 있다.
AngularJS 템플릿에서
생성자에 접근하기 위해서는
{{ constructor.constructor }}로 접근할 수 있다.
Figure 7. Angular Template Injection 공격
{ constructor.constructor("alert(1)")() }}
3. 정리
Client Side Template Injection은
꺽쇠와 같은 특수문자가 필터링 되었더라도
XSS로 연계할 수 있어 파급력이 높은 취약점이다.
프론트엔드 프레임워크를 이용할 때에는
반드시 production mode로 코드를 빌드하여 사용하고,
이용자의 입력이 템플릿으로 인식되지 않도록 유의하여야 한다.