< 문제 >
https://dreamhack.io/wargame/challenges/26
< 풀이 >
/admin/notice_flag 페이지 관련 코드를 보면
@app.route("/admin/notice_flag")
def admin_notice_flag():
global memo_text
if request.remote_addr != "127.0.0.1":
return "Access Denied"
if request.args.get("userid", "") != "admin":
return "Access Denied 2"
memo_text += f"[Notice] flag is {FLAG}\n"
return "Ok"
1. if request.remote_addr 구문을 통해 이용자의 IP가 로컬 호스트가 아닌경우 "Access Denied" 값이 반환된다.
2. if requests.args.get("userid","") 구문을 보면, userid 파라미터 값이 'admin' 이 아니라면, 또 접근이 거부된다.
위 두 조건이 아니라면, memo_text에 flag 값이 입력된다.
/vuln 페이지 관련 코드를 보면
@app.route("/vuln")
def vuln():
param = request.args.get("param", "").lower()
xss_filter = ["frame", "script", "on"]
for _ in xss_filter:
param = param.replace(_, "*")
return param
XSS를 필터링 하지만, CSRF를 유발하는 < >는 필터링 되고 있지 않기에, 해당 페이지로 CSRF를 유발 시킬 수 있다.
즉, CSRF 공격으로 /vuln 페이지를 방문한 로컬 호스트 이용자가 /admin/notice_flag 페이지에 요청을 보낼 수 있도록,
/flag 페이지의 param 파라미터 값으로 공격이 유발되는 코드를 삽입한다.
<img src="/admin/notice_flag?userid=admin" >
한줄평: CSRF.. 평소에 많이 접하지 않아서 어려웠다. 기본 강의(드림핵)를 보고, 풀도록 하자..