2003
[WEB] CSTI(Client Side Template Injection) 취약점 본문
프론트엔드 프레임워크
- 다양한 개발의 편의성 제공
- DOM 내의 데이터를 수정하기에 간편
- 웹 페이지를 컴포넌트화 하여 작성할 수 있음
- Vue, React, AngularJS
Client Side Template Injection
- 사용자의 입력 값이 client side template framework에 의해 템플릿으로 해석되어 렌더링 될 때 발생함
- 이를 악용하여 악성 스크립트를 실행하거나 사용자의 브라우저에서 다른 액션을 취하도록 유도할 수 있음
Vue
- 사용자 인터페이스를 위한 JavaScript 프레임워크
- 리액티브 데이터 바인딩: 데이터와 UI 간의 동적인 바인딩을 통해 데이터의 변경에 따라 UI가 자동으로 업데이트됨
- 컴포넌트 기반 아키텍처: UI를 독립적인 컴포넌트로 나누어 재사용성이 높고 유지보수가 용이
- 가상 DOM: 변화를 추적하고 최소한의 DOM 조작만을 수행하여 성능을 향상
- 단순성과 유연성: 핵심 라이브러리의 크기가 작고 배우기 쉬움
<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>
취약한 Vue 예제
- 이용자로부터 입력받은 GET 메소드의 msg 파라미터를 그대로 출력하지만, htmlspecialchars 함수를 통해 꺽쇠 문자가 모두 인코딩되기 때문에 일반적인 XSS 공격은 불가능
- 하지만 출력되는 값이 Vue의 템플릿으로 사용될 수 있기 때문에 Template Injection이 발생
아래 사이트에서 실습해 볼 수 있습니다.
https://vue-client-side-template-injection-example.azu.vercel.app/
https://vue-client-side-template-injection-example.azu.vercel.app/
Hello ?name=undefined Source Code
vue-client-side-template-injection-example.azu.vercel.app
const express = require('express');
const helmet = require('helmet');
const escapeHTML = require('escape-html');
const app = express();
app.use(helmet());
app.get('/', (req, res) => {
res.set('Content-Type', 'text/html');
const name = req.query.name
res.status(200).send(`<!DOCTYPE html>
<html>
<body>
<div id="app">
<h1>Hello ?name=${escapeHTML(name)}</h1>
</div>
<footer>
<a href="https://github.com/azu/vue-client-side-template-injection-example">Source Code</a>
</footer>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.13/dist/vue.js"></script>
<script>
new Vue({
el: '#app'
});
</script>
</body>
</html>`);
});
module.exports = app;
Payload
Vue 템플릿 컨텍스트 내에서 생성자에 접근하여 XSS 실행 가능
{{_openBlock.constructor('alert(1)')()}} /* v3 */
{{constructor.constructor('alert("CSTI XSS")')()}} /* v2 */
- _openBlock.constructor 및 this.constructor.constructor를 통해 Function 객체의 생성자 함수에 접근하고, 이를 이용하여 새로운 함수를 생성함
- 생성된 함수를 호출하여 alert("1")을 실행함
- https://portswigger.net/web-security/cross-site-scripting/cheat-sheet#vuejs-reflected 여기서 더 많은 페이로드 참고 가능
AngularJS
Google에서 개발한 오픈 소스 프론트엔드 웹 애플리케이션 프레임워크
HTML, CSS 및 JavaScript를 사용하여 동적인 웹 애플리케이션을 빌드하는 데 도움이 되는 많은 기능을 제공
- MVVM 아키텍처 사용
- 데이터 바인딩: 양방향 데이터 바인딩을 제공하여 모델과 뷰 간의 실시간 데이터 동기화 가능
- 지시자(Directives): HTML의 새로운 구문을 만들어 추가적인 기능을 제공함. ng-app, ng-model, ng-repeat 등의 지시자를 사용하여 HTML에 AngularJS의 동작을 정의 가능
- 의존성 주입(Dependency Injection): 의존성 주입을 지원하여 애플리케이션의 컴포넌트 간의 의존성을 관리하고 결합도를 낮추어 코드의 재사용성을 높이고 테스트하기 쉽게 만듦
- 루트 모듈 및 컴포넌트 기반 개발: 애플리케이션이 모듈과 컴포넌트로 구성되어 이를 조합하여 복잡한 애플리케이션을 구축
<!doctype html>
<html ng-app>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.3/angular.min.js"></script>
</head>
<body>
<?php echo htmlspecialchars($_GET['msg']); ?>
</body>
</html>
취약한 AngularJS 예제
- 이용자로부터 입력받은 GET 메소드의 msg 파라미터를 그대로 출력
- htmlspecialchars 함수를 통해 꺽쇠 문자가 모두 인코딩되기 때문에 일반적인 XSS 공격은 불가능
- 출력되는 값이 AngularJS의 템플릿으로 사용될 수 있기 때문에 Template Injection이 발생
Payload
{{constructor.constructor('alert(1)')()}}
{{'a'.constructor.prototype.charAt=[].join;$eval('x=alert(1)');}}
- constructor.constructor를 통해 Function 객체의 생성자 함수에 접근하고, 이를 이용하여 새로운 함수를 생성함
- 생성된 함수를 호출하여 alert("1")을 실행함
- 꺾쇠와 같은 특수문자가 필터링 되어 있어도 XSS 공격이 가능한 것을 알 수 있음
더 많은 페이로드 참고: https://gist.github.com/mccabe615/cc92daaf368c9f5e15eda371728083a3
'보안 > WEB' 카테고리의 다른 글
| [Wargame] Dreamhack Relative Path Overwrite Advanced (0) | 2024.04.03 |
|---|---|
| [Wargame] Client Side Template Injection (0) | 2024.04.02 |
| [Wargame] Dreamhack CSRF Advanced (0) | 2024.02.16 |
| [Wargame] CSP Bypass Advanced (0) | 2024.02.14 |
| [WEB] SSTI(Server-Side Template Injection) 취약점 - Jinja2 (1) (0) | 2024.02.05 |