AnbyMata의 해킹 노트

[THM] XSS - EP.2 (Task 4~5) 본문

TryHackMe/Web Hacking

[THM] XSS - EP.2 (Task 4~5)

AnbyMata 2026. 3. 3. 22:00

TryHackMe - "XSS". Task 4~5. Write-up + Extra Study!

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

 

XSS

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

tryhackme.com

 

[4]  Reflected XSS

- Reflected XSS = malicious(악성) script가 사용자 브라우저로 즉시 반사되는 유형

- 보통 조작된 URL이나 폼 제출을 통해 발생

- 웹 애플리케이션이 취약할 때 발생

 

Vulnerable Web Application (취약한 웹 애플리케이션)

- 사용자의 특정 검색어가 결과 페이지에 그대로 포함되는 등의 단순한 구조가 XSS 공격에 취약함

- 취약점을 수정하는 것은 비교적 간단함 → <script> 같은 태그를 문자열로 인식하게 만들면 됨

 + 사용자 입력값을 sanitized(정화)

 + 출력 시 HTML-encoded

[보충 설명]
Sanitize = 사용자 입력에서 위험한 코드나 태그를 제거하거나 필터링합니다.
사용자가 `<script>alert('XSS')</script>` 같이 HTML 태그를 포함한 문자열을 입력하면,
sanitize 적용을 통해 <script> 태그를 제거하여 `alert('XSS')`로 필터링합니다.

HTML-encoded = 특수 문자를 브라우저가 태그로 해석하지 않도록 문자 형태로 변환합니다.
`<script>alert('XSS')</script>` 코드를 인코딩하면, `<`는 `&lt;`로, `>`는 '&gt;`로 처리되어
`&lt;script&gt;alert('XSS')&lt;/script&gt;`로 변환되어 처리됩니다.
브라우저는 저 변환된 문자열을 받아서 "<script>alert('XSS')</script>"라는 문자열을 출력하게 됩니다.

 

이제 언어 및 프레임워크에서의 취약한 코드 예제들을 살펴보겠습니다.

 

 

 

[4-1] PHP

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

 

[Vulnerable Code (취약한 코드)]

- `https://anby.thm/ex.php?q=mata`라는 URL이 있습니다.

 = URL의 파라미터 `q` 값을 받아 $owner_input 변수에 저장합니다.

 =  $owner_input 값과 "Hacking Note!" 문자열을 함께 출력하는 코드입니다.

 → URL대로라면, "mata Hacking Note!"가 출력됩니다.

 

- 사용자 입력 ($_GET['q'])을 그대로 HTML에 삽입해 출력하는 코드

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

- 즉, 공격자가 악성 스크립트를 넣어서 브라우저 화면에 실행시킬 수 있음

 

 

[공격 예시]

1)  공격자가 q 파라미터에 `<script>alert(document.cookie)</script>`를 넣은 URL 생성

2)  이 코드는 `document.cookie`로 사용자의 cookie 값을 반환해 alert 명령어로 그 cookie 값을 팝업창에 띄우는 코드

3)  공격자는 이 URL을 피해자에게 전달 (메신저, 이메일, 링크 등)

4)  피해자가 해당 링크를 클릭

5)  피해자의 브라우저에서 q 파라미터에 넣은 코드가 실행됨

6)  피해자의 브라우저에 cookie 값이 표시됨

(alert 명령어라 피해자의 화면에 표시되는걸로 끝나지만, 실제로는 다른 코드를 사용해 cookie 값을 탈취함)

 

 

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

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

 = `htmlspecialchars()`는 HTML 특수 문자를 HTML Entity로 변환합니다.

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

[보충 설명]
HTML Entity = HTML에서 특수 문자를 문자 그대로 표시하기 위해 사용하는 표현 방식
브라우저는 `<`, `>` 같은 문자를 태그로 해석합니다.
그래서 이를 단순 텍스트로 보여주려면 다른 형태로 바꿔야 하는데, 그 형식이 HTML Entity입니다.
`<script>`를 HTML Entity 형식으로 변환하면, `&lt;script&gt;`입니다.
그리고 브라우저는 `&lt;script&gt;`를 "<script>"라는 단순 텍스트로 표시합니다.

 

 

 

[4-2] JavaScript (Node.js)

JavaScript = 프로그래밍 언어

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

 

[Vulnerable Code (취약한 코드)]

- `https://anby.thm/user?q=mata`라는 URL이 있습니다.

 = express 모듈을 불러옵니다. (Express = Node.js 용 웹 프레임워크)

 = Express 애플리케이션 객체를 생성하여 `app`이 웹 서버 역할을 하도록 합니다.

 = '/user' 경로로 GET 요청이 오면, app.get 함수의 코드 부분이 실행됩니다.

 = q 파라미터의 값과 "Hacking Note!" 문자열을 함께 브라우저에 전송하는 코드입니다.

 → URL대로라면, "mata Hacking Note!"가 전송됩니다.

 = 서버는 80번 포트에서 실행됩니다. (80번 = 기본 HTTP 포트)

 

- 사용자 입력 (req.query.q)을 그대로 응답에 포함해 전송함

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

- 즉, 공격자의 악성 스크립트를 포함한 서버의 응답을 브라우저가 HTML로 해석하면서 실행됨

- [공격 예시][4-1] PHP에 적힌 예시와 동일함

 

 

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

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

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

 = sanitize-html 모듈에서 sanitizeHtml() 함수를 불러왔습니다.

 = 이 함수는 사용자 입력에 포함된 위험한 HTML 태그나 속성을 제거합니다.

[보충 설명]
sansitizeencoding을 구분해야 합니다.
sanitize = 입력값에서 위험한 태그나 속성을 제거하는 방식
encoding = 특수 문자를 HTML Entity로 변환하여 코드 실행을 차단하는 방식

즉, `<script>alert('XSS attack')</script>` 각각 sansitizeencoding하여 브라우저에 표시하면,
sanitize → "alert('XSS attack')" 텍스트가 출력 (코드로써 기능 X)
encoding → "<script>alert('XSS attack')</script>" 텍스트가 출력 (코드로써 기능 X)
즉, sanitize는 허용되지 않은 태그를 제거해버리기에 사용자가 입력한 텍스트가 일부 변경되거나 삭제될 수 있습니다.

 

 

 

[4-3] Python (Flask)

Python = 프로그래밍 언어

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

 

[Vulnerable Code (취약한 코드)]

- `https://anby.thm/user?q=mata`라는 URL이 있습니다.

 = flask 모듈에서 Flask 클래스와 request 객체를 가져옵니다.

 = Flask 애플리케이션 객체를 생성합니다. (__name__은 현재 모듈 이름)
 = "/user" 경로로 들어오는 요청을 처리합니다.

 = getOwner() 함수는 q 파라미터의 값과 "Hacking Note!" 문자열을 함께 반환합니다.

 → URL대로라면, "mata Hacking Note!"가 반환됩니다.

 = if 문은 이 파일을 직접 실행할 때만 서버를 실행하게 해줍니다.

[보충 설명]
__name__ 은 현재 실행 중인 모듈의 이름을 담는 변수입니다.
파일이 직접 실행된 경우에는 "__main__"을 값으로 가지게 됩니다.
다른 파일에서 불러오면 그 파일의 이름을 값으로 가지게 됩니다.

즉, if __name__ == "__main__" 조건문은 이 파일을 직접 실행할 때만 서버를 실행하도록 하고, 다른 파일에서 import될 경우에는 서버 실행 코드가 동작하지 않도록 한다.

 

- 사용자 입력 (request.args.get("q"))을 그대로 응답에 포함해 전송함

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

- 즉, 공격자의 악성 스크립트를 포함한 서버의 응답을 브라우저가 HTML로 해석하면서 실행됨

- [공격 예시] [4-1] PHP에 적힌 예시와 동일함

 

 

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

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

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

 = 이 함수는 HTML 특수 문자를 HTML Entity로 변환합니다.

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

 

 

 

[4-4] ASP.NET

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

 

[Vulnerable Code (취약한 코드)]

- `https://anby.thm/user?q=mata`라는 URL이 있습니다.

 = Page_Load는 웹 페이지가 로드되면 자동으로 실행됩니다.

 = q 파라미터의 값과 "Hacking Note!" 문자열을 함께 응답으로 출력합니다.

 → URL대로라면, "mata Hacking Note!"가 응답으로 출력됩니다.

 

- 사용자 입력 (Request.QueryString["q"])을 그대로 응답에 포함해 전송함

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

- 즉, 공격자의 악성 스크립트를 포함한 서버의 응답을 브라우저가 HTML로 해석하면서 실행됨

- [공격 예시] [4-1] PHP에 적힌 예시와 동일함

 

 

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

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

 = Sytem.WebHttpUility 클래스를 사용하기 위한 네임스페이스입니다.

 = HttpUtility 클래스의 HtmlEncode() 함수는 HTML 특수 문자를 HTML Entity로 변환합니다.

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

 

 

 


[5]  Vulnerable Web Application 1

- 취약한 copyparty 서버가 실행 중

- 취약점 ID: CVE-2023-38501

- 서버 포트: 3923

- `?k304=y <img src=copyparty onerror=alert(1)>` 코드를 인코딩하여 XSS 공격에 사용합니다.

- URL 인코딩 된 코드: ?k304=y%0D%0A%0D%0A%3Cimg+src%3Dcopyparty+onerror%3Dalert(1)%3E

[보충 설명]
URL 인코딩된 코드를 보면, 특수문자들이 어떤 값으로 변환되었는지 대충 알 수 있습니다.
`<` → %3C  /  `>` → %3E  /  `=` → %3D  /  `  `(공백)+

그리고, %0D%0ACRLF라고 불리는 줄바꿈 문자입니다.
CRLF는 사람눈에는 안 보이는 특수 제어 문자로, 줄을 다음 줄로 이동시킵니다.
(LF = 한줄 아래로 이동 / CR =  커서를 줄 맨 앞으로 이동)

 

 

[5-1] Reflected XSS 실습

1)  copyparty 서버접속하기

 - 새 창을 열어서 URL에 `[Target IP Address]:3923`을 입력해서 copyparty 서버에 접속합니다.

 - [Target IP Address]는 "Start Machine"을 클릭 후 생성된 가상머신의 IP 주소입니다. (000.000.000.000 형식)

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

 

 

 

2)  파일 내용 확인

 - 파일의 내용을 확인해보면,

cat.png

 = 이와 같이 모두 사진 한 장을 담고 있는 파일들입니다.

 

 

 

3)  XSS 공격 시행

 - URL 뒤쪽에 인코딩된 코드를 추가하여 XSS 공격을 합니다.

`http://??.??.???.???:3923/?k304=y%0D%0A%0D%0A%3Cimg+src%3Dcopyparty+onerror%3Dalert(1)%3E`

 = 우리가 의도한 코드인 ` <img src=copyparty onerror=alert(1)>`의 결과가 출력되었습니다.

 - 이 코드의 태그는 <img>로 이미지를 불러오는 태그입니다.

 - `onerror=alert(1)` 부분을 통해 이미지 로딩에 실패하면, 숫자 1을 표시하는 팝업창이 나옵니다.

 → 즉, 현재 화면은 "copyparty"라는 이미지 경로가 존재하지 않아 이미지 로딩에 실패한 모습입니다.

[보충 설명]
현재 우리는 XSS 공격에 URL 인코딩된 코드를 사용했습니다.
URL 문법은 특수문자를 안정적으로 처리하지 못합니다. 그래서 안전하게 특수문자를 포함시키기 위해 URL 인코딩을 하여 넣은 것입니다.
추가적으로 서버에서 <script> 같은 특수문자를 필터링하는 경우가 있기에, 이를 우회하기 위해서 URL 인코딩을 합니다.

 

 

 

4)  브라우저에 표시된 지시에 따라 이동

 - 공격이 성공하면 특정 경로로 이동하라는 안내 문구가 표시됩니다.

 - [Target IP Address]:3923 뒤에 이동하라고 나온 경로를 넣어주면 됩니다.

`http://??.??.???.???:3923/???????`

 = 웹 서버의 Admin(관리) 페이지로 이동했습니다.

 

 

 


[TryHackMe] XSS - EP.2 (Task 4~5). END.

 

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

https://anbymata.tistory.com/59

 

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

TryHackMe - "XSS". Task 6~7. Write-up + Extra Study!출처: https://tryhackme.com/room/axss XSSExplore in-depth the different types of XSS and their root causes.tryhackme.com [6] Stored XSS- Stored XSS = 사용자 입력이 서버에 저장된 후, 다른

anbymata.tistory.com

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

[THM] XSS - EP.4 (Task 8~10). 完  (2) 2026.03.21
[THM] XSS - EP.3 (Task 6~7)  (0) 2026.03.06
[THM] XSS - EP.1 (Task 1~3)  (1) 2026.02.25
[THM] SQL Injection - EP.3 (Task 6~10). 完  (0) 2026.02.16
[THM] SQL Injection - EP.2 (Task 4~5)  (0) 2026.02.07