프론트엔드 프레임워크의 보안은 프레임워크와 프레임워크가 의존하는 기본 언어를 모두 커버하기 때문에 매우 광범위할 수 있다. 이 글에서는 애플리케이션을 취약하게 하는 vue 구현에 대해 설명한다.
TL;DR
- vue 또는 기타 프론트엔드 프레임워크를 사용할 때 가장 기본적인 보안 규칙은 신뢰할 수 없는 콘텐츠를 컴포넌트 템플릿으로 사용하지 않는 것이다.
- 어떤 웹 애플리케이션이든 HTML, CSS 또는 자바스크립트로 검증되지 않은 사용자 제공 입력을 실행하는 것은 위험할 수 있으므로 가능한 한 피해야 한다.
1. HTML Content Injection
VueJS는 원시 HTML을 렌더링 하기 위한 디렉티브 v-html를 제공한다. 디렉티브는 Vue에 의해 제공되는 특별한 속성이다. 임의의 HTML을 동적으로 렌더링 하면 XSS 취약성으로 이어지기 쉽기 때문에 매우 위험하다.
1-1) HTML Content Injection 사례
사용자가 제공한 데이터가 검증 없이 v-html 디렉티브에 허용되는 경우 공격자가 자바스크립트 또는 HTML을 포함한 공격 페이로드를 입력할 수 있다. 이로 인해 XSS가 발생할 수 있다.
1-2) 해결방안
v-html를 사용하여 사용자가 제공하는 원시 HTML을 렌더링 하면 않는다. 대신 다음 중 하나를 사용한다.
- VueJS 엔진에서 제공되는 v-text 또는 {{}}을(를) 사용한다.
- 또는 사용자 지정 검증을 만들거나 알려진 라이브러리를 사용하여 사용자 입력을 삭제한다. 잘 알려진 라이브러리의 좋은 예는 DOMPurify이다.
2. URL Injection
VueJS에서는 다음과 같이 href 속성을 바인딩하여 링크를 추가할 수 있다. v-pref:href="url" 또는:href="url". 여기서 문제는 사용자가 지정한 URL에 잘못된 리디렉션이 포함되어 있거나 자바스크립트가 내장되어 있을 수 있다는 것이다.
2-1) URL Injection 사례
공격자는 임의의 외부 도메인으로 리디렉션 하는 URL을 애플리케이션에 구축하여 입력할 수 있다. 이 동작을 이용하면 애플리케이션 사용자에 대한 피싱 공격을 용이하게 할 수 있다.
웹 애플리케이션에 URL이 표시되어 있는 경우 공격자는 자바스크립트를 URL에 추가하여 Reflected XSS를 발생시킬 수도 있다.
2-2) 해결방안
사용자가 지정한 URL을 웹 애플리케이션에 렌더링 하지 않는다.
사용자 지정 URL을 사용할 경우 사용자 지정 URL 검증을 만들거나 well-known 라이브러리를 사용하여 URL을 지울 수 있다. 이에 적합한 라이브러리는 sanitize-url이다. 공격자가 자신의 클라이언트를 사용하여 프론트엔드 검증을 우회할 수 있다는 점에 주의해야 한다. 따라서 URL을 데이터베이스에 저장하기 전에 항상 백엔드로 sanitize 하는 것이 중요한 것은 URL을 데이터베이스에 저장하는 것이다.
3. Style Injection
악의적인 사용자는 : style 속성 내의 "clickjack"에 CSS를 제공할 수 있다. UIrecareattack이라고도 불리는 Clickjacking은 유저가 실제로 다른 것을 클릭하고 있을 때, 어떤 것을 클릭하고 있다고 믿게 하는 공격이다. 사용자는 웹 페이지의 일반 UI를 사용한다고 생각하지만 실제로 컨트롤에는 숨겨진 UI가 있다. 사용자가 안전하다고 생각하는 것을 클릭하면 숨겨진 UI는 다른 액션을 수행한다.
3-1) 사례
공격자는 background: URL()과 같은 스타일로 Clickjack URL을 전달할 수 있다. URL에는 애플리케이션의 실제 페이지와 유사한 투명한 iframe이 포함되어 있을 수 있으므로 폼 입력 캡처에 사용할 수 있다. 예를 들어 공격자가 로그인 사용자 이름과 암호를 캡처할 수 있는 로그인 양식에서 사용하는 경우 이는 위험할 수 있다.
3-2) 해결방안
sandbox iframe 내에서 사용자가 지정한 CSS만 완전히 제어할 수 있도록 해야 한다.
또는 스타일 바인딩을 통해 사용자 제어를 제공하는 경우 VueJS 객체 구문을 사용하여 사용자가 안전하게 제어할 수 있는 특정 속성의 값만 제공할 수 있다.
'development' 카테고리의 다른 글
[Nuxt] Template not found: /node_modules/@nuxtjs/google-adsense/dist/templates/plugin.mjs (0) | 2023.01.01 |
---|---|
셸(Shell)과 터미널(Terminal) 차이 (0) | 2022.12.13 |
k8s - 이스티오(Istio) 정리 #2 (0) | 2022.12.04 |
k8s - 이스티오(Istio) 정리 #1 (0) | 2022.12.04 |
프론트엔드, 리액트 면접 인터뷰 (0) | 2022.12.03 |