[SEC-005][기초] XSS와 CSRF를 막는 브라우저 보안 기초 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[SEC-005][기초] XSS와 CSRF를 막는 브라우저 보안 기초

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 243회 작성일 26-09-01 07:36

본문

[이번 수업]

XSS와 CSRF의 차이와 출력 인코딩·CSRF 토큰·CSP 방어를 배웁니다. 로컬 Python으로 출력과 토큰 검증만 연습합니다.

[선수지식]

SEC-001~004의 위협 모델, 인증·인가, 입력 검증과 HTML·HTTP·쿠키의 역할을 알면 따라가기 쉽습니다.

[학습목표]

1. XSS와 CSRF의 발생 조건과 영향을 구분한다.
2. 브라우저의 출처와 동일 출처 정책을 설명한다.
3. HTML 출력 인코딩과 세션별 CSRF 토큰 검증을 구현한다.

[핵심개념]

출처(origin)는 URL의 스킴, 호스트, 포트 조합입니다. 동일 출처 정책은 다른 출처가 보호된 내용을 읽지 못하게 격리하지만 링크 이동이나 폼 전송 같은 모든 요청까지 막지는 않습니다.

XSS(Cross-Site Scripting)는 신뢰하지 않은 값을 글자가 아니라 HTML이나 스크립트로 해석할 때 생기는 코드 주입 문제입니다. 같은 출처에서 실행되므로 페이지 변경이나 사용자 권한의 요청으로 이어질 수 있습니다. 값은 출력 위치에 맞게 인코딩해야 합니다. HTML, 속성, URL, JavaScript, CSS는 규칙이 달라 같은 인코딩을 재사용하면 안 됩니다. 단순 글자는 innerHTML보다 textContent로 표시하고, HTML 허용이 필요할 때만 검증된 정화기를 사용합니다.

CSRF(Cross-Site Request Forgery)는 로그인한 사이트로 원하지 않은 상태 변경 요청을 보내게 하는 요청 위조입니다. 브라우저가 세션 쿠키를 자동으로 붙이는 특성을 악용합니다. 서버는 예측하기 어려운 토큰을 세션에 묶어 제출값과 비교합니다. 상태 변경을 GET으로 처리하지 않고 Origin을 허용 목록과 비교하며, Secure·HttpOnly·SameSite 쿠키를 보조 방어로 사용합니다.

XSS는 같은 출처에서 토큰을 읽거나 정상 요청을 만들 수 있어 CSRF 방어도 약화시킵니다. CSP(Content Security Policy)는 페이지가 불러오거나 실행할 자원을 응답 헤더로 제한하는 추가 안전망입니다. Report-Only로 관찰한 뒤 좁은 정책을 적용하되 출력 인코딩을 생략하지 않습니다.

[따라하기]

아래 내용을 browser_defense.py로 저장합니다. 네트워크 요청 없이 HTML 본문용 인코딩과 토큰 비교를 확인합니다.

```python
from html import escape
from secrets import compare_digest, token_urlsafe

comment = "<b>안녕하세요</b>"
csrf_token = token_urlsafe(32)
submitted_token = csrf_token

print(f"<p>{escape(comment)}</p>")
print("csrf_valid=", compare_digest(csrf_token, submitted_token))
```

macOS·Linux는 `python3 browser_defense.py`, Windows는 `py browser_defense.py`를 실행합니다. py가 없다면 `python browser_defense.py`를 사용하세요. 예상 결과는 다음과 같습니다.

```text
<p>&lt;b&gt;안녕하세요&lt;/b&gt;</p>
csrf_valid= True
```

b 태그가 실행되지 않고 글자로 바뀝니다. 이 인코딩은 HTML 본문용입니다. 실제 앱은 토큰을 세션에 보관하거나 안전하게 서명하고 로그에 남기지 않습니다.

[흔한 실수]

- 입력 검증만 하면 XSS가 사라진다고 생각합니다. 허용된 값도 출력 문맥에 맞게 인코딩해야 합니다.
- 모든 값을 한 번에 공통 인코딩해 HTML·URL·JavaScript 문맥에 재사용합니다.
- CSRF 토큰을 모든 사용자에게 같은 값으로 주거나 쿠키에만 넣고 요청값과 비교하지 않습니다.

[보안 주의]

실습은 본인 소유의 로컬·격리 환경에서만 하며 실제 서비스에 스크립트나 위조 요청을 보내지 마세요. 세션 쿠키에는 Secure·HttpOnly와 흐름에 맞는 SameSite를 설정합니다. 토큰은 안전한 난수로 만들고 로그에 남기지 않습니다. CSP는 unsafe-inline을 습관적으로 허용하지 말고 Report-Only 결과를 검토해 강화하세요.

[직접 해볼 과제]

1. comment를 `5 < 7 & 8 > 3`으로 바꾸고 &, <, >가 어떻게 인코딩되는지 기록하세요.
2. submitted_token을 다른 값으로 바꿔 csrf_valid가 False가 되는지 확인하고, 서버가 이 요청을 거부해야 하는 이유를 한 문장으로 설명하세요.

[확인문제]

1. XSS와 CSRF는 브라우저에서 각각 무엇을 악용하나요?
2. HTML 본문용 인코딩을 URL이나 JavaScript 문맥에 그대로 쓰면 안 되는 이유는 무엇인가요?
3. CSRF 토큰, SameSite 쿠키, Origin 검증을 함께 사용하는 이유는 무엇인가요?

[다음 학습]

SEC-006에서는 SSRF·파일 업로드·경로 조작 방어를 배웁니다.

[공식 참고 자료]

- RFC 6454 웹 출처 개념: https://www.rfc-editor.org/info/rfc6454/
- OWASP XSS 방어 지침: https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
- OWASP CSRF 방어 지침: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
- W3C Content Security Policy Level 3: https://www.w3.org/TR/CSP3/
- Python html 모듈: https://docs.python.org/3/library/html.html
- Python secrets 모듈: https://docs.python.org/3/library/secrets.html

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
1,046
어제
5,103
최대
16,772
전체
772,100
Copyright © 소유하신 도메인. All rights reserved.