XSS(크로스사이트 스크립팅)의 개념부터 Reflected, Stored, DOM 기반 XSS 공격 유형, 실제 공격 시나리오, HTML 인코딩·CSP 등 대응 방안까지 상세히 설명합니다. Sparrow SAST·DAST로 개발 단계와 운영 환경 전반에서 XSS 취약점을 지속적으로 점검하고 대응하세요.
■ XSS 취약점이란 무엇인가?
XSS(Cross-Site Scripting, 크로스사이트 스크립팅)는 웹 애플리케이션이 사용자 입력값을 적절히 검증하거나 인코딩하지 않을 때, 악성 스크립트가 사용자 브라우저에서 실행되는 보안 취약점입니다.
공격자는 XSS를 통해 사용자의 세션 쿠키를 탈취하거나, 웹 페이지를 변조하는 등 다양한 공격을 수행할 수 있습니다. 과거 OWASP Top 10 Injection 범주에 포함될 만큼 발생 빈도가 높고, 실제로 다수의 CVE에서 보고될 만큼 공격 사례가 풍부합니다.
XSS 공격이 성공하면 공격자가 다음과 같은 행위를 수행할 수 있어 주의가 필요합니다.
🚨 사용자 세션 쿠키 탈취
🚨 웹 페이지 내용 변조
🚨 악성 사이트로의 자동 리다이렉트
🚨 사용자 권한으로 임의 요청 실행
■ XSS 공격 유형 3가지 – Reflected, Stored, DOM 기반 비교
XSS(크로스사이트 스크립팅)는 Reflected XSS, Stored XSS, DOM 기반 XSS로 구분됩니다.
| 구분 | 발생 위치 | 영구성 (악성 스크립트 저장 여부) |
| Reflected XSS |
서버 측(Server-side) 서버가 사용자 입력값을 검증 없이 응답 페이지에 포함시키는 과정에서 발생 |
X (저장되지 않음) |
| Stored XSS |
서버 측(Server-side) 서버가 사용자 입력값을 검증 없이 응답 페이지에 포함시키는 과정에서 발생 |
O (웹 서버 DB에 저장) |
| DOM 기반 XSS |
클라이언트 측(Client-side) 클라이언트(JavaScript)가 사용자 입력값을 DOM에 반영하는 과정에서 발생 |
X (저장되지 않음) |
✅ Reflected XSS 공격 (반사형 XSS) – URL을 통해 즉시 실행
Reflected XSS는 사용자의 입력값이 서버 응답에 즉시 반영되면서 브라우저에서 실행되는 공격입니다. 주로 URL 파라미터, 검색어, 에러 메시지 등이 포함됩니다. 공격자는 악성 스크립트가 삽입된 URL을 이메일이나 메신저로 전달해 클릭을 유도합니다. 해당 URL에 접속하는 순간 스크립트가 실행되며, 세션 쿠키 탈취나 악성 사이트 이동으로 이어집니다.
✅ Stored XSS (저장형 XSS) – 서버(DB)에 저장되어 반복 실행
Stored XSS는 공격자가 입력한 악성 스크립트가 서버(DB)에 저장된 후, 다른 사용자에게 전달되면서 실행되는 공격입니다. 게시판 댓글, 사용자 프로필, 공지사항 입력란 등에서 주로 발생합니다. 한 번의 공격으로 다수 사용자에게 영향을 미치고, 삭제하지 않는 한 계속 실행된다는 점에서 세 가지 유형 중 위험도가 가장 높습니다.
✅ DOM 기반 XSS – 클라이언트 측 스크립트에서 발생
DOM 기반 XSS는 서버 응답이 아니라, 클라이언트 측 JavaScript가 DOM(Document Object Model)을 처리하는 과정에서 발생하는 취약점입니다. 브라우저에서 location, document.URL 등의 값을 통해 직접 참조된 후, innerHTML, document.write, eval 같은 DOM API를 통해 화면에 반영되면서 악성 스크립트가 실행됩니다.
Reflected XSS와 Stored XSS는 서버가 사용자 입력값을 검증 없이 응답 페이지에 포함시키는 과정에서 발생하며, 서버가 생성한 HTML에 악성 스크립트가 포함되어 브라우저로 전달되는 것이 특징입니다. 반면, DOM 기반 XSS는 서버 응답 자체에는 문제가 없지만, 클라이언트(JavaScript)가 사용자 입력값을 DOM에 반영하는 과정에서 발생합니다.
■ XSS 공격 시나리오 예시
⚠️ 사용자 정보 조회 기능에서 발생하는 Reflected XSS
웹 애플리케이션에서 URL 파라미터를 통해 사용자 정보를 조회하고, 해당 값을 화면에 출력하는 기능을 예로 들겠습니다.
▶️ 취약점 원인
사용자 입력값(eid)을 별도의 검증이나 인코딩 없이 그대로 화면에 출력하고 있습니다.
|
<% String eid = request.getParameter(“eid”); %> |
▶️ 정상 동작
사용자가 아래와 같이 요청 시
| https://example.com/profile?eid=12345 |
페이지에는 다음과 같이 출력됩니다.
| Employee ID: 12345 |
▶️ 공격 시나리오
공격자는 eid파라미터에 악성 스크립트를 포함한 URL을 생성합니다.
| https://example.com/profile?eid=<script>alert(document.cookie)</script> |
이 URL을 이메일이나 메신저로 사용자에게 전달하여 클릭을 유도합니다.
▶️ 공격 결과
사용자가 해당 URL에 접속하면, 서버는 입력값을 그대로 포함한 응답을 반환하고 브라우저에서 스크립트가 실행됩니다.
이로 인해 다음과 같은 공격이 가능합니다.
🚨 사용자 쿠키 탈취
🚨 세션 하이재킹
🚨 악성 사이트로 리다이렉트
⚠️ 게시판 댓글에서 발생하는 Stored XSS
게시판에 댓글을 입력하고 조회할 수 있는 기능을 예로 들겠습니다.
▶️ 취약점 원인
사용자가 입력한 댓글이 DB에 저장된 후, 출력 시 별도의 검증이나 인코딩 없이 그대로 렌더링됩니다.
|
<div class=“comment”> |
▶️ 공격 시나리오
공격자는 댓글 입력란에 아래와 같은 악성 스크립트를 삽입합니다. 이 스크립트는 서버 DB에 그대로 저장됩니다.
| <script>alert(‘XSS’)</script> |
▶️ 공격 결과
다른 사용자가 해당 게시글을 조회하면, 서버는 저장된 댓글을 그대로 응답에 포함시키고 브라우저에서 스크립트가 실행됩니다.
이로 인해 다음과 같은 문제가 발생할 수 있습니다.
🚨 다수 사용자에게 동일한 공격 수행
🚨 지속적인 세션 탈취
🚨 웹 페이지 변조
Reflected XSS와 달리, 한 번 저장된 악성 스크립트가 여러 사용자에게 반복적으로 실행된다는 점에서 더 위험합니다.
■ XSS 대응 방안 4가지
XSS(크로스사이트 스크립팅) 취약점은 사용자 입력값이 적절히 처리되지 않을 때 발생하는 만큼, 입력값을 안전하게 다루는 것이 무엇보다 중요합니다. 특히 공격은 대부분 사용자 입력값이 브라우저에서 실행되는 과정에서 발생하기 때문에, 이를 차단하기 위한 다각적인 대응이 필요합니다.
1️⃣ 출력 시 HTML 인코딩
XSS 대응에서 가장 기본이자 중요한 방법은 사용자 입력값을 화면에 출력할 때 HTML 인코딩을 적용하는 것입니다.
웹 애플리케이션은 사용자로부터 전달받은 데이터를 그대로 출력하는 경우가 많은데, 이 과정에서 <, >, &, “와 같은 문자가 포함되어 있으면 브라우저가 이를 HTML 또는 스크립트로 해석할 수 있습니다. 따라서 사용자 입력값을 출력할 때는 아래와 같이 HTML 특수문자를 안전한 문자(Entity)로 변환해야 합니다.
| 원래 문자 | 인코딩 후 |
| < | &It; |
| > | > |
| & | & |
| “ | " |
이와 같은 인코딩 처리를 통해 브라우저가 입력값을 단순한 문자열로 인식하도록 만들어, 악성 스크립트 실행을 방지할 수 있습니다. 인코딩은 입력 단계가 아닌 출력 시점에 적용하는 것이 원칙입니다.
또한 출력 위치(HTML, JavaScript, URL 등)에 따라 적절한 인코딩 방식이 달라질 수 있으므로 상황에 맞는 처리가 필요하며, 단순 필터링이나 일부 문자 치환만으로는 XSS를 완전히 방어할 수 없습니다. 출력 인코딩과 반드시 함께 적용해야 합니다.
2️⃣ 안전한 HTML 처리 (화이트리스트 기반)
게시판, 댓글 기능 등과 같이 HTML 입력이 필요한 경우에는 허용 가능한 태그만 제한적으로 사용하도록 설정해야 합니다. 사용자 입력값에 포함된 HTML은 브라우저에서 그대로 렌더링되기 때문에, <script>, <iframe>, <img onerror>와 같이 스크립트 실행이 가능한 요소가 포함될 경우 XSS 공격으로 이어질 수 있습니다.
따라서 <b>, <i>와 같은 기본적인 서식 태그만 허용하고, 이벤트 핸들러(onclick, onerror 등)나 javascript: 스킴과 같이 스크립트 실행과 관련된 속성은 반드시 제거해야 합니다. 이때 블랙리스트 방식으로 특정 태그를 차단하는 것만으로는 우회가 가능하므로, 허용 가능한 태그와 속성을 명확히 정의한 화이트리스트 기반의 필터링을 적용하는 것이 안전합니다.
또한 HTML을 허용하는 경우에도 출력 시점의 인코딩 또는 안전한 HTML Sanitizer 라이브러리를 함께 적용하여, 허용되지 않은 요소가 실행되지 않도록 추가적인 보호 조치를 수행해야 합니다.
3️⃣ 입력값 검증 및 필터링
입력값 검증은 허용된 데이터만 처리하도록 제한하는 방식으로, XSS를 포함한 다양한 공격을 줄이는 데 도움을 줍니다. 사용자 입력값은 신뢰할 수 없다는 전제하에, 입력값의 길이, 형식, 허용 가능한 문자 등을 사전에 정의하고 이를 만족하는 값만 처리하도록 해야 합니다. 예를 들어, 숫자만 입력되어야 하는 항목에는 숫자만 허용하거나, 이메일·전화번호와 같이 정해진 형식이 있는 경우에는 해당 형식에 맞는 값만 입력받도록 제한할 수 있습니다.
또한, 입력값에 포함된 불필요한 공백이나 제어문자 등을 제거하는 정규화(Normalization) 과정도 함께 고려할 수 있습니다.
4️⃣ CSP(Content Security Policy) 적용
CSP(Content Security Policy)는 브라우저에서 실행 가능한 스크립트의 출처를 제한하는 보안 정책으로, XSS 공격을 완화하기 위한 중요한 보안 메커니즘입니다. 웹 애플리케이션은 HTTP 응답 헤더 또는 메타 태그를 통해 허용된 스크립트의 출처를 정의할 수 있으며, 이를 통해 신뢰되지 않은 외부 스크립트의 로딩이나 실행을 차단할 수 있습니다.
예를 들어, script-src 지시자를 활용하여 특정 도메인에서 제공되는 스크립트만 실행하도록 제한하거나, 인라인 스크립트 실행을 금지함으로써 공격자가 삽입한 스크립트의 실행을 방지할 수 있습니다. 또한 nonce 또는 hash 기반 정책을 적용하면 허용된 스크립트만 선택적으로 실행되도록 제어할 수 있습니다.
다만 CSP는 이미 존재하는 XSS 취약점을 근본적으로 제거하는 방법이 아니라, 공격이 성공하더라도 실행을 제한하는 보완적인 보안 통제 수단입니다. 따라서 CSP는 출력 인코딩과 같은 근본적인 대응 방안과 함께 적용해야 하며, 잘못된 정책 설정 시 정상 기능이 차단되거나 보안 효과가 감소할 수 있으므로 주의가 필요합니다.
■ XSS 공격 대응, 스패로우의 애플리케이션 보안 테스팅 도구와 함께하세요
최근 생성형 AI 기반 코드 작성이 빠르게 확산되면서, 개발 생산성은 크게 향상되고 있습니다. 그러나 동시에 보안 검증이 충분히 이루어지지 않은 코드가 함께 생성될 가능성도 높아지고 있습니다. 특히 XSS와 같은 기본적인 취약점은 작은 입력값 처리 실수로도 쉽게 발생할 수 있어 각별한 주의가 필요합니다. 이러한 환경에서는 개발 단계부터 보안을 고려한 코드 작성과 함께, 취약점을 사전에 식별하고 점검하는 체계적인 접근이 중요합니다.
스패로우는 개발 단계에서 취약점을 조기에 발견하고, 실제 운영 환경에서의 공격 가능성을 검증해 XSS와 같은 웹 취약점에 대응할 수 있는 애플리케이션 보안 테스팅 도구들을 제공합니다.
🔴 소스코드 보안약점 분석 도구, Sparrow SAST
소스코드를 분석하여 사용자 입력값이 적절한 검증이나 인코딩 없이 화면에 출력되는 코드 흐름을 식별할 수 있습니다. 특히, 외부 입력값이 innerHTML, document.write, eval과 같은 위험한 함수나 출력 구문으로 전달되는 패턴을 분석함으로써, XSS로 악용될 수 있는 취약 코드 구조를 개발 단계에서 사전에 탐지할 수 있습니다.
이를 통해 개발자는 입력값 검증 누락이나 출력 인코딩 미적용과 같은 문제를 조기에 발견하고 수정할 수 있으며, XSS 취약점이 실제 서비스에 반영되기 전에 제거하는 데 도움을 받을 수 있습니다.
🟠 웹 애플리케이션 취약점 동적 분석 도구, Sparrow DAST
실제 운영 중인 웹 애플리케이션을 대상으로 다양한 XSS 공격 페이로드를 주입하여, 사용자 입력값이 브라우저에서 실행되는지 여부를 동적으로 검증할 수 있습니다. 이를 통해 Reflected XSS, Stored XSS와 같은 취약점이 실제 공격으로 이어질 수 있는지 확인할 수 있으며, 서버 응답뿐 아니라 브라우저에서의 실행 결과를 기반으로 클라이언트 측 동작까지 고려한 점검이 가능합니다.
Sparrow SAST와 Sparrow DAST를 함께 활용해 개발 단계와 운영 환경 전반에서 XSS 취약점을 지속적으로 점검하고 대응해보세요! 정적 분석을 통한 사전 예방과 동적 분석을 통한 실제 공격 검증을 병행함으로써, 웹 애플리케이션의 보안 수준을 효과적으로 강화할 수 있습니다.
▶️ Sparrow SAST 바로가기 : https://sparrow.im/kr/product/sast/
▶️ Sparrow DAST 바로가기 : https://sparrow.im/kr/product/dast/
FAQ – XSS에 대해 자주 묻는 질문
Q1. XSS란 무엇인가요?
A. XSS(Cross-Site Scripting)는 웹 애플리케이션이 사용자 입력값을 검증하거나 인코딩하지 않을 때, 악성 스크립트가 사용자 브라우저에서 실행되는 취약점입니다. 세션 탈취, 웹 페이지 변조 등의 피해로 이어질 수 있습니다.
Q2. XSS는 어떻게 대응하고 예방하나요?
A. 가장 중요한 방법은 사용자 입력값을 화면에 출력 시 HTML 인코딩을 적용하는 것입니다. 여기에 화이트리스트 기반 안전한 HTML 처리, 입력값 검증 및 필터링, CSP(Content Security Policy) 적용을 병행하면 효과적으로 대응할 수 있습니다. Sparrow SAST와 같은 정적 분석 도구로 개발 단계에서 취약 코드를 탐지하고, Sparrow DAST와 같은 동적 분석 도구로 운영 환경을 점검하는 체계도 갖추는 것이 좋습니다.
Q3. DOM 기반 XSS는 서버 필터링으로 막을 수 없나요?
A. 맞습니다. DOM 기반 XSS는 서버가 아닌 클라이언트 JavaScript 코드에서 발생하기 때문에, 서버 측 필터링만으로는 충분히 방어하기 어렵습니다. innerHTML, eval 등과 같은 위험한 DOM API에 외부 입력값을 그대로 전달할 경우 취약점이 발생할 수 있으므로, 클라이언트 코드에서 안전한 방식으로 DOM을 조작하는 것이 중요합니다. innerHTML 대신 textContent, innerText와 같은 안전한 API를 사용하고 Sparrow SAST와 같은 정적 분석 도구를 활용하여 이러한 취약 코드 패턴을 소스코드 단계에서부터 사전에 탐지하는 것을 권장합니다.
Q4. XSS 공격을 받았는지 어떻게 알 수 있나요?
A. XSS 공격은 사용자 브라우저에서 실행되는 특성상 서버 로그에 명확한 흔적이 남지 않는 경우가 많아, 단순 증상만으로 정확히 식별하기는 어렵습니다. 다만 비정상적인 세션 만료, 계정 무단 접근 시도, 웹 페이지 내용 변조, 예상치 못한 스크립트 실행 등의 현상이 발생할 경우 XSS 공격을 의심해볼 수 있습니다. 정확한 확인을 위해서는 Sparrow DAST를 통한 정기적인 웹 취약점 점검과 웹 방화벽(WAF) 로그 모니터링을 병행하여, 의심스러운 요청 패턴이나 공격 시도를 지속적으로 확인하는 것을 권장합니다.
