웹 보안을 이해하는 첫 걸음, XSS(Cross-site Scripting)
조금이라도 틈이 보이면 공격자는 이를 비집고 들어와 어플리케이션을 망가뜨릴 수 있습니다. 이런 위협을 미리 탐지하고 차단하는 것이 보안인데요. 다행히도 브라우져에는 기본적인 보호 장치가 있어서 웹 어플리케이션을 안전하게 지킬수 있습니다.
이 덕분에 개발을 하면서 보안에 대해서 크게 신경쓰지 않았던 것 같습니다. 만약 브라우져의 보안 매커니즘과 이를 활용한 개발 지식을 잘 이해하고 있다면, 더 좋은 품질의 제품을 만들 수 있을 것이라고 생각합니다.
이번 글에서는 보안 공격 가운데 대표적인 기법인 XSS에 대해 알아보겠습니다.
공격
웹 문서는 기본적으로 정적입니다. HTML로 문서의 내용을 표현하고, CSS로 꾸미죠. 웹 어플리케이션이라고 부르는 핵심에는 자바스크립트의 역할이 큰데요. 돔(DOM)을 제어하고, 서버와 통신하기 위해 HTTP 요청 보내는 등, 웹을 "동적으로" 만드는 거의 모든 역할을 맡고 있기 때문입니다.
그런데 바로 이 동적 특성 때문에 문제가 생길 수도 있어요. 소프트웨어가 의도하지 않은 방식으로 동작하게 만들 여지가 생기기 때문이죠. 예를 들어, 사용자가 폼에 이런 문구를 입력한다면 어떻게 될까요?
"<script>alter('bump')</script>"
겉보기에는 단순한 텍스트처럼 보이지만, 브라우져는 이를 단순한 문자열이 아니라 실행 가능한 자바스크립트 코드로 이해합니다. 만약 이 값이 검증되지 않고 웹 페이지에 삽입된다면, 우리가 의도하지 않았던 코드가 그대로 실행될거에요. 사용자는 화면에서 갑작스러운 알림창을 보게되는데, 다양한 공격의 시작점이 될 수 있습니다.
세니타이즈
자바스크립트를 활용한 공격을 막기 위해서는, 사용자가 입력한 문자에서 위험한 스크립트를 찾아내고 제거해야 하는데요, 이를 "세니타이즈(sanitize)" 라고합니다. '살균처리'라는 의미로, 신뢰할 수 없는 코드나 데이터를 제거해서 웹 페이지가 안전하게 동작하도록 만드는 과정을 말해요.
대표적인 도구가 바로 DOMPurify인데요, 플레이그라운드에서 아래 코드를 입력하면, 이 라이브러리가 렌더링에 안전한 문자만 남기고, 위험한 스크립트를 모두 제거할 겁니다.
"text <script>alert('bomb!!!')</script>"
이스케이프
자바스크립트 뿐만 아니라 HTML 코드를 입력하는 것도 공격이 될 수 있어요.
"<h1>Bomb!!!</h1>"
사용자가 폼에 이 텍스트를 입력한다면, 렌더링 과정을 통해 다른 문자와 달리 크고 굵게 표시될 거에요. 개발자가 의도하지 않은 디자인으로 보이는 거죠. 폼을 통해 비정상적인 코드를 주입한 공격입니다.
어플리케이션 측면에서 보면 사용자가 입력한 데이터를 그대로 보여주는 것이 맞긴 합니다. 하지만 개발자는 사용자가 HTML이나 스크립트 코드까지 입력할 것이라고는 기대하지는 않았을 거에요. 이런 상황에서는 사용자가 입력한 문자를 마크업으로 해석하지 않고 텍스트로만 표시하는 것이 안전합니다.
이스케이프(escape)는 원래 '도망치다', '따돌리다'라는 뜻을 갖는데요. 브라우져가 특정 문자나 태그를 해석하지 못하도록 안전한 형태로 변환하는 기법을 의미합니다. 즉, 브라우져가 위험한 문자를 잘못 처리하지 않도록 그 해석을 우회하게 만드는 것이죠.
"<" → "<"
">" → ">"
이러한 변환 작업을 통해 브라우저는 사용자가 입력한 값을 HTML 태그나 스크립트로 해석하지 않고, 텍스트 그대로 렌더링할 수 있습니다.
Lodash 라이브러리의 escape 같은 함수를 이용하면, 사용자 입력값을 브라우져 렌더링에 안전한 텍스트로 변환할 수 있습니다.
다른 공격의 기점이 된다
소개한 두 가지 공격은, HTML 문서를 제공한 곳과 다른 출처(Cross-Site)에서 만든 스크립트(Script)가 실행되는 데서 비롯됩니다.
웹 페이지가 신뢰할 수 없는 입력 값 - 여기서는 사용자가 입력한 스크립트 - 을 그대로 처리하게 되면, 애플리케이션 의도와 무관하게 악성 코드가 주입될 수 있죠. 이런 취약점을 악용한 공격을 크로스 사이트 스크립팅(Cross-Site Scripting), 줄여서 XSS라고 부릅니다.
XSS는 단순히 스크립트 한 줄이 실행되는 수준에서 그치지 않습니다. 이것을 발판 삼아 2차, 3차 공격으로 이어질 수 있다는 점에서 중요한데요. 사용자의 브라우저 환경을 직접 공격할 수 있다는 점에서 웹 개발자는 반드시 이해하고 있어야 합니다.
정리
XSS를 기반으로한 공격은 외부 코드를 처리하는 것만으로는 충분하지 않습니다. 콘텐츠 보안 정책(CSP), 쿠키 설정(HttpOnly, Secure, SameSite) 등의 브라우져의 보안 정책 뿐만 아니라, HTTP의 보안 속성까지 잘 이해하고 있어야만 우리의 애플리케이션을 안전하게 보호할 수 있습니다.
---
이 외에도 웹 개발에서 자주 등장하는 CORS, HTTPS 등의 주요 보안 기술 대해 깊이 이해하고 싶으시다면, 제가 준비한 강의 「웹 개발의 핵심, HTTP 완벽 가이드」 5편을 참고하시면 도움이 될 것입니다.
이 강의에서 다루는 내용
1편. HTTP 기본
2편. 브라우져
3편. AJAX
4편. 추가 프로토콜
5편. 보안
6편. 성능
댓글을 작성해보세요.