Cookie 보안 플래그 완전 가이드|Secure / HttpOnly / SameSite / __Host-
웹 애플리케이션의 세션 관리에 가장 많이 사용되는 쿠키이지만, 올바르게 설정하지 않으면 세션 하이재킹 (session hijacking), CSRF (cross-site request forgery), XSS를 통한 토큰 탈취 같은 공격을 초래합니다. 본 글에서는 쿠키에 추가해야 할 4가지 주요 플래그 (Secure / HttpOnly / SameSite / __Host- 접두사)의 의미와 구현 시 주의할 점을 정리합니다.
Set-Cookie 헤더 구조
서버가 브라우저에 쿠키를 설정할 때 HTTP 응답에 다음과 같은 헤더를 반환합니다.
Set-Cookie: session_id=abc123; Path=/; Domain=example.com; Expires=Wed, 22 Apr 2026 10:00:00 GMT; Secure; HttpOnly; SameSite=Lax
세미콜론으로 구분된 복수의 속성이 있지만, 크게 나누면 다음 2 종류가 있습니다.
- 스코프 속성: Path / Domain / Expires / Max-Age — Cookie가 언제 어디로 전송되는지 결정
- 보안 속성: Secure / HttpOnly / SameSite — 전송/접근 제한
Secure — HTTPS로만 전송
Secure 속성이 있는 쿠키는 브라우저에서 HTTPS 연결일 때만 서버로 전송됩니다. 없으면 피해자가 http://로 사이트에 접근할 때 쿠키가 평문으로 전송되어 중간자 공격(Man-in-the-Middle)으로 세션 ID가 탈취될 수 있습니다.
철칙: 인증 관련 쿠키에는 반드시 붙이세요. 로컬 개발은 localhost이므로 HTTPS가 아니어도 Secure 쿠키가 전송되지만, 본번의 HTTPS를 전제로 하면 문제없습니다.
HttpOnly — JavaScript에서 접근 불가
HttpOnly를 붙이면 document.cookie로 읽을 수 없게 됩니다. 이로 인해 XSS 공격으로 삽입된 JavaScript가 Cookie를 도용할 수 없게 됩니다.
XSS는 여전히 발생 가능한 취약점이므로 세션 쿠키에는 필수로 생각하세요. JavaScript 측에서 쿠키 값을 읽을 필요가 있는 경우(예: CSRF 토큰), 읽기 전용의 별도 쿠키를 만드는 것이거나 <meta> 태그를 통해 값을 전달하는 것이 원칙입니다.
SameSite — 크로스사이트 요청에서의 전송 제어
SameSite 속성은 CSRF 대책의 핵심입니다. 값은 다음의 3가지입니다:
| 값 | 동작 | CSRF 방어 |
|---|---|---|
Strict | 크로스사이트 요청에는 전혀 보내지 않음 (외부 링크에서 올 때도) | 최강 |
Lax (기본값) | 최상위 GET 네비게이션에서만 전송 (링크 클릭 OK, POST 폼 NG) | 강함 |
None | 모든 크로스사이트 요청으로 전송 (Secure 필수) | 없음 |
2020년 이후의 모던 브라우저는 지정되지 않은 SameSite를 Lax로 취급하므로 명시하지 않아도 최소한의 CSRF 보호를 얻을 수 있습니다. 하지만 의도를 명확히 하기 위해 명시적으로 설정하는 것이 좋습니다.
SSO 연동이나 iframe 임베드에서 SameSite=None을 사용할 경우, 반드시 Secure도 함께 설정해야 하는 것이 현대 브라우저의 요구사항입니다. Secure가 없는 SameSite=None 쿠키는 브라우저에 의해 거부됩니다.
__Host- / __Secure- 접두사
Cookie 이름이 __Host-로 시작하는 경우 브라우저는 다음 3 가지 조건을 강제합니다.
Secure플래그 필수Domain속성을 붙여서는 안 됩니다 (=요청을 보낸 정확한 호스트만)Path=/이어야 함
이들은 「다른 서브도메인에서 덮어쓸 수 없음」「Host 헤더 위조로 임의로 쿠키를 설정할 수 없음」이라는 강력한 보장을 제공합니다. 세션 쿠키에는 __Host-session과 같이 프리픽스를 붙이는 것이 가장 견고합니다.
다른 __Secure- 접두사는 필수 Secure 플래그만 적용합니다 (Domain / Path 제약 없음).
4096 바이트 제한
Cookie의 value는 RFC 6265에서 총 4096 바이트로 권장됩니다. 큰 JSON이나 배열을 Cookie에 담으면 이를 초과할 수 있으며, 브라우저가 조용히 잘라낼 수 있습니다. 큰 데이터는 서버 사이드 세션에 두고, Cookie에는 세션 ID만 넣는 것이 정석입니다.
구현 예시: 인증 세션 쿠키
올바르게 설정된 인증 쿠키는 다음과 같은 형태입니다.
Set-Cookie: __Host-session=eyJ0eXAi...; Path=/; Max-Age=3600; Secure; HttpOnly; SameSite=Lax
__Host-: 서브도메인 오염 및 호스트 위장 방지Path=/: 사이트 전체에서 접근 가능Max-Age=3600: 1시간 후 만료Secure: HTTPS를 통해서만 전송HttpOnly: JavaScript에서 접근 불가SameSite=Lax: 크로스사이트 POST에서 전송되지 않음 (CSRF 보호)
PHP (Laravel) 예제
// config/session.php
return [
'secure' => true, // Secure フラグ
'http_only' => true, // HttpOnly フラグ
'same_site' => 'lax', // SameSite=Lax
'path' => '/',
'cookie' => '__Host-session',
];
Node.js (Express) 예제
const session = require('express-session');
app.use(session({
name: '__Host-session',
secret: process.env.SESSION_SECRET,
cookie: {
secure: true,
httpOnly: true,
sameSite: 'lax',
path: '/',
maxAge: 3600 * 1000,
},
}));
기존 사이트의 Cookie 설정을 확인하는 방법
DevLab의 쿠키 검사 도구를 사용하면 자신의 사이트나 타사 사이트의 쿠키가 올바르게 설정되었는지 즉시 확인할 수 있습니다. URL을 입력하기만 하면 반환된 모든 Set-Cookie 헤더를 분석하고 다음과 같은 진단을 표시합니다.
- 각 Cookie의 Secure / HttpOnly / SameSite 유무
- SameSite=None인데 Secure가 없는 등의 위반
- __Host- 접두사의 일관성
- 4096 바이트 초과 경고
- 전체 요약 (Secure 비율 / HttpOnly 비율 / SameSite 분포)
요약
Cookie 보안 플래그는 임의로 설정하는 것이 아니라, 공격 시나리오와 대응 방안을 이해한 후에 설정하는 것이 중요합니다. 최소한 프로덕션 환경의 인증 세션 Cookie에는 Secure + HttpOnly + SameSite + __Host- 접두사 + 짧은 Max-Age를 붙여야 합니다. 기존 사이트의 설정 재검토에는 Cookie 검사 도구의 사용을 권장합니다.