본문 바로가기
컴소니/보안

[웹 해킹] Dreamhack XSS Filtering Bypass(Level 1)

by 금소니 2023. 8. 25.
반응형

#265

1. 개요

워게임 명 : XSS Filtering Bypass

난이도 : Level 1

관련 개념 : Javascript, XSS, Cookie

문제 : XSS 취약점을 이용하여 FLAG 값 획득

* 이전에 풀이하였던 xss-1 워게임과 비슷하지만 XSS 취약점에 사용하고 있는 기본적인 단어들에 대하여 필터링 기능이 추가되었습니다.

XSS  Filtering Bypass 강의에 포함된 워게임입니다.

2. 소스 코드 확인

1) HTML

이전의 xss-1 워게임에서 사용한 소스 코드와 동일합니다.

 

1-1) base.html

1-2) index.html

1-3) memo.html

1-4) flag.html

파라미터를 입력받는 페이지입니다.

2) python

python 소스의 경우 필터링과 관련된 부분만 추가되었습니다.

 

2-1) 초기 선언 부분

#!/usr/bin/python3
from flask import Flask, request, render_template
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import urllib
import os

app = Flask(__name__)
app.secret_key = os.urandom(32)

try:
    FLAG = open("./flag.txt", "r").read()
except:
    FLAG = "[**FLAG**]"

2-2) read_url 함수

def read_url(url, cookie={"name": "name", "value": "value"}):
    cookie.update({"domain": "127.0.0.1"})
    try:
        service = Service(executable_path="/chromedriver")
        options = webdriver.ChromeOptions()
        for _ in [
            "headless",
            "window-size=1920x1080",
            "disable-gpu",
            "no-sandbox",
            "disable-dev-shm-usage",
        ]:
            options.add_argument(_)
        driver = webdriver.Chrome(service=service, 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

2-3) check_xss

def check_xss(param, cookie={"name": "name", "value": "value"}):
    #check_xss는 read_url함수 호출하여 vuln 엔드포인트 접속
    url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"
    return read_url(url, cookie)

2-4) xss_filter

#입력한 문자열을 필터링하는 함수
def xss_filter(text):
    #script, on, javascript: 문자열 발견 시
    _filter = ["script", "on", "javascript:"]
    for f in _filter:
        if f in text.lower():
            #""로 치환
            text = text.replace(f, "")
    return text

2-5) app.route("/")

#render_template : flask에서 제공하는 함수로 templates에 저장된 html을 불러올 때 사용하는 함수
@app.route("/")
def index():
    return render_template("index.html")

2-6) app.route("/vuln")

#사용자가 입려갛ㄴ param 값을 출력
@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")
    #필터링과 관련된 함수 호출
    param = xss_filter(param)
    return param

2-7) app.route("/flag", methods["GET", "POST"])

@app.route("/flag", methods=["GET", "POST"])
def flag():
    #이용자에게 URL을 입력받는 페이지를 제공
    if request.method == "GET":
        return render_template("flag.html")
    elif request.method == "POST":
        param = request.form.get("param")
        #파라미터 값과 쿠키에 FLAG를 포함해 check_xss 함수 호출
        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>'

2-8) app.route("/memo")

memo_text = ""

#사용자가 요청한 내용을 메모로 작성하여 출력
#여기는 render_template를 통해 출력하기 때문에 취약하지 않음
@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)

2-8) 서비스 실행

app.run(host="0.0.0.0", port=8000)

3. 웹 화면 확인

xss-1과 동일하게 구성된 웹 서비스 화면입니다.

 

1) /vuln

취약한 페이지로 드림핵 홈페이지의 로고를 호출하도록 작성한것 같은데 제대로 로드가 되지 않았습니다.

한 번 변경해서 요청해봤습니다.

 

2) /memo

여기는 마찬가지로 메모가 입력되어 저장되는 경로로 링크를 클릭할 때 마다 hello 문구가 추가됩니다.

3) /flag

이 곳이 저희가 실제 테스트하여 flag 값을 얻을 경로입니다.

4.  문제 풀이

1) 요구사항 파악

앞서서 풀이하였던 XSS 워게임들과 유사하지만 주요 단어들이 필터링되어 있어 다른 방법으로 공격을 수행해야 합니다.

필터링과 관련된 소스코드를 확인해보면 해당 단어를 입력할 경우 에러페이지를 반환하거나 요청을 못하도록 제한하는 것이 아닌 blank("")로 치환합니다.

이를 이용하여 공격을 수행할 수 있습니다.

 

2) script를 두 번 사용하여 alert 띄우기

필터링에 의해 script라는 단어를 단독으로 사용하였을 때는 제대로 동작하지 않지만 아래와 같이 입력하면 우회하여 실행할 수 있습니다.

 

<sscriptcript>alert(1)</sscriptcript>

 

3) 대문자를 이용하여 alert 띄우기

또한, 대문자에 대한 필터링 규칙이 없기 때문에 대문자를 활용하여서도 공격이 가능합니다.

 

<Script>alert(1)</Script>

 

4) 실제 공격해보기

이 두 가지 방법을 이용하여 이전 공격에 사용한 스크립트를 작성해보도록 하겠습니다.

 

<Script>locatioonn.href = "/memo?memo=" + document.cookie;</Script>

 

사실 위의 스크립트 말고도 여러가지 방법으로 작성할 수 있습니다.

저의 경우에는 대문자 방법과 문자열을 blank로 만들어 실행할 수 있도록 작성하였습니다.

입력하여 요청한 결과 flag 값을 확인할 수 있었습니다.

반응형

댓글