DVWA(Damn Vulnerable Web Application) 실습 중 DOM XSS Medium 단계에서 겪은 시행착오를 정리했다.
참고 페이지: https://cheatsheetseries.owasp.org/cheatsheets/DOM_based_XSS_Prevention_Cheat_Sheet.html
클라이언트 측 소스코드의 76번 라인을 분석하면, 사용자 입력값이 저장된 변수(lang)가 <option> 태그의 속성과 데이터 영역에 직접 삽입되는 구조적 취약점을 가지고 있다.

// 76번 라인: 검증 없이 입력값을 HTML 구조에 삽입
document.write("<option value='" + lang + "'>" + (lang) + "</option>");
구조: <option value="[입력값]">[입력값]</option>
문제점: 입력값이 HTML의 구조를 결정하는 문맥에 직접 노출되어 있었다.
1) 공격 시도 (서버 검증 로직 우회 시도 중)
서버 측 PHP 소스코드의 <script 대소문자 구분 없는 검증 로직을 우회하기 위해 <img> 태그를 활용한 스크립트를 다음과 같이 작성하였다. 고의로 존재하지 않는 이미지 주소를 입력하여 에러를 발생시킨 후, onerror 핸들러를 통해 쿠키값을 노출하는 스크립트이다.
<img src="x">

2) 실행 실패 원인 (클라이언트의 데이터 처리 방식)
작성한 스크립트가 실행되지 않은 이유는 HTML 표준 때문인데, 브라우저는 <option> 태그 내부에 다른 HTML 태그가 포함되는 것을 좋아하지 않기 때문이다.
브라우저가 받아들이는 방식은 아래와 같았다.
<option value="<img src='x' onerror='alert(document.cookie)'>">
<img src="x" onerror="alert(document.cookie)">
</option>**텍스트**
위와 같이 삽입된 <img> 태그는 유효한 코드로 해석되지 못하고 단순한 문자열로 처리되어 경고창이 발생하지 않았다.
3) 해결 방법: 태그 탈출(Breakout) 및 새 태그 생성
기존 HTML 구조를 강제로 종료시키는 '태그 탈출' 기법을 사용하여 우회를 시도했다.
최최종 스크립트:
?default=English'></option></select><img src=x onerror=alert(document.cookie)>
작동 원리
<option> 태그의 value 속성 값을 닫는다.></option></select>를 주입하여 현재 속한 태그와 상위 부모 태그인 <select>까지 닫는다.<img> 태그를 생성한다!
해당 취약점은 사용자의 입력값이 HTML 문서의 구조를 결정하는 문맥(Context)에 직접 삽입될 때 발생한다.
대응 방안
document.write와 같은 위험한 함수 사용을 지양하고 .textContent를 사용을 권장한다.https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html