인덱스 화면이다.
3가지 페이지가 준비되어 있다.
GET 메소드로 받을 수 있는 param에 스크립트 구문이 삽입 되어 있고 그 구문이 동작하는 것을 볼 수 있다.
이 말은 즉슨 url에 스크립트를 삽입하는 DOM-based XSS 공격을 사용할 수 있다는 것이다.
alert의 값을 변경해도 잘 작동한다
이 곳에서는 memo에 대입하는 값을 html 텍스트로 보여준다.
하지만 스크립트 태그는 무시된다.
그 이유는 코드를 분석하면서 알아보자.
이 곳에서는 셀러니움으로 가상 접속을 할 url을 입력한다.
아까 봤던 vuln사이트에서는 DOM-based XSS 공격이 가능했기 때문에 그 곳을 이용하게 된다.
나는 가상의 랜덤 포트에서 접속한 것이기 때문에 셀러니움은 그 호스트로 가기 위해 설정한 로컬호스트:8000포트로 vuln을 찾아간다.
또한 이따가 코드 분석을 하면 알겠지만 그곳에서는 flag를 쿠키 설정한다.
그래서 그 곳에 쿠키를 메모하는 코드를 작성하게 되면 /memo페이지에는 flag가 출력될 것이다.
성공적으로 스크립트가 주입되었다.
그리고 아까 memo로 가게 되면 flag가 노출 되어 있는 것을 볼 수 있다.
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("/")
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)
먼저 메인페이지 /에 라우팅된 코드부터 살펴보자
그저 index.html을 보여줄 뿐이다.
아까 살펴봤던 memo 코드를 보면 rendet_template로 감싸져 있다.
그래서 스크립트 태그가 실행이 되지 않았던 것이다.
그럼 가장 중요한 /flag를 보자
flag값과 url 값을 read_url()로 보낸다.
그 곳에서는 셀리니움을 이용해 가상의 웹 접속을 하고 그 곳에 쿠키를 설정한뒤 설정한 url로 이동한다.
우리는 url에 vuln 페이지를 이용해 스크립트 태그를 사용하고 그 내용은 memo페이지에 memo에 현재 쿠키를 GET하라는 내용이다.
따라서 현재 쿠키는 flag가 될 것이고 그 쿠키는 memo 화면에 출력된다.