728x90
반응형
1️⃣ CSRF란?
- CSRF = Cross-Site Request Forgery
- 한국말로 하면 사이트 간 요청 위조
- 공격자가 사용자의 인증 정보를 이용해서 몰래 요청을 보내는 공격이에요.
핵심 포인트
- 사용자는 이미 로그인 상태
- 공격자는 사용자를 속여 자신이 원하는 요청을 서버에 보내도록 유도
- 서버는 요청이 정상 사용자 요청으로 인식 → 공격 성공
즉, **“사용자의 권한을 도용해서 몰래 행동시키는 공격”**이에요.
2️⃣ 예시
- 은행 사이트: https://bank.com/transfer?to=attacker&amount=1000
- 사용자가 은행에 로그인한 상태
- 공격자가 만든 사이트에 접속 →
<img src="https://bank.com/transfer?to=attacker&amount=1000">
- 브라우저가 로그인 쿠키를 포함해 자동 요청
- 돈이 공격자 계좌로 이체됨 😱
- 사용자는 모르는 사이에 요청이 실행됨
- 서버는 “로그인된 사용자의 요청”으로 착각
3️⃣ CSRF 공격 조건
- 사용자가 로그인 상태이어야 함 (세션/쿠키 등 인증 정보 존재)
- 서버가 요청을 추가 검증 없이 바로 처리
- 공격자가 HTML/스크립트 등을 통해 사용자 브라우저에 요청을 유발할 수 있어야 함
4️⃣ 방어 방법
- CSRF 토큰 사용
- 서버가 랜덤 토큰 발급 → 폼 제출 시 함께 보내야 함
- 서버는 토큰이 맞는지 확인 → 위조 요청 차단
- SameSite 쿠키
- 쿠키에 SameSite=Strict 또는 Lax 설정 → 외부 사이트에서 요청 시 쿠키 전송 차단
- Referer/Origin 체크
- 요청이 정상 도메인에서 왔는지 확인 → 외부 사이트 요청 차단
- POST 요청만 처리
- 민감 작업(GET 아닌 POST)으로 처리 → 단순 이미지 요청으로는 실행 불가
5️⃣ 요약
- CSRF = 사용자가 모르게 인증된 상태로 서버 요청을 위조당하는 공격
- 주로 폼 제출, 계좌 이체, 설정 변경 등 민감한 작업에서 위험
- 방어: CSRF 토큰 + SameSite 쿠키 + Origin/Referer 체크
여기서 말하는 Referer는 바로 HTTP 요청 헤더에 있는 Referer(원래는 Referrer 오타에서 유래)입니다. 😄
1️⃣ Referer 헤더란?
- 클라이언트(브라우저)가 서버에 요청을 보낼 때 “내가 지금 어디서 왔는지” 알려주는 헤더입니다.
- 서버 입장에서는 **요청 출처(URL)**를 확인할 수 있어요.
예시 요청:
GET /submit-form HTTP/1.1
Host: ticket.example.com
Referer: https://ticket.example.com/form-page
- 여기서 Referer는 사용자가 어떤 페이지에서 이 요청을 보냈는지 나타냅니다.
- 보통 HTML 폼 제출, 링크 클릭, 이미지 로딩 등에서 자동으로 포함됩니다.
2️⃣ CSRF 방어에서의 역할
- 서버는 민감 요청이 자기 도메인에서 온 건지 확인 가능
- 예: 티켓팅 서버에서 POST 요청이 들어오면, Referer가 ticket.example.com이면 정상, 외부 사이트이면 차단
장점
- 외부 공격자가 몰래 보내는 요청은 대부분 다른 도메인에서 발생 → Referer 체크로 차단 가능
단점
- 브라우저 설정이나 일부 프라이버시 정책 때문에 Referer가 없을 수도 있음
- HTTPS → HTTP 리퍼러 전송 금지, 프록시·방화벽에서 제거 가능
- 따라서 Referer만 의존하면 안 되고, CSRF 토큰 등 다른 방어와 병행해야 함
3️⃣ 정리
- Referer = HTTP 요청 헤더, 요청 출처(URL) 정보
- CSRF 방어에서 “정상 도메인에서 요청한 건가?” 판단하는 단서로 사용
- 단독 방어는 부족 → CSRF 토큰과 함께 사용해야 안전
더보기
1️⃣ 기본 원칙
- Referer 헤더는 HTTP와 HTTPS 요청 모두에서 기본적으로 포함 가능합니다.
- 즉, HTTPS 페이지에서 다른 HTTPS 페이지로 요청을 보내도 Referer는 정상 전송됩니다.
2️⃣ 단, 보안·프라이버시 규칙 때문에 달라짐
- HTTPS → HTTP 요청
- 브라우저는 보안 위험 때문에 기본적으로 Referer를 전송하지 않음
- HTTPS 페이지에서 HTTP로 요청하면 도메인은 보이지만, URL 전체는 제거되거나 아예 안 보내는 경우 있음
- HTTPS → HTTPS 요청
- 기본적으로 Referer 전송 가능
- 다만 일부 브라우저나 사이트에서 Referrer Policy 설정에 따라 달라질 수 있음
3️⃣ Referrer Policy
- HTML <meta> 태그나 HTTP 헤더로 브라우저에 Referer 전송 방식을 지시할 수 있음
| 정책 | 설명 |
| no-referrer | 아예 Referer 헤더를 보내지 않음 |
| origin | |
| strict-origin-when-cross-origin (기본값 현대 브라우저) |
HTTPS→HTTP는 제거 HTTPS→HTTPS는 전체 URL 전송, 같은 출처는 전체 URL 전송 |
| same-origin | 같은 출처일 때만 Referer 전송 |
- 즉, HTTPS에서도 Referer가 안 올 수 있음 → 서버에서 체크만 의존하면 안 됨
4️⃣ 정리
- HTTP와 HTTPS 모두 Referer 헤더를 포함할 수 있음
- 단, HTTPS → HTTP 요청이나 Referrer Policy 설정 때문에 안 올 수 있음
- CSRF 방어용으로는 Referer만 의존하지 않고 CSRF 토큰 + SameSite 쿠키와 함께 사용하는 것이 안전
1️⃣ 브라우저에서의 쿠키 저장 위치
- 메모리(Memory)
- 브라우저가 실행되는 동안만 유지되는 쿠키
- 브라우저 종료 시 사라짐 → 세션 쿠키(session cookie)
- 디스크(Disk / Profile 폴더)
- 브라우저 프로필 디렉터리에 파일로 저장
- 브라우저 종료 후에도 유지 → 영속 쿠키(persistent cookie)
- 예: Chrome: User Data\Default\Cookies (SQLite DB 형식)
2️⃣ 쿠키 속성에 따른 저장/전송
| 속성 | 설명 | 저장 여부 / 전송 조건 |
| HttpOnly | JS에서 접근 불가 | 브라우저 내부에서만, 요청 시 자동 전송 |
| Secure | HTTPS에서만 전송 | HTTP 요청 시 전송되지 않음 |
| SameSite | CSRF 방어용, 외부 도메인에서 자동 전송 제한 | |
| Expires / Max-Age | 만료 시간 지정 | 세션 쿠키: 브라우저 종료 시 삭제 영속 쿠키: 지정 시간까지 유지 |
3️⃣ 로그인 쿠키 동작
- 로그인 후 서버가 Set-Cookie 헤더를 보냄:
Set-Cookie:
sessionid=abc123;
HttpOnly;
Secure;
SameSite=Lax;
Path=/;
Max-Age=3600
- 브라우저가 쿠키를 저장
- 세션 쿠키라면 메모리에, 영속 쿠키라면 디스크에 저장
- 이후 같은 도메인 요청 시 브라우저가 자동으로 쿠키 포함 → 서버에서 로그인 상태 유지
4️⃣ 브라우저 외 환경
- 모바일 앱 / 웹뷰: 자체 스토리지 또는 앱 전용 쿠키 저장소
- 헤드리스 브라우저 / 자동화 스크립트: 런타임 메모리 저장, 코드에서 조작 가능
5️⃣ 핵심 요약
- 로그인 쿠키 = 서버가 발급한 인증 정보
- 브라우저 내부 메모리 또는 디스크에 저장
- HttpOnly, Secure, SameSite 속성에 따라 접근과 전송 조건 달라짐
- 쿠키가 있어야 세션/로그인 상태 유지 → 대기열, 제출, CSRF 방어 등 가능
쿠키 저장 위치와 메모리/디스크 차이를 정확히 정리해 드릴게요. 😄
1️⃣ 브라우저 프로필 디렉터리
- HDD/SSD에 있는 브라우저 전용 폴더를 말합니다.
- 예시:
- Chrome (Windows):
C:\Users\<사용자>\AppData\Local\Google\Chrome\User Data\Default\ - Firefox (Windows):
C:\Users\<사용자>\AppData\Roaming\Mozilla\Firefox\Profiles\<프로필폴더>\
- Chrome (Windows):
- 이 폴더 안에 쿠키, 캐시, 북마크, 세션 정보, 확장 프로그램 데이터 등이 파일로 저장됨.
- 즉, **영속 쿠키(persistent cookie)**는 이 디렉터리에 있는 파일(SQLite 등)로 저장되어 브라우저 종료 후에도 유지됩니다.
2️⃣ 세션 쿠키(Session Cookie)와 메모리 저장
- 세션 쿠키는 브라우저가 실행 중일 때 **메모리(RAM)**에 저장됩니다.
- RAM = 휘발성 메모리 → 브라우저 종료하거나 컴퓨터 전원 끄면 사라짐
- “flash”라고 말씀하신 건 SSD/HDD 등 비휘발성 저장장치를 의미하는데, 세션 쿠키는 여기 저장되지 않아요.
- 즉 세션 쿠키는 임시 저장, 휘발성이며 RAM 내부에 존재한다고 이해하면 됩니다.
3️⃣ 요약
| 쿠키 종류 | 저장 위치 | 유지 여부 |
| 세션 쿠키 | 브라우저 실행 중 RAM | 브라우저 종료 시 삭제 |
| 영속 쿠키 | 브라우저 프로필 폴더 (HDD/SSD) C:\Users\<사용자명>\AppData\Local\Google\Chrome\UserData\Default |
지정 만료일까지 유지 |
- 브라우저가 RAM에 세션 쿠키를 올려두는 이유: 빠른 접근과 보안
- 디스크에 저장하면 브라우저 종료 후에도 남지만, 보안상 민감 정보는 주로 세션 쿠키(RAM)로 처리
즉, 세션 쿠키 = RAM(휘발성), 영속 쿠키 = HDD/SSD(비휘발성) 이렇게 생각하면 이해하기 쉽습니다.
1️⃣ 세션 쿠키(RAM)에 저장되는 민감 정보
세션 쿠키는 **휘발성(RAM)**에 저장되기 때문에 브라우저 종료 시 사라지지만,
그 안에는 보안상 중요한 정보가 담길 수 있어요.
일반적으로 다음과 같은 것들이 있습니다:
| 정보 종류 | 설명 |
| 세션 ID | 서버에서 로그인 상태를 식별하는 유일 값. (sessionid=abc123 같은 형태) |
| CSRF 토큰 | 폼 제출 시 서버가 요청 위조를 막기 위해 발급한 랜덤 값. |
| JWT 또는 액세스 토큰 | OAuth/OpenID 등 인증용 토큰. 서버에서 서명 검증으로 유효성 판단. |
| 사용자 임시 상태 | 대기열 번호, 폼 진행 상태, 장바구니 등. 서버와 연동되어야 함. |
요약: 로그인 상태와 민감 요청 인증용 정보가 대부분이고, RAM에만 존재하므로 브라우저 종료 시 자동으로 소멸됩니다.
2️⃣ 디스크에 저장되는 영속 쿠키(Persistent Cookie)
영속 쿠키는 **만료일(Expires / Max-Age)**이 설정되어 있어야 유효 기간을 서버/브라우저가 판단합니다.
- 만료일 지정 있음 → 해당 날짜/시간까지 유지 후 자동 삭제
- 만료일 지정 없음 → 사실상 세션 쿠키 취급, 브라우저 종료 시 삭제
즉, “영속 쿠키 = 평생 저장”은 아니고, 만료일을 명시해야 실제로 장기 저장 가능합니다.
- 브라우저에 따라 영속 쿠키 저장 위치: SQLite DB 파일 등 (Chrome: User Data\Default\Cookies)
- 보안상 민감 정보(로그인 토큰 등)를 영속 쿠키에 담으면 위험 → 탈취 시 장기적으로 악용 가능
3️⃣ 핵심 포인트 요약
- 세션 쿠키(RAM): 로그인 세션, CSRF 토큰, JWT 등 민감 정보 → 브라우저 종료 시 소멸
- 영속 쿠키(HDD/SSD): 만료일 설정한 경우만 장기 저장, 없으면 브라우저 종료 시 사라짐
- 보안 관점: 민감 정보는 RAM 세션 쿠키로 유지, 장기 저장은 최소화 또는 암호화/보호
1️⃣ 만료일(Expires / Max-Age) 지정 주체
- 서버가 쿠키를 발급할 때 지정하는 것이 일반적입니다.
- HTTP 응답 헤더에서 Set-Cookie를 통해 서버가 브라우저에 “이 쿠키는 언제까지 유효”를 알려줌.
예시:
Set-Cookie:
sessionid=abc123;
Expires=Wed, 09 Oct 2025 23:59:59 GMT;
Path=/;
Secure;
HttpOnly
- Expires = 쿠키 만료 날짜/시간
- 또는
Set-Cookie:
sessionid=abc123;
Max-Age=3600;
Path=/;
Secure;
HttpOnly
- Max-Age = 쿠키가 발급된 시점부터 유효한 초 단위 기간 (3600초 = 1시간)
2️⃣ 클라이언트가 직접 만료일 지정할 수 있나?
- 브라우저 개발자 도구에서 수정 가능
- 예: Chrome → 개발자 도구 → Application → Cookies → 만료일 편집 가능
- 하지만 일반 사용자가 임의로 바꾸면 서버에서 발급한 토큰/세션이 유효하지 않으면 무용지물
- JS에서 생성하는 쿠키는 document.cookie로 만료일 설정 가능:
document.cookie = "username=Alice; max-age=3600; path=/";
- 단, HttpOnly 속성이 붙은 쿠키는 JS에서 접근/설정 불가
- 민감한 세션 쿠키/로그인 쿠키는 서버 발급 + HttpOnly 속성이므로 클라이언트가 직접 바꿀 수 없음
3️⃣ 요약
| 항목 | 서버 발급 | 클라이언트 설정 |
| 로그인/세션 쿠키 | ✅ 만료일 지정 가능 (세션쿠키) | ❌ 일반적으로 못 바꿈 (HttpOnly) |
| 일반/사용자 쿠키 | ✅ (세션쿠키) / ❌ (영속쿠키) | ✅ JS에서 설정 가능 |
| 장기 보존 여부 | 서버 결정 | 클라이언트 임의 변경 가능하지만 의미 없음 |
- 즉, 로그인/세션 쿠키 만료일은 서버가 통제하며, 클라이언트가 바꾸더라도 서버 검증을 통과하지 못하면 의미가 없습니다.
1️⃣ Domain과 Path의 기본 의미
| 속성 | 의미 | 쿠키 적용 범위 |
| Domain | 쿠키를 전송할 서버 도메인 | 지정한 도메인과 그 하위 도메인에서만 브라우저가 쿠키를 서버로 전송 |
| Path | 도메인 내에서 쿠키가 유효한 URL 경로 | 지정한 경로 또는 그 하위 경로에서만 브라우저가 쿠키 전송 |
2️⃣ 예시
2-1) Domain
Set-Cookie:
sessionid=abc123;
Domain=example.com;
Path=/
- 쿠키는 example.com과 sub.example.com으로 요청할 때 브라우저가 자동 전송
- 다른 도메인(other.com) 요청에는 전송되지 않음
2-2) Path
Set-Cookie:
cart=xyz;
Domain=example.com;
Path=/shop
- 쿠키는 https://example.com/shop과 그 하위 경로(/shop/item) 요청에만 전송
- https://example.com/blog 요청에는 전송되지 않음
3️⃣ Path와 Domain 차이 핵심
- Domain = 서버 단위, “어느 도메인으로 쿠키를 전송할 수 있는가”
- Path = URL 단위, “도메인 안에서 어떤 경로로 요청할 때 쿠키를 포함할 것인가”
- Path가 /이면 도메인 전체 경로에서 쿠키 사용 가능
- Path가 /shop이면 /shop과 하위 경로에서만 쿠키 전송 → 서버가 경로별로 쿠키 분리 가능
4️⃣ 왜 필요한가?
- 보안: 민감 쿠키를 특정 경로/도메인에서만 전송하게 제한
- 기능 분리: 장바구니 쿠키는 /shop에서만, 블로그 설정 쿠키는 /blog에서만 사용 가능
정리하면:
- Domain → 어떤 도메인/하위 도메인에 전송되는지
- Path → 도메인 안에서 어떤 URL 경로에 전송되는지
Domain과 SameSite가 겹치는 것처럼 보여도 목적과 동작이 완전히 달라서 둘 다 필요합니다. 하나씩 차이를 짚어볼게요.
1️⃣ Domain 속성
- **“어느 도메인/하위 도메인으로 요청할 때 쿠키를 보내는지”**를 지정
- 예:
Set-Cookie: sessionid=abc123; Domain=example.com; Path=/
- 브라우저는 example.com과 sub.example.com으로 요청할 때만 쿠키를 포함
- 사이트 간 요청 자체는 막지 않음 → 공격자가 iframe, form, image 등으로 요청 보내도 Domain만 맞으면 쿠키 전송됨
2️⃣ SameSite 속성
- **“쿠키를 전송할 요청이 같은 사이트에서 발생했는지”**를 기준으로 전송 여부 결정
- 세 가지 모드:
| 모드 | 설명 |
| Strict | 외부 사이트에서 발생한 요청에서는 쿠키 전송 금지 (CSRF 공격 방지용) |
| Lax | 안전한 메서드(GET 등)에서는 전송 허용, 위험한 메서드(POST)는 외부 사이트에서 전송 금지 |
| None | 외부 사이트에서도 전송 허용 (Secure 옵션 필요) |
- 핵심: 도메인은 맞지만 “사이트 출처(origin)”가 다르면 쿠키 전송 차단 가능
- 예: 공격자가 iframe/자동 form 제출로 POST 요청을 보내도 SameSite=Strict/Lax면 쿠키 전송 안 됨 → CSRF 방어 가능
3️⃣ Domain vs SameSite 비교
| 속성 | 기준 | 역할 |
| Domain | 서버 도메인 | 어느 도메인 요청에 쿠키를 포함할지 결정 |
| SameSite | 사이트 출처(origin) | 사이트 간 요청(CSRF, 외부 요청)에서 쿠키 전송 제한 |
- Domain = 어디로 전송할 수 있는가
- SameSite = 외부 사이트에서 보내는 요청에 전송할 것인가
4️⃣ 왜 둘 다 필요한가?
- Domain만 있으면:
- 공격자가 다른 사이트에서 form/iframe/image로 요청 보내도 쿠키 전송 가능
- → CSRF 공격에 취약
- SameSite만 있으면:
- Domain이 다른 도메인 요청에 대해 아예 쿠키를 전송하지 않음
- 그러나 서버가 동일 도메인에서 여러 하위 도메인을 운영하면, Domain 설정으로 어느 도메인에 쿠키를 전송할지 제어 가능
ㅇ즉, Domain = 범위 제어, SameSite = 사이트 간 전송 제어로 역할이 다르기 때문에 둘 다 필요합니다.
- Domain
- 서버 도메인 기준
- “이 쿠키를 어느 서버(도메인/하위 도메인)로 전송할 수 있는가”를 결정
- 서버 입장에서 쿠키 전송 범위를 지정
- SameSite
- 요청을 생성한 클라이언트 사이트(origin) 기준
- “이 쿠키를 외부 사이트 요청에서 전송할 것인가”를 결정
- CSRF 방어용, 사이트 간 전송 제한
즉,
- Domain = 쿠키가 어디로 가는지
- SameSite = 쿠키를 누가 보냈는지(같은 사이트인지) 확인
둘은 서로 다른 기준이어서, 둘 다 있어야 안전하게 쿠키 전송 범위를 제어할 수 있어요.
728x90
반응형
'네트워크2' 카테고리의 다른 글
| XML vs HTML 차이점 비교 :: HyperText 란? Markup 이란? (0) | 2025.10.07 |
|---|---|
| 네트워크 탭에서 내가 보낸 요청 확인 방법 (0) | 2025.10.07 |
| HTTP :: 요청 헤더 / 응답 헤더 (0) | 2025.10.07 |
| 쿠키(Cookie) 와 세션(Sessoion) (0) | 2025.10.07 |
| HTTP 요청/응답 (서버와 통신) :: XHR vs fetch vs Axios (0) | 2025.10.04 |
| 브라우저 업로드 진행률 표시 XHR / fetch :: 콜백 vs Promise, async/await (0) | 2025.10.04 |
| 쿼리 파라미터 ?key=value&key=value :: 웹 서버에서 처리 과정 (0) | 2025.10.03 |
| 불법 사이트 안 걸리는 이유 vs 걸리는 이유 (0) | 2025.10.03 |