AnbyMata의 해킹 노트

[THM] XSS - EP.3 (Task 6~7) 본문

TryHackMe/Web Hacking

[THM] XSS - EP.3 (Task 6~7)

AnbyMata 2026. 3. 6. 22:00

TryHackMe - "XSS". Task 6~7. Write-up + Extra Study!

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

 

XSS

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

tryhackme.com

 

[6]  Stored XSS

- Stored XSS = 사용자 입력이 서버에 저장된 후, 다른 사용자에게 인코딩 없이 제공되면서 발생하는 유형

- 웹 애플리케이션 보안 취약점

- 사용자 입력이 데이터 저장소에 저장되고, 이후 충분한 escaping이나 sanitization 없이 다른 사용자에게 제공되는 웹 페이지에 포함될 때 발생함

- 링크를 클릭한 사용자만 공격하는 Reflected XSS와 달리 페이지를 방문한 모든 사용자가 공격 대상임

- 위험도가 매우 높음

- 피해자가 링크를 클릭하지 않고 단순 페이지 열람만으로 실행

 

Stored XSS 공격 흐름

- 1. 공격자가 웹 애플리케이션의 입력 필드에 malicious script(악성 스크립트) 삽입

- 2. 서버가 해당 입력 (malicious script)를 DB에 저장

- 3. 피해자가 malicious script가 저장된 페이지접근

- 4. 브라우저가 malicious script를 실행

- 5. 세선 쿠키 탈취, 관리자 권한 계정 하이재킹, 사용자 대신 요청 전송 등의 악성 행위 가능

 

 

[6-1] Stored XSS 방어 방법

1. Validate and Sanitize Input (입력 검증 및 정제)

 - 사용자 입력에 대한 명확한 규칙 정의

 - 허용 가능한 값만 받음

 

 

2. Use Output Escaping (출력 시 escape)

 - HTML에 사용자 입력을 출력할 때, `<`, `>`, `&`, ` " ` 등의 특수문자를 HTML Entity로 변환

 

 

3. Apply Context-Specific Encoding (컨텍스트 기반 인코딩)

 - 데이터의 삽입 위치에 따라 인코딩 방식이 달라야 함

  + HTML 본문 → HTML encoding

  + JavaScript 내부 → JS encoding

  + URL → Percent encoding

  + HTML 속성 → Attribute encoding

 

 

4. Defence in Depth (다층 방어)

 - Client 검증만 하는 것이 아닌 Server 측 검증도 필수

 - CSP (Content Security Policy) 적용 가능

 - 여려 방어 기법을 함께 사용

 

 

 

[6-2] PHP

PHP = 웹 서버에서 실행되는 Server-side scripting 언어

 

[Vulnerable Code (취약한 코드)]

- 사용자의 댓글을 저장하는 코드

- DB 안에 storage 테이블이 존재하는 전제

 = userInput 입력값을 $inputValue 변수에 저장합니다.

 = DB의 storage 테이블의 comment 컬럼에 $inputValue 값을 INSERT

 = 조회 시엔, storage 테이블에서 comment 컬럼을 조회하여 모든 댓글을 가져옵니다.

 = 그리고 조회된 결과를 한 줄씩 출력합니다.

[보충 설명]
mysqli_query()
- MySQL 데이터베이스에 SQL query를 실행하는 함수입니다.
- 즉, PHP에서 DB에 SQL 명령을 보내는 역할을 합니다.

mysqli_fetch_assoc()
- SQL 조회 결과에서 한 행씩 가져오는 함수입니다.
- 가져온 결과들을 연관 배열 형태로 반환합니다.

 

- 사용자 입력 ($_POST['userInput'])을 그대로 DB에 저장함

→ 입력값에 HTML-encoding 과정이 없음

- 즉, 다른 사용자가 페이지를 열면, malicious(악성) script가 브라우저에서 실행됨

 

 

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

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

 = 사용자의 입력을 SQL에 사용하기 전, mysqli_real_escape_string() 으로 escape 처리합니다.

 = 화면에 출력하기 전, htmlspecialchars() 로 HTML encoding을 수행합니다.

 → `<`, `>`, `&`, ` " ` 같은 문자를 변환해 입력값에 포함된 스크립트가 실행되지 않습니다.

 

 

 

[6-3] JavaScript (Node.js)

JavaScript = 프로그래밍 언어

Node.js = 브라우저 밖에서도 JavaScript를 실행할 수 있게 해주는 실행 환경

 

[Vulnerable Code (취약한 코드)]

- 저장된 사용자 입력을 출력하는 코드

- storage 배열에 DB에서 가져온 사용자 입력이 저장되어있다는 전제

- express 모듈을 불러오는 부분은 생략

 = storage 배열에서 저장된 데이터들을 하나씩 가져옵니다.

 = 이를 <li> 태그를 통해 HTML 리스트 항목에 추가합니다.

 = 마지막에 이 내용들을 response(응답)로 브라우저에 보냅니다.

[보충 설명]
<ul> = HTML에서 순서가 없는 목록을 만들 때 사용하는 태그
<li> = 목록의 개별 항목을 나타내는 태그

예시
 <ul>
    <li>항목_1</li>
    <li>항목_2</li>
 </ul>

 

- 저장된 사용자 입력 (inputValue)을 그대로 가져옴

→ 가져온 데이터에 HTML-encoding 과정이 없음

- 즉, 다른 사용자가 페이지를 열면, malicious(악성) script가 브라우저에서 실행됨

 

 

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

- 저장된 사용자의 입력을 필터링하는 과정이 필요합니다.

 = sanitize-html은 Node.js에서 사용하는 HTML sanitizaton(정제) 라이브러리입니다.

 = sanitize-html 모듈의 sanitizeHtml() 함수를 사용합니다.

 = 이 함수로 저장된 데이터에 포함된 위험한 HTML 태그나 속성을 제거합니다.

 

 

 

[6-4] Python (Flask)

Python = 프로그래밍 언어

Flask = Python으로 웹 서버를 만들 수 있게 해주는 웹 프레임워크

 

[Vulnerable Code (취약한 코드)]

- 사용자의 댓글을 저장하고 출력하는 코드

 = Flask 애플리케이션과 SQLite 데이터베이스 site.db를 사용합니다.

 = SQLAlchemy를 통해 DB를 연결합니다.

 = Storage 클래스는 id를 primary key로 가지며, content 칼럼에 사용자 댓글을 저장합니다.

 = `/storage` 경로로 POST 요청이 들어오면, add_comment() 함수를 실행해 사용자 입력을 저장합니다.

 = `/storage` URL로 접속하면 show_comments() 함수를 실행해 DB에 저장된 모든 댓글을 조회합니다.

[보충 설명]
SQLAlchemy = Python에서 데이터베이스를 쉽게 다루기 위해 사용하는 ORM (Object Relational Mapping) 라이브러리
→ SQL 문을 작성하지 않고, Python 객체를 사용해 데이터베이스를 조작할 수 있습니다.

 

- 사용자 입력 (request.form['userInput'])을 그대로 DB에 저장함

→ 가져온 데이터에 HTML-encoding 과정이 없음

- 즉, 다른 사용자가 페이지를 열면, malicious(악성) script가 브라우저에서 실행됨

 

 

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

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

 = markupsafe 모듈에서 escape() 함수를 가져왔습니다.

 = 각 댓글을 escape() 함수로 HTML encoding 합니다.

 → `<`, `>`, `&`, ` " ` 같은 문자를 변환해 입력값에 포함된 스크립트가 실행되지 않습니다.

 

 

 

[6-5] C# (ASP.NET)

C# = 프로그래밍 언어

ASP.NET = Microsoft가 만든 웹 개발 프레임워크 (서버에서 동작)

 

[Vulnerable Code (취약한 코드)]

- 사용자의 댓글을 저장하고 출력하는 코드

 = AddComment() 함수는 사용자가 입력한 댓글(userInput)을 받아옵니다.

 = ShowComments() 함수로 storage 테이블의 comment 컬럼을 조회해서 댓글들을 읽어냅니다.

[보충 설명]
SqlCommand() = DB에 전달한 SQL query를 생성하는 객체
ExecuteReader() = SQL query를 실행시키는 함수

SqlCommand()의 안에 connection은 SQL query를 실행할 DB와의 연결 정보를 가지고 있는 객체로 어떤 DB에 SQL을 보낼지 알려줍니다.

 

- 사용자 입력 (userInput)을 그대로 DB에 저장함

→ 가져온 데이터에 HTML-encoding 과정이 없음

- 즉, 다른 사용자가 페이지를 열면, malicious(악성) script가 브라우저에서 실행됨

 

 

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

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

 = SQL 작성 방식에 `@comment`를 사용하여 SQL 구조와 데이터 값을 분리하여 처리합니다.

= System.WebHttpUility 클래스의 HtmlEncode() 함수를 사용하여 HTML encoding 합니다.

 → `<`, `>`, `&`, ` " ` 같은 문자를 변환해 입력값에 포함된 스크립트가 실행되지 않습니다.

[보충 설명]
`@comment`는 SQL 파라미터를 표시합니다.
즉, SQL 문 안에서 나중에 값이 들어갈 자리를 표시하는 역할을 합니다.
이를 통해 SQL 구조와 사용자 입력 데이터를 분리하여
SQL 문장 구조는 고정시키고, 실제 값만 나중에 따로 넣을 수 있습니다.
이는 SQL Injection 방어의 핵심이기도 합니다.

 

 

 


[7]  Vulnerable Web Application 2

- 취약한 프로젝트 Hospital Management System 실행

- 취약점 ID: CVE-2021-38757 (exploit 코드 공개 상태. But, 패치 안함)

- 취약점은 contact.pnp 파일에 존재

- 공격 방법

 + 1. Contact 페이지 이동

 + 2. 이름 / 이메일 / 전화번호 입력

 + 3. message 필드에 payload 입력

 + 4. 메시지 저장

 + 5. 다른 사용자가 메시지를 보면 악성 스크립트 실행

 

 

[7-1] Stored XSS 실습

1)  Hospital Management System 접속

 - 새 창을 열어서 URL에 `[Target IP Address]`를 입력해 프로젝트에 접속합니다.

http://??.??.???.??

 

 

 

2)  CONTACT 페이지 이동

CONTACT

 = 문제에서 나온대로 이름, 이메일, 전화번호를 입력하는 칸이 있습니다.

 

 

 

3)  XSS payload 입력

 - 이름, 이메일, 전화번호는 임의의 값으로 채웁니다.

 - 메시지 부분에 payload를 삽입해봅니다.

<script>alert("XSS")</script>

 = 메시지를 전송해보면, "Message sent successfully!" 라는 문구의 팝업창이 나타납니다.

 → 우리가 입력한 메시지가 정상적으로 서버에 저장되었습니다.

 

 

 

4)  Admin 계정으로 로그인

 - Home 페이지로 이동해서 "Receptionist"로 로그인합니다.

Home → Receptionist

 

 

 

5)  XSS payload 결과 확인

 = 관리자 계정으로 로그인을 하는 순간, "XSS" 라는 문구의 팝업창이 나타납니다.

 = 내가 주입한 payload의 코드가 실행되는 모습입니다. (<script>alert("XSS")</script>)

 → 사용자의 입력이 필터링(sanitize)이나 HTML-encoding없이 그대로 입력되어 payload가 실행된 모습입니다

 → Stored XSS 취약점이 존재합니다!

 

 

 

6)  악성 스크립트를 메시지에 포함하여 공격

 - "3) XSS payload 입력" 과정에서 메시지 필드에 악성 스크립트를 포함해 악성 스크립트를 삽입합니다.

 - `alert(document.cookie)` 같은 명령어를 사용하면, 쿠키 값을 확인할 수 있습니다.

 

 

 


[TryHackMe] XSS - EP.3 (Task 6~7). END.

 

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

https://anbymata.tistory.com/61

 

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

TryHackMe - "XSS". Task 8~10. Write-up + Extra Study!출처: https://tryhackme.com/room/axss XSSExplore in-depth the different types of XSS and their root causes.tryhackme.com [8] DOM-Based XSS- DOM-based XSS = 브라우저에서 JS가 DOM을 조작하는

anbymata.tistory.com

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

[TryHackMe] CSRF  (0) 2026.05.05
[THM] XSS - EP.4 (Task 8~10). 完  (2) 2026.03.21
[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