๋๋ฆผํต ์๊ฒ์ level1 xss-1 ๋ฌธ์ ์ ๋ํ ํ์ด์ด๋ค.
๋ฌธ์ ํ์ผ์ ๋ค์ด๋ฐ๊ณ app.py ํ์ผ์ ์ด์ด์ฃผ๋ฉด ๋ค์๊ณผ ๊ฐ์ ํ์ด์ง๋ค์ด ๋ผ์ฐํ ๋๊ณ ์์์ ํ์ธํ ์ ์๋ค.
๊ฐ ํ์ด์ง์ ๊ธฐ๋ฅ์ ์ ๋ฆฌํ๋ฉด ์๋์ ๊ฐ๋ค.
๐ค ์ฝ๋ ๋ถ์
๊ฐ ํ์ด์ง์ ๊ธฐ๋ฅ์ ์ ๋ฆฌํ๋ฉด ์๋์ ๊ฐ๋ค. (๋๋ฆผํต ์น ํดํน ๊ฐ์ข์์ ์ด๋ฏธ ์ ๋ฆฌ๋ ๋ด์ฉ์ด๋ค.)
ํ์ด์ง | ๊ธฐ๋ฅ |
/ | ์ธ๋ฑ์ค ํ์ด์ง |
/vuln | ์ด์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ ์ถ๋ ฅ |
/memo | ๋ฉ๋ชจ ์์ฑ ๋ฐ ์์ฑํ ๋ฉ๋ชจ ์ถ๋ ฅ |
/flag | ์์ฑํ URL ์ ๋ฌ |
@app.route("/vuln")
def vuln():
param = request.args.get("param", "")
return param
- request.args.get("param", "")๋ HTTP ์์ฒญ์์ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์ฝ๋
- ์๋ฅผ ๋ค์ด, URL์ด http://example.com/?param=test๋ผ๋ฉด, request.args.get("param", "")๋ "test" ๊ฐ์ ๋ฐํ
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)
- param: ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ ๊ฐ์ ์๋ฏธ
- cookie: ์ฟ ํค ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ ๊ธฐ๋ณธ๊ฐ์ด {"name": "name", "value": "value"}์ธ ๋์ ๋๋ฆฌ
- ์ด ์ฝ๋์์ url ๋ณ์๋ param ๊ฐ์ URL ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ํฌํจํ๋ URL์ ์์ฑํจ
- urllib.parse.quote(param)๋ param ๊ฐ์ URL ์ธ์ฝ๋ฉํ์ฌ ์ฟผ๋ฆฌ ํ๋ผ๋ฏธํฐ๋ก ์์ ํ๊ฒ ์ ๋ฌํ ์ ์๋๋ก ํจ. ์ด๋ ํน์ ๋ฌธ์๋ ๊ณต๋ฐฑ ๋ฑ์ URL์ ์ ํฉํ ํ์์ผ๋ก ๋ณํํ๋ ์ญํ .
- ์๋ฅผ ๋ค์ด, param ๊ฐ์ด "hello world"๋ผ๋ฉด, urllib.parse.quote(param)์ "hello%20world"๋ก ๋ณํ.
- ์ต์ข ์ ์ผ๋ก ์์ฑ๋๋ URL์ http://127.0.0.1:8000/vuln?param=<encoded_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>'
- GET ์์ฒญ์ด ๋ค์ด์ค๋ฉด, flag.html ํ ํ๋ฆฟ์ ๋ ๋๋งํ์ฌ ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ๋ก ๋ฐํ. ์ฆ, ์ฌ์ฉ์์๊ฒ ์น ํ์ด์ง๋ฅผ ๋ณด์ฌ์ฃผ๋ ๋ถ๋ถ
- ์ฌ์ฉ์๊ฐ ํผ์ ์ ์ถํ๋ฉด, POST ์์ฒญ์ด ์ฒ๋ฆฌ๋จ. ํผ์์ ์ ์ถ๋ param ๊ฐ์ request.form.get("param")์ ์ฌ์ฉํด ๊ฐ์ ธ์ด.
- if not check_xss(...):
- check_xss๊ฐ False๋ฅผ ๋ฐํํ๋ค๋ ๊ฒ์, param์ XSS ๊ณต๊ฒฉ์ด ํฌํจ๋์ด ์์์ ์๋ฏธ.
- ์ด ๊ฒฝ์ฐ, ์๋ฒ๋ wrong??๋ผ๋ ๋ฉ์์ง๋ฅผ alert ์ฐฝ์ผ๋ก ํ์ํ๊ณ , ์ฌ์ฉ์๋ฅผ ์ด์ ํ์ด์ง๋ก ๋์๊ฐ๊ฒ (history.go(-1)) ๋ง๋ฆ
๊ฐ๋จํ ์ ๋ฆฌํ๋ฉด memo์ vuln ํ์ด์ง ๋ชจ๋ ์ ๋ฌ ๋ฐ์ param์ ํ๋ฉด์ ์ถ๋ ฅํ๋๋ฐ, param์ flag์์ cookie ๊ฐ๊ณผ ํจ๊ป xss๋ฅผ ํ์ธํ๋ ํจ์๋ก ์ฐ์ ๋ณด๋ด์ง๊ณ , ๋ฌธ์ ๊ฐ ์๊ธฐ์ง ์์ผ๋ฉด read_url ํจ์๋ก ๋ณด๋ด์ ธ ๊ฐ ํ์ด์ง์ param์ ์ ๋ฌํ๊ณ ์๋ค.
๐ญ ๋ฌธ์ ํ์ด๋ฅผ ์ํ ์ง์
๋ฌธ์ ๋ฅผ ํ๋ ค๋ฉด ์ฐ์ ์๋ ๋ ๊ฐ์ง ์์ฑ๊ฐ์ ์๊ณ ์์ด์ผ ํ๋ค.
location.href: ์ ์ฒด URL์ ๋ฐํํ๊ฑฐ๋, URL์ ์ ๋ฐ์ดํธํ ์ ์๋ ์์ฑ๊ฐ
document.cookie: ํด๋น ํ์ด์ง์์ ์ฌ์ฉํ๋ ์ฟ ํค๋ฅผ ์ฝ๊ณ , ์ฐ๋ ์์ฑ๊ฐ
memo์ vuln ๋ชจ๋ flag์์ ์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ ์ถ๋ ฅ ํ์ง๋ง ์ฟ ํค๋ฅผ ํ์ทจํ ์ ์๋ ํ์ด์ง๋ vuln ํ์ด์ง์ผ ๋ฟ์ด๋ค. ๊ทธ ์ด์ ๋ ์๋์ ๊ฐ์ ์ฐจ์ด์ ์ด ์๊ธฐ ๋๋ฌธ์ด๋ค.
- memo: render_template ํจ์๋ฅผ ์ฌ์ฉํด memo.html์ ์ถ๋ ฅ, render_template ํจ์๋ ์ ๋ฌ๋ ํ ํ๋ฆฟ ๋ณ์๋ฅผ ๊ธฐ๋กํ ๋ HTML ์ํฐํฐ์ฝ๋๋ก ๋ณํํด ์ ์ฅํ๊ธฐ ๋๋ฌธ์ XSS๊ฐ ๋ฐ์ํ์ง ์์ (์ถ์ฒ: ๋๋ฆผํต ์น ํดํน ๊ฐ์)
- vuln: ์ด์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ ํ์ด์ง์ ๊ทธ๋๋ก ์ถ๋ ฅ, XSS ๋ฐ์ ๊ฐ๋ฅ
๐ ๋ฌธ์ ํ์ด
vuln ํ์ด์ง์ ์ฟ ํค๋ฅผ ํ์ทจํ๊ธฐ ์ํ param์ ์ ๋ฌํ ๋ค ํ์ทจํ ์ฟ ํค๋ฅผ memo ํ์ด์ง์์ ๋ณด์ด๊ฒ ํด์ฃผ๋ฉด ๋๋ค.
flag ํ์ด์ง param์ ์์ฑํ๋ ๋ถ๋ถ์ ์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
<script>location.href = "/memo?memo=" + document.cookie;</script>
document.cookie ์ฆ, ํ์ทจํ ์ฟ ํค๊ฐ ๋ด๊ฒจ์๋ ํ๋ผ๋ฏธํฐ๋ฅผ memo ์๋ํฌ์ธํธ์ ์ ๋ฌํ๋ฉด
memo ํ์ด์ง๋ ์ ๋ฌ๋ฐ์ param์ ๋ณด์ฌ์ค๋ค.

'๐ธ๏ธ ์น ํดํน' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[wargame] ๋๋ฆผํต xss-2 ๋ฌธ์ ํ์ด (0) | 2025.03.06 |
---|---|
Cross-Site Scripting (XSS) ๊ฐ๋ ์ ๋ฆฌ (0) | 2025.03.05 |
์น ๋ธ๋ผ์ฐ์ ๋ณด์ ์ ์ฑ SOP, CORS, JSONP ๊ฐ๋ ์ ๋ฆฌ (0) | 2025.03.05 |
[wargame] Dreamhack ๋ฌธ์ ํ์ด: session-basic (0) | 2025.03.05 |
[wargame] ๋๋ฆผํต beginner cookie ๋ฌธ์ ํ์ด (0) | 2025.03.03 |