교차 사이트 스크립팅(Cross-Site Scripting, XSS) 공격은 전자상거래 비즈니스와 다양한 웹 애플리케이션이 직면하는 가장 빈번한 인젝션(injection) 공격 중 하나이면서도, 의외로 쉽게 해결할 수 있는 보안 취약점입니다. 구형 웹 기술로 개발된 애플리케이션부터 풍부한 클라이언트 측 UI를 갖춘 최신 애플리케이션까지, XSS는 모든 종류의 웹 서비스를 위협해 왔습니다. 하지만 다행인 점은, XSS 공격의 원인이 되는 잠재적 취약점은 비교적 쉽게 탐지하고 적시에 수정할 수 있다는 사실입니다.
교차 사이트 스크립팅(XSS) 공격은 어떻게 발생하나?
교차 사이트 스크립팅(XSS) 공격은 다음 두 가지 조건이 충족될 때 발생합니다.
- 웹 애플리케이션이 신뢰할 수 없는 소스로부터 입력 데이터를 받아들이는 경우
- 웹 요청을 통해 입력된 동적 콘텐츠가 악성 코드 포함 여부를 검증하지 않은 채 사용되는 경우
가장 단순한 예로, 폼(form)에 이름, 이메일 주소, 아이디·비밀번호 등을 입력하는 상황을 들 수 있습니다. 이러한 입력값들은 내부 코드가 제대로 검증하지 않으면 모두 조작될 수 있습니다. 공격자는 이러한 검증 미비를 이용해 일반적으로 자바스크립트(JavaScript), HTML 등 브라우저에서 실행 가능한 형태의 악성 코드를 삽입합니다. 최종 사용자는 신뢰할 수 없는 스크립트임을 알아차릴 방법이 없어 결국 해당 코드를 실행하게 되고, 한 번 삽입되면 스크립트는 해당 사이트가 사용하는 쿠키, 세션 토큰 또는 민감한 정보에 접근할 수 있게 됩니다.
XSS 공격은 크게 3가지 유형으로 나뉩니다:
- DOM 기반 공격(DOM Based Attack): 클라이언트 측에서 악성 코드가 삽입되어 발생합니다. 삽입되는 코드는 자바스크립트, 플래시, 비주얼 베이직 등 다양할 수 있습니다.
- 저장형 XSS 공격(Persistent XSS Attack): 악성 페이로드(payload)가 서버 측에 저장되고, 사용자가 해당 페이지를 요청할 때마다 불러와져 실행되는 방식입니다.
- 반사형 XSS 공격(Non-Persistent XSS Attack): 조작된 입력값이 포함된 링크를 통해 취약한 웹사이트에 접속하면, 페이로드가 그대로 사용자에게 반사되어 실행되는 방식입니다.
교차 사이트 스크립팅(XSS) 공격의 구조
공격자는 어떻게 XSS를 악용하는가?
일반적으로 공격자는 XSS 취약점을 이용해 최종 사용자의 세션 쿠키를 탈취하고, 이를 통해 사용자의 계정에 무단으로 접근합니다. 대표적인 시나리오는 다음과 같습니다:
- 사용자가 접속한 웹사이트에 댓글 입력란이 존재합니다.
- 공격자가 댓글 영역에 악성 페이로드를 게시합니다.
- 정상적인 사용자가 해당 댓글을 열어보는 순간, HTML이 이 스크립트를 파싱(parsing)합니다.
- 브라우저가 HTML 파싱을 수행하면, 사용자의 쿠키가 공격자의 서버로 전송됩니다.
이처럼 단순해 보이는 취약점이라도 웹 애플리케이션에 존재할 경우 매우 심각한 결과를 초래할 수 있습니다. 또 다른 흔한 XSS 악용 사례는 드라이브바이 다운로드(drive-by download) 공격입니다. 공격자가 정상적으로 보이는 링크를 클릭하도록 유도해, 사용자가 자신도 모르는 사이에 멀웨어를 다운로드하게 만드는 방식입니다.
악명 높은 교차 사이트 스크립팅 공격 사례
XSS 공격은 대부분 금전적 이득을 노리고 발생합니다. 대표적인 사례로 전자상거래 거대 기업 이베이(eBay)에 대한 과거 공격을 들 수 있습니다. 해커들은 저렴한 아이폰 판매 게시물 여러 곳에 악성 자바스크립트 코드를 삽입했고, 이를 통해 사용자들을 가짜 로그인 페이지로 리디렉션하여 계정 정보를 탈취했습니다.
전자상거래 사이트뿐만 아니라 여러 소셜 미디어 플랫폼도 이러한 악명 높은 공격의 표적이 되었습니다. 트위터(Twitter)는 'StalkDaily'라는 사이트로 악성 링크를 확산시키는 XSS 웜의 공격을 받았습니다. 또한 잘 알려진 사례로 마이스페이스(MySpace)를 노린 '새미 웜(Samy Worm)' 공격이 있는데, 이는 사용자 프로필 페이지를 변조하고 무작위 친구 요청을 대량 발송한 비교적 무해한 형태의 바이러스였습니다.
XSS 공격을 완화하기 위한 예방 조치
XSS 공격을 예방한다고 해서 사용자의 입력 자체를 차단해야 하는 것은 아닙니다. 핵심은 입력값이 브라우저에서 HTML로 파싱되어 실행되지 않도록 하는 것입니다. 다음은 XSS 공격을 방지하기 위해 널리 활용되는 주요 방법론입니다.
-
입력값 검증(Input Validation)
XSS를 방지하려면 대부분의 입력값에 대해 화이트리스트(white-list) 방식으로 검증하여 영숫자 또는 필요한 경우에 한해 특수 문자만 허용해야 합니다. 이를 통해 공격 표면을 줄이고 버그 발생 가능성을 최소화할 수 있습니다.
-
안전한 DOM 요소 사용
DOM(문서 객체 모델) 요소를 안전하지 않게 처리하면 풍부한 클라이언트 UI에서도 XSS 공격이 발생할 수 있습니다. 예를 들어 innerHTML 속성을 사용하면 사용자 입력이 자바스크립트 이벤트와 함께 실행되어 XSS로 이어질 수 있습니다. 이 경우에는 textContent나 innerText 같은 안전한 대안을 사용하는 것이 좋습니다.
-
자바스크립트 이스케이핑(JavaScript Escaping)
작은따옴표(')를 이스케이프 처리하면 자바스크립트 내부로의 코드 삽입을 방지할 수 있습니다. 작은따옴표를 '와 같은 HTML 엔티티로 인코딩하여 사용함으로써 코드 삽입 문제를 예방해야 합니다.
-
출력 인코딩(Output Encoding)
출력 인코딩은 대다수의 XSS 페이로드를 무력화하는 데 매우 효과적인 방법으로, 서버 측 인젝션 공격을 완화하는 데 활용됩니다. HTML 인코딩이 가장 널리 쓰이는 방식이며, URL 인코딩은 링크 및 리디렉션에 삽입되는 마크업 기반 공격을 차단하는 데 도움이 됩니다.