최근 들어 개발의 편의성을 위해 다양한 프론트엔드 프레임워크를 사용하는 추세이다. 프레임워크를 사용하면 DOM 내의 데이터를 수정하기에 간편하고, 웹 페이지를 컴포넌트화 하여 작성할 수 있기 때문에 개발하는데에 있어서 굉장히 편리해진다. 보편적으로 사용되는 프레임워크의 종류로 Vue, React, AngularJS 등이 존재한다.
Client Side Template Injection은 이용자의 입력 값이 Client Side Template Framework에 의해 템플릿으로 해석되어 렌더링될 때 발생한다. 개발의 편의성을 높여주는 프레임워크지만 잘못된 방식으로 사용할 경우, 이를 통해 XSS 취약점까지 연계하는 것이 가능하다.
Vue 혹은 Vue.js라고 불리는 프론트엔드 프레임워크는 2014년 출시된 프레임워크이며, Google의 한 연구원인 Evan You가 개발하였다. Vue는 오픈소스 자바스크립트 프레임워크로, 이용자 인터페이스나 Single Page Application을 빌드할 때 사용된다. Vue에 대한 상세한 정보는 https://vuejs.org/에서 확인할 수 있다.
<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 템플릿 부분이다. 해당 템플릿 내에서 문자열을 표기하거나, 자바스크립트 표현식을 실행할 수 있다. 만약 여기서 템플릿 내부에 공격자의 입력이 들어가 Template Injection 취약점이 발생한다면, XSS 공격으로 이어질 수 있다.
아래 코드는 이용자의 입력을 그대로 페이지에 출력하여 Vue Template Injection에 취약한 예제 소스코드이다.
<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이 발생한다.
Vue Template Injection이 발생하는지 확인하는 간단한 방법은 템플릿을 이용해 산술 연산을 수행해보는 것이다. {{1+1}}과 같은 산술 연산 형태의 템플릿을 입력했을 때, 연산이 실행된 형태인 2가 출력된다면 Template Injection이 발생하는 것으로 확인할 수 있다.

Template Injection이 발생할 때 이를 임의 자바스크립트 코드 실행으로 연계하는 방법으로 보통 생성자 (constructor)를 이용한다. Vue 템플릿 컨텍스트 내에서 생성자에 접근하여 임의 코드에 해당하는 함수를 생성하고, 이를 호출하는 방식으로 XSS 공격이 가능하다.