본문으로 건너뛰기

02. XSS (Cross-Site Scripting)

정보

모든 실습은 00. 실습 원칙과 범위 에 따라 허가된 로컬 환경(01. 실습 환경 구축)에서만 수행한다.

1. 원리: 왜 생기는가​

XSS는 사용자 입력이 검증·인코딩 없이 HTML/스크립트로 실행될 때 발생한다. 웹 페이지가 사용자 입력을 그대로 화면에 출력하면, 입력에 포함된 스크립트가 다른 사용자의 브라우저에서 실행된다.

사용자 입력 → 서버/페이지가 그대로 출력 → 브라우저가 "코드"로 해석·실행
유형설명
Stored(저장형)입력이 DB에 저장되어, 그 페이지를 보는 모두에게 실행
Reflected(반사형)요청 파라미터가 응답에 즉시 반사되어 실행
DOM-based클라이언트 측 스크립트가 입력을 안전하지 않게 DOM에 반영

영향: 세션 탈취(쿠키), 피싱, 화면 변조, 사용자 행위 위조 등.

2. 실습 (로컬, 고수준)​

DVWA의 XSS 메뉴 또는 Juice Shop의 검색/입력 필드에서, 입력이 그대로 출력되는지를 확인하는 수준으로 진행한다.

  • 입력란에 평범한 문자열 대신 HTML 특수문자(<, >, ")를 넣었을 때, 화면 소스에서 그 문자가 그대로 태그로 들어가는지 확인한다.
  • 그대로 들어간다면, 그 위치는 인코딩이 안 되고 있다는 뜻이다. 가장 흔한 확인 방법은 alert 같은 무해한 동작으로 스크립트 실행 여부만 보는 것이다.
경고

공개 문서에는 동작 확인 수준(무해한 alert)까지만 기록하고, 쿠키 탈취처럼 실제 피해로 이어지는 페이로드는 게시하지 않는다. 원리 이해가 목적이다.

DVWA 난이도 비교​

DVWA의 Low/High 소스를 비교하면, 어떤 처리가 빠졌을 때 취약해지는지 한눈에 보인다.

// Low: 입력을 그대로 출력 → 취약
echo '<pre>Hello ' . $_GET['name'] . '</pre>';

// High: 출력 시 인코딩 → 안전
echo '<pre>Hello ' . htmlspecialchars($_GET['name']) . '</pre>';

3. AI로 해석하기​

실습에서 얻은 요청/응답을 AI(Claude)에게 주고 다음을 묻는다.

  • "이 응답에서 내 입력이 어디에, 어떤 형태로 출력됐는지 짚어 줘"
  • "이 위치는 HTML 컨텍스트인가, 속성인가, 자바스크립트 컨텍스트인가?"
  • "왜 이 입력이 코드로 실행됐는지 원리를 설명해 줘"

:::tip AI 활용 포인트 XSS 대응은 출력 컨텍스트(HTML 본문/속성/JS/URL)에 따라 인코딩 방식이 달라진다. AI는 "지금 이 출력이 어떤 컨텍스트인지" 판단을 도와주는 데 유용하다. 단, 판단 결과는 직접 재현해 확인한다. :::

4. 대응​

대응설명
출력 인코딩출력 컨텍스트에 맞게 인코딩 (HTML: htmlspecialchars 등). 가장 핵심
입력 검증허용 목록(allowlist) 기반 검증. 보조 수단
CSPContent-Security-Policy 헤더로 인라인 스크립트 실행 제한
HttpOnly 쿠키세션 쿠키에 HttpOnly → 스크립트의 쿠키 접근 차단
프레임워크 기본값최신 프레임워크의 자동 이스케이프 기능 활용 (임의로 끄지 않기)
Content-Security-Policy: default-src 'self'; script-src 'self'
Set-Cookie: session=...; HttpOnly; Secure; SameSite=Lax

5. 점검 체크리스트​

  • 사용자 입력이 출력되는 모든 지점을 식별했는가
  • 각 출력 지점의 컨텍스트에 맞는 인코딩이 적용됐는가
  • CSP 헤더가 설정되어 있는가
  • 세션 쿠키에 HttpOnly가 적용됐는가
  • 프레임워크의 자동 이스케이프를 임의로 끄지 않았는가

참고​

  • OWASP: Cross-Site Scripting (XSS)
  • OWASP: XSS Prevention Cheat Sheet