AnbyMata의 해킹 노트

[THM] XSS - EP.4 (Task 8~10). 完 본문

TryHackMe/Web Hacking

[THM] XSS - EP.4 (Task 8~10). 完

AnbyMata 2026. 3. 21. 22:00

TryHackMe - "XSS". Task 8~10. Write-up + Extra Study!

출처: https://tryhackme.com/room/axss

 

XSS

Explore in-depth the different types of XSS and their root causes.

tryhackme.com

 

[8]  DOM-Based XSS

- DOM-based XSS = 브라우저에서 JS가 DOM을 조작하는 과정에서 발생하는 유형

- 서버가 아닌 브라우저 내부에서 발생

- 지금도 자주 발견되는 Reflected XSS, Stored XSS와 달리 요즘에는 거의 발생하지 않음

- 브라우저의 기본 보안 기능 강화 → DOM-based XSS 감소

 

 

[8-1] DOM (Document Object Model)

DOM (Document Object Model)

- 웹 페이지 (HTML)를 트리 구조 형태로 표현하는 프로그래밍 인터페이스

- JavaScript를 통해 웹 사이트의 다양한 요소를 프로그래밍적으로 접근하고 조작할 수 있게 함

- 개발자 도구에서 Chrome, WhaleElement 탭, FirefoxInpsector 탭에서 DOM 확인 가능

Whale 환경

 

 

DOM 조작 예시

- 개발자 도구의 Console 탭에서 JavaScript를 사용해 DOM을 조작할 수도 있음

- ([2]  Terminology and Types에서 Console 사용법을 다뤘습니다)

 + document.createElement() = 새로운 element(요소) 생성

 + element.append() = element(요소)에 child element(자식 요소) 추가

 = div 요소와 p 요소를 생성 → p 요소를 div의 자식 요소로 지정

 

 

[8-2] DOM-based XSS in Vulnerable Web Applications

 

[Vulnerable Code (취약한 코드)]

- URL에서 사용자 이름을 가져와서 "누구의 Hacking Note!" 문장을 출력하는 코드

- URL 내의 name 파라미터에 사용자의 이름을 입력함

 = URLSearchParams() 함수를 이용해 URL의 name 파라미터 값을 userInput 변수에 저장합니다.

 = 그 이후, 사용자의 이름을 포함한 문장을 페이지에 출력합니다.

[보충 설명]
new URLSearchParams(...).get('name') = query 문자열에서 name 값만 추출합니다.
window.location.search = 현재 URL의 query 문자열을 가져옵니다.
- window.location은 브라우저가 제공하는 Location 객체이고, search는 그 안의 속성 이름이로, 고정된 이름입니다.

 

- 사용자 입력 (name 파라미터)을 document.write()로 DOM에 직접 HTML 삽입

→ 검증 및 인코딩 과정이 필요합니다.

- 즉, 공격자가 만든 악성 URL을 사용자가 열면, 브라우저에서 스크립트가 실행됨

 

 

[Fixed Code (코드 수정하기)]

- 사용자의 입력을 인코딩하는 과정이 필요합니다.

 = encodeURIComponent()name 파라미터 값을 escape 처리합니다.

 = textContent 를 사용해 escape 된 입력값을 추가합니다.

 → textContent는 HTML로 해석을 안 하기에 악성 script를 실행할 수 없습니다.

[보충 설명]
escape 처리는 SQL Injection을 방어하기 위해 사용합니다.
escape는 특수문자를 일반 문자로 바꾸는 과정으로, 입력 처리 부분에 해당됩니다.
하지만, XSS는 출력 방식의 문제로 생기는 취약점이라 escape을 한다고 예방이 되지 않습니다.

 

 

 


[9]  Context and Evasion

 

[9-1] Context

삽입된 payload는 보통 3가지 위치 중 하나에 들어갑니다.

- HTML 태그 사이 / HTML 태그 내부 / JavaScript 내부

 

1. XSSHTML 태그 사이에 발생

 - 공격자는 `<script>...</script>` 와 같이 <script> 태그 사이에 코드를 넣어 실행 가능

 - ex) <script>alert(document.cookie)</script>

 

2. XSSHTML 태그 내부에서 발생

 - 공격자는 `><script>... </script>` 같이 해당 context에 맞게 수정해야 됨

 - ex) ><script>alert(document.cookie)</script>

 

3. XSS가 기존 JavaScript 내부에서 발생

 - 기존 스크립트를 종료하고 이어서 코드를 작성해야 됨

 - 종료 방법에는 </script>, ' (따옴표) 로 문자열 닫기, ; (세미콜론) 으로 명령 끝내기 등이 있음

 

→ 즉, XSS는 payload 자체보다는 어디에 들어가느냐 (Context)가 더 중요함

 

 

 

[9-2] Evasion

대표적인 사이트들의 XSS 대처법

- 특정 문자열 차단 / 길이 제한 / 필터링

 

1. Tiny XSS Payloads

 - 최대한 짧게 만든 XSS 코드

 → 길이 제한을 우회하기 위한 출발점

 

2. 문자 분할

 - 문자열을 중간에 끊어 필터를 우회하는 기법

 - 필터 = 문자열 그대로 검사 / 브라우저 = 공백/제어문자를 무시하고 해석 (정확히는 whitespace로 처리)

 → 즉, 필터는 문자열을 보고, 브라우저는 해석된 결과만을 본다는 점을 이용

 → 문자열 기반 필터는 속이고, 브라우저 파서는 속이지 않음

 → 결과적으로, payload가 실행됨

 

 

[9-3] 문자 분할 예시

적용할 payload = `javascript:alert(1)`

문자 분할 적용 = `jav&#x09;ascript:alert(1)`

필터 = "javascript" 없음 → 통과

브라우저 = "javascript"로 해석 → 악성 코드 실행

 

사용되는 분할 문자

1. TAB (수평 탭)0x09

 - ex) <img src="jav&#x09;ascript:alert('XSS');">

 

2. LF (줄바꿈) 0x0A

 - ex) <img src="jav&#x0A;ascript:alert('XSS');">

 

3. CR (캐리지 리턴) 0x0D

 - ex) <img src="jav&#x0D;ascript:alert('XSS');">

[보충 설명]
사용되는 문자가 여러개 입니다.
이는 필터마다 막는 방식이 다르기 때문에 그렇습니다.

필터마다 공백만 제거, `\n`만 차단, 특정 패턴만 검사 등 다 다르게 동작합니다.
즉, 분할 문자가 여러 개 있습니다.
하지만, 브라우저에서는 TAB, LF, CR 모두 공백으로 해석되어 문자만 다르지 다 같은 역할을 합니다.

 

 

 


[10]  Conclusion

- XSS가 발생하는 원인과 다양한 대응 방법들을 배웠습니다.

→ 내부 동작을 이해해야 payload를 상황에 맞게 변형해나가야 합니다.

 

 

 


[TryHackMe] XSS - EP.4 (Task 8~10). END.

 

[TryHackMe] XSS. Finish!

'TryHackMe > Web Hacking' 카테고리의 다른 글

[TryHackMe] CSRF  (0) 2026.05.05
[THM] XSS - EP.3 (Task 6~7)  (0) 2026.03.06
[THM] XSS - EP.2 (Task 4~5)  (0) 2026.03.03
[THM] XSS - EP.1 (Task 1~3)  (1) 2026.02.25
[THM] SQL Injection - EP.3 (Task 6~10). 完  (0) 2026.02.16