XSS-1

mercure·2024년 8월 13일
0

Dreamhack

목록 보기
13/18

XSS(Cross-Site Scripting)는 공격자가 악성 스크립트를 다른 사용자의 브라우저에서 실행할 수 있도록 만드는 공격 기법이다. XSS는 웹 애플리케이션이 사용자 입력을 적절하게 처리하지 않고, 검증이나 인코딩 없이 그대로 출력할 때 발생한다.

XSS의 종류

Stored XSS

  • 악성 스크립트가 서버에 저장되어 다른 사용자가 페이지를 방문할 때 실행

Reflected XSS

  • 악성 스크립트가 URL이나 요청에 포함되어 서버 응답 시 즉시 실행

DOM-based XSS

  • 클라이언트 측에서 DOM(Document Object Mode)을 조작하는 과정에서 악성 스크립트가 실행
    DOM

XSS-1 문제

메인화면

vuln(xss) page

memo

flag

코드 분석

#!/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**]"

# URL과 쿠키를 받아서 쿠키를 업데이트하고 URL을 읽는 함수
def read_url(url, cookie={"name": "name", "value": "value"}):
    cookie.update({"domain": "127.0.0.1"})  # 쿠키의 도메인을 로컬 서버로 업데이트
    try:
        service = Service(executable_path="/chromedriver")  # ChromeDriver 서비스 설정
        options = webdriver.ChromeOptions()  # Chrome 옵션 설정
        for _ in [
            "headless",  # 브라우저 창 없이 실행 (헤드리스 모드)
            "window-size=1920x1080",  # 가상 브라우저 창 크기 설정
            "disable-gpu",  # GPU 사용 비활성화
            "no-sandbox",  # 샌드박스 모드 비활성화
            "disable-dev-shm-usage",  # /dev/shm 사용 비활성화 (메모리 제한 문제 방지)
        ]:
            options.add_argument(_)  # 옵션을 Chrome에 추가
        driver = webdriver.Chrome(service=service, options=options)  # WebDriver 객체 생성
        driver.implicitly_wait(3)  # 암묵적 대기 시간 설정 (3초)
        driver.set_page_load_timeout(3)  # 페이지 로드 타임아웃 설정 (3초)
        driver.get("http://127.0.0.1:8000/")  # 기본 페이지 로드 (로컬 서버)
        driver.add_cookie(cookie)  # 설정된 쿠키를 브라우저에 추가
        driver.get(url)  # 지정된 URL로 이동
    except Exception as e:
        driver.quit()  # 예외 발생 시 브라우저 종료
        # return str(e)
        return False  # 실패 시 False 반환
    driver.quit()  # 정상적으로 실행된 경우 브라우저 종료
    return True  # 성공 시 True 반환

# XSS(크로스 사이트 스크립팅) 공격이 발생할 수 있는지 확인하는 함수
def check_xss(param, cookie={"name": "name", "value": "value"}):
    url = f"http://127.0.0.1:8000/vuln?param={urllib.parse.quote(param)}"  # XSS 공격을 테스트할 URL 생성
    return read_url(url, cookie)  # 생성된 URL을 read_url 함수로 전달하여 XSS 테스트 수행

# index.html을 렌더링
@app.route("/")
def index():
    return render_template("index.html")  

# 사용자 입력을 그대로 반환 (XSS 취약성 존재)
@app.route("/vuln")
def vuln():
    param = request.args.get("param", "")  
    return param  

# POST 요청에서 XSS 공격 성공 여부에 따라 다른 응답 반환
@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")  
        # 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>'

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)  

경로

  • / - 메인 페이지
  • /memo
    사용자에게 get 요청으로 memo 값 받아서 길고 기본값은 hello
  • /vuln
    URL 파라미터 그대로 반환
  • /flag
    get - flag.html 받아옴
    post를 통해 제출시 xss 공격이 들어가는지 체크한다

  • /memo에서 직접적으로 스크립트를 실행할 방법은 따로 보이지 않으므로 /flag에서 진행하는것이 맞다고 판단하였다.

  • /vuln에서는 사용자 입력을 그대로 반환하지만 flag 얻을 방법이 보이지 않는다.

따라서 /flag 경로에서 친절히 /vuln경로를 쓸수 있게 지정 해주었으므로 이를 활용 하였다.

/flag 경로에서는 사용자가 POST 요청으로 제출한 param 값을 check_xss 함수에 전달하는데 이 함수는 내부적으로 read_url 함수를 호출하여 Selenium을 통해 /vuln경로 이동하여 쿠키를 업데이트한다. 이때 쿠키는 flag 값이 된다. 이 쿠키를 /memo를 통해 기록해주면 될 것이다.

<script>location.href = '/memo?memo='+document.cookie;</script>

location.href는 자바스크립트에서 현재 페이지의 URL을 가리키는 속성

위 코드를 삽입하면 memo 에 flag값인 쿠키를 작성할 수 있다.

profile
하루에 한걸음씩

0개의 댓글

관련 채용 정보