여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다.
CSRF 취약점을 이용해 플래그를 획득하세요.
check_csrf
def check_csrf(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)
위 코드는 파라미터에 저장된 값을 합친 url 값과, cookie값을 반환해 준다.
vuln
def vuln(): param = request.args.get("param", "").lower() xss_filter = ["frame", "script", "on"] for _ in xss_filter: param = param.replace(_, "*") return param
위 코드는 frame, script, on 키워드를 필터링 하고 있고, 대문자또한 필터링 하고 있음을 볼 수 있다.
또한 _ 문자도 필터링 하고 있다.
필터링 된 결과를 param에 저장해서 반환한다.
flag
def flag(): if request.method == "GET": return render_template("flag.html") elif request.method == "POST": param = request.form.get("param", "") if not check_csrf(param): return '<script>alert("wrong??");history.go(-1);</script>' return '<script>alert("good");history.go(-1);</script>'
위 코드는 check_csrf에 파라미터를 보내는 코드
memo
def memo(): global memo_text text = request.args.get("memo", None) if text: memo_text += text return render_template("memo.html", memo=memo_text)
위 코드는 메모. 생략.
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"
위 코드는 127.0.0.1에서 보내고, userid가 admin이면flag를 메모에 저장해주겠다는 코드인듯
admin_notice_flag로 위 조건을 만족시켜서 접근할 수 있을까?
우선 flag 페이지를 보면
파라미터자체가 127.0.0.1에서 보내진다
1번조건 ok
이제 userid=admin을 맞춰주면된다
앞서 필터링에 꺽쇠는 없기 때문에 img 태그를 사용해서 주면 해당 페이지로 유도 가능
<img src="/admin/notice_flag?userid=admin">