← 기술 지식

기술 지식 / 보안 / 입력·웹 보안

쿠키 요청 위조와 스크립트 실행의 다른 경계

SameSite·origin·CSRF 토큰·HttpOnly를 요청 흐름으로 나누고 출력 문맥·HTML 정화·URL 스킴·CSP nonce와 캐시를 설명합니다.

보안 · 원리·구현·운영
기술 지식 트리

브라우저 보안 문제는 쿠키가 요청에 붙는 경계와 데이터가 코드로 해석되는 경계를 따로 분석해야 합니다. 이 노트는 CSRF, XSS, SameSite, 출력 문맥, URL 스킴, CSP가 각각 어느 경로를 제한하는지 요청 흐름으로 연결합니다.

CSRF 요청 위조와 XSS 스크립트 실행의 구분

사용자가 은행에 로그인한 상태에서 다른 사이트를 방문했다고 합시다. 그 사이트가 은행으로 상태 변경 요청을 보내고 브라우저가 은행 쿠키를 자동 첨부하면, 서버가 사용자 의도를 확인하지 않을 때 문제가 됩니다. 이것이 CSRF의 전형적인 경계입니다. 공격자가 응답을 읽을 수 있어야만 성립하는 것은 아닙니다.

반면 게시물의 비신뢰 입력이 우리 사이트의 스크립트로 실행되면 XSS입니다. 같은 origin에서 실행되는 코드는 사용자의 세션으로 요청하거나 화면을 바꿀 수 있습니다. HttpOnly 쿠키의 원문을 직접 읽지 못하더라도 피해가 남습니다. 따라서 CSRF와 XSS는 한 설정으로 함께 해결되는 문제가 아닙니다.

Site·origin 구분과 SameSite 쿠키 범위

origin은 scheme·host·port가 모두 같은지로 구분하고, site는 브라우저가 쿠키의 same-site 여부를 판단할 때 보는 더 넓은 범위입니다. 현대 브라우저의 schemeful site 판단은 대체로 scheme과 등록 가능한 도메인을 기준으로 하므로, 서로 다른 서브도메인은 cross-origin이어도 same-site일 수 있습니다. 그래서 신뢰할 수 없는 형제 서브도메인이 같은 site 범위에 들어오면 SameSite만으로 모든 요청 위조를 막는다고 가정할 수 없습니다.

설정 줄이는 범위 남는 조건
SameSite=Strict cross-site 쿠키 첨부를 강하게 제한 외부 링크 로그인 UX·same-site 위협
SameSite=Lax 많은 cross-site 서브리소스·폼 요청에서 제한 안전 메서드의 최상위 탐색 등 허용 경로
SameSite=None; Secure cross-site 사용 허용 브라우저 추가 제한·별도 CSRF 방어
HttpOnly 스크립트의 쿠키 값 직접 읽기 XSS의 인증된 요청 실행
Secure 일반적으로 HTTPS 전송에 한정 자원 인가·스크립트 안전성

쿠키 속성을 생략했을 때 브라우저가 적용하는 기본 동작과 SameSite=Lax를 명시했을 때의 세부 예외를 하나의 계약으로 간주하지 않습니다. 지원 대상 브라우저에서 최상위 navigation, form, fetch를 각각 실행해 쿠키가 붙는지와 서버가 어떻게 처리하는지를 확인합니다. host-only 쿠키(설정한 host에만 보내는 쿠키)와 적절한 __Host- 제약은 서브도메인으로 쿠키를 넓히는 범위를 줄이는 데 도움이 되지만, Path는 요청 출처를 분리하는 강한 보안 경계가 아닙니다.

상태 변경 요청과 CSRF 의도 검증

방어 선택은 요청이 쿠키 인증을 사용하는지, 상태를 바꾸는지, 공격자가 응답을 읽어야 하는지로 나눕니다. 쿠키 기반 상태 변경에는 SameSite와 별도로 서버 토큰·origin 검사를 두고, Bearer 토큰처럼 자동 첨부되지 않는 인증은 같은 CSRF 설명을 그대로 적용하지 않되 XSS가 토큰 사용을 악용할 수 있는 경계는 계속 검토합니다.

세션에 결합된 CSRF 토큰을 발급하고, 상태 변경 요청에 들어온 토큰이 그 세션의 값과 맞는지 서버에서 확인합니다. double-submit은 쿠키와 요청의 두 값이 같은지만 비교하는 방식으로 끝내지 말고, 공격자가 쿠키를 주입할 수 있는지와 토큰 서명·세션 결합을 포함한 구성을 사용해야 합니다. Origin·Referer는 신뢰할 origin 허용 목록과 비교하고, Fetch Metadata는 요청 맥락을 보는 보조 신호로 사용하되 헤더가 없거나 프록시를 거친 경우의 처리 정책도 정합니다.

CORS는 다른 origin의 스크립트가 응답을 읽거나 특정 요청을 보내는 브라우저 규칙이지 모든 서버 인가나 CSRF를 대체하지 않습니다. GET에 결제·포인트 지급 같은 부수 효과를 넣으면 링크 탐색·프리패치로도 변경이 일어날 수 있습니다. 상태 변경 메서드와 CSRF 방어를 함께 유지합니다.

요청 위조와 코드 삽입은 다른 방어점을 가집니다외부 사이트의 요청. 게시물의 비신뢰 입력. 세션 결합·origin 검사. 출력 문맥·정화·안전한 DOM. 서버 인가·상태 변경: CSP는 추가 실행 제한자동 쿠키 첨부 경계문법 해석 경계허용된 요청코드가 아닌 데이터외부 사이트의 요청게시물의 비신뢰 입력세션 결합·origin 검사출력 문맥·정화·안전한 DOM서버 인가·상태 변경CSP는 추가 실행 제한
요청 위조와 코드 삽입은 다른 방어점을 가집니다 화살표는 비신뢰 입력이 영향을 주는 경로입니다. CSRF 토큰은 요청 의도를 검사하고 출력 인코딩·정화는 데이터가 코드가 되는 지점을 막습니다.
그림을 글로 읽기
  • 외부 사이트의 요청
  • 게시물의 비신뢰 입력
  • 세션 결합·origin 검사
  • 출력 문맥·정화·안전한 DOM
  • 서버 인가·상태 변경: CSP는 추가 실행 제한
  1. 외부 사이트의 요청 → 세션 결합·origin 검사: 자동 쿠키 첨부 경계
  2. 게시물의 비신뢰 입력 → 출력 문맥·정화·안전한 DOM: 문법 해석 경계
  3. 세션 결합·origin 검사 → 서버 인가·상태 변경: 허용된 요청
  4. 출력 문맥·정화·안전한 DOM → 서버 인가·상태 변경: 코드가 아닌 데이터

출력 문맥별 인코딩·정화 방어

단순 텍스트는 프레임워크의 기본 escaping이나 textContent로 넣습니다. HTML 본문·속성·URL·JavaScript 문자열은 다른 문법입니다. HTML용 escape를 한 값을 스크립트 문자열에 붙이는 것이 안전하다는 보장은 없습니다. 가능한 한 동적 script 문자열·innerHTML을 피하고 안전한 API로 구조와 데이터를 나눕니다.

사용자가 제한된 서식 HTML을 작성해야 한다면 유지보수되는 sanitizer의 요소·속성 허용 목록으로 HTML 구조를 먼저 제한합니다. script 태그만 정규식으로 삭제하는 방식은 다른 문맥의 위험한 속성을 남길 수 있으므로 충분하지 않습니다.

링크의 href는 속성 인코딩만으로 끝내지 말고, URL을 파싱한 뒤 허용 스킴인지 확인해야 합니다. 인코딩으로 따옴표를 데이터로 만들 수 있어도 위험한 URL의 의미가 안전한 탐색으로 바뀌는 것은 아닙니다.

상대 URL·base URL·정규화 규칙은 각자 흩어지게 두지 말고 하나의 URL 파서 계약으로 처리합니다.

정화한 결과를 다른 라이브러리가 다시 조합하거나 위험한 속성을 추가하면 최종 DOM의 의미가 바뀔 수 있습니다. 저장 시 한 번 검사했다는 기록만 믿지 말고 실제 출력 경로와 sanitizer 버전 변경 때의 재처리를 고려합니다.

CSP nonce와 신뢰 코드의 실행 위치 제한

CSP nonce는 응답마다 예측하기 어려운 값을 만들고 CSP 헤더와 허용 script 태그에 같은 값을 넣는 방식입니다. 템플릿이 사용자 HTML까지 포함한 모든 script에 nonce를 자동으로 붙이면 공격자 코드도 승인됩니다. nonce를 값의 비밀성만으로 이해하지 말고 누가 실행 허가를 받는지 통제해야 합니다.

캐시된 HTML의 nonce와 새 헤더의 nonce가 다르면 정상 코드가 막힙니다. 반대로 전체 HTML을 같은 nonce로 여러 응답에 장기간 재사용하면 응답별 새 값이라는 설계를 잃습니다. nonce 생성·헤더·본문을 같은 응답 단위로 만들거나, 고정된 정적 코드에 적합한 hash 기반 정책 등 다른 구조를 선택합니다. shared cache에서 사용자별 콘텐츠가 섞이는 문제도 별도로 막습니다.

Report-Only는 보고 모드이며 차단 모드가 아닙니다. 허용된 스크립트의 취약한 DOM 조작이나 지나치게 넓은 출처 허용은 여전히 문제가 됩니다. 정책 위반 보고의 원문·URL·트래픽도 개인정보와 비용을 고려해 제한합니다.

브라우저 요청 경로별 쿠키 첨부·차단 검증

진단 결과는 “쿠키가 붙었는가”와 “서버가 허용했는가”를 분리해 기록합니다. 브라우저가 쿠키를 차단해도 서버의 상태 변경 endpoint가 토큰 없이 허용되면 방어가 완성되지 않고, 쿠키가 붙지 않아도 XSS가 same-origin 요청을 실행할 수 있으므로 두 경로를 따로 확인해야 합니다.

테스트 origin 두 개와 형제 서브도메인을 두고 최상위 링크·폼·fetch·iframe 요청의 쿠키 첨부와 서버 거절을 따로 봅니다. 유효 세션으로 보낸 잘못된 CSRF 토큰, 누락 Origin 정책, 정상 외부 로그인 복귀도 포함합니다.

합성 HTML의 텍스트·속성·링크가 의도한 DOM으로 남는지, 미승인 script가 차단되는지, 승인 script는 실행되는지 검사합니다. 캐시 hit에서도 헤더와 본문 nonce가 맞아야 합니다. 이 노트는 방어 설계와 테스트 목록이며 이 보안 사례들을 실제 브라우저에서 실행했다고 주장하지 않습니다.

후속·관련 개념

이 개념의 확장

함께 읽을 문서

전체 기술 지식
선택 연습 · 관련 질문 4개

질문은 이해를 확인하는 보조 자료입니다. 학습 경로와 문서의 범위는 질문 수와 독립적입니다.