목차
- [[#1. URI / URL / URN 개념 정리]]
- [[#2. Cookie - 클라이언트에 상태를 저장하다]]
- [[#3. Session - 서버에 상태를 저장하다]]
- [[#4. Token 기반 인증과 JWT]]
- [[#5. 실습 - Set-Cookie와 쿠키 보안 속성]]
- [[#6. 실습 - 세션 하이재킹 (쿠키 재생 공격)]]
1. URI / URL / URN 개념 정리
graph TD
URI[URI - 리소스를 식별하는 모든 방법] --> URL[URL - 리소스의 위치를 표현]
URI --> URN[URN - 리소스의 이름을 표현]
| 용어 | 정의 | 예시 |
|---|---|---|
| URI (Uniform Resource Identifier) | 인터넷상의 리소스를 식별하는 총칭 | - |
| URL (Uniform Resource Locator) | 리소스의 위치(어디에 있는지)를 표현. 우리가 흔히 쓰는 웹 주소 | https://example.com/login |
| URN (Uniform Resource Name) | 리소스의 이름(무엇인지)을 표현. 위치가 바뀌어도 값은 유지 | urn:isbn:0451450523 |
2. Cookie - 클라이언트에 상태를 저장하다
HTTP는 매 요청마다 응답하는 구조(stateless)라, 로그인 상태 같은 정보를 유지하려면 별도 저장 수단이 필요하다. 그래서 등장한 것이 쿠키.
- 쿠키는 서버가 생성하고 클라이언트(브라우저)에 저장된다.
- 매 요청(TCP 세션)마다 클라이언트가 다시 쿠키를 실어 보내므로, 서버는 매번 로그인 절차를 반복하지 않아도 된다.
Persistent Cookie vs Session Cookie
| 구분 | 저장 위치 | 만료 시점 |
|---|---|---|
| Persistent Cookie | 디스크(하드디스크)에 저장 | Set-Cookie에 명시된 Expires/Max-Age 날짜가 되면 만료 |
| Session Cookie | 메모리에만 저장 | Expires/Max-Age가 없는 쿠키. 브라우저를 종료하면 즉시 삭제 |
Cookie 기반 인증의 문제점
- 쿠키에 사용자 인증 정보가 담기기 때문에, 탈취 당하면 그대로 로그인 도용으로 이어짐
- HTTP 요청 스니핑/가로채기를 당하면 쿠키 값이 그대로 노출됨
- 쿠키 크기가 커지면 매 요청마다 같이 전송되어 네트워크 트래픽 과부하를 유발할 수 있음
- (보완) 브라우저가 쿠키를 자동으로 실어 보내는 특성 때문에 CSRF(Cross-Site Request Forgery) 공격에도 취약해질 수 있음 — 이건 뒤에 나오는
SameSite속성으로 방어
3. Session - 서버에 상태를 저장하다
쿠키와 반대로, 실제 데이터는 서버에 저장하고 클라이언트에는 이를 식별할 세션 ID만 쿠키로 내려주는 방식.
sequenceDiagram
participant C as 클라이언트
participant S as 서버(세션 저장소)
C->>S: 로그인 요청 (ID/PW)
S->>S: 세션 생성 + 세션ID 발급
S-->>C: Set-Cookie: 세션ID
C->>S: 이후 요청 시 세션ID 쿠키 첨부
S->>S: 세션 저장소와 세션ID 대조
S-->>C: 인증된 사용자로 응답
[!note]- 세션 쿠키 예시
Cookie: ASPSESSIONIDCSTBCQTA=NMKNEGOCOPKOFBCGDJDIHJHO
- 실제 개인정보/인증 데이터가 클라이언트가 아닌 서버 저장소에 있기 때문에 쿠키 단독 저장 방식보다 보안이 상대적으로 우수
- 다만 세션 ID 자체가 탈취되면 여전히 위험하므로 주기적 갱신 + 유효 시간 설정이 필요
- 금융권은 보안 요구 수준이 높아 세션 유효 시간을 약 10분 수준으로 짧게 잡는 경우가 많음
Session Hijacking (개념)
- 공격자가 유효한 세션ID를 탈취하면, 로그인 없이 해당 사용자로 위장할 수 있다.
- 세션 ID의 유효시간(타임아웃) 설정이 이 위험을 완화하는 핵심 대응책 중 하나 (실습은 6절에서 진행)
4. Token 기반 인증과 JWT
Token 기반 인증
- 클라이언트가 ID/PW로 로그인하면, 서버는 토큰을 발급해 클라이언트에 내려준다.
- 서버가 세션 저장소를 유지할 필요가 없어 서버 부담이 줄고 확장성(scalability)이 좋아짐 → 클라우드/분산 서버 환경에 적합
- 여러 플랫폼/서비스 간 권한 공유(SSO 등)가 쉬움
- 세션ID보다 무효화(revocation) 처리가 유연해 상대적으로 안전하다고 평가됨
JWT (JSON Web Token)
공식 문서/디버거: https://www.jwt.io/
[!note]- JWT 구조 예시
Encoded Token eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTUxNjIzOTAyMn0.KMUFsIDTnFmyG3nMiGM6H9FNFUROf3wh7SmqJp-QV30 // Decoded Header { "alg": "HS256", "typ": "JWT" } // Decoded Payload { "sub": "1234567890", "name": "John Doe", "admin": true, "iat": 1516239022 } a-string-secret-at-least-256-bits-long // Secret Key
JWT는 점(.)으로 구분된 3개 파트로 구성된다.
| 파트 | 내용 |
|---|---|
| Header | 서명에 사용할 암호화 알고리즘 등의 옵션 (alg, typ) |
| Payload | 인증에 필요한 실제 정보(Claims) — 예: ID, 이름, 권한 |
| Signature | Header + Payload를 Secret Key로 서명한 값. 무결성 검증에 사용 |
JWT 관련 대표 취약점 (보완)
| 취약점 | 설명 |
|---|---|
alg: none 공격 |
서버가 알고리즘 검증을 제대로 안 하면, 헤더의 alg를 none으로 바꿔 서명 없이 위변조된 토큰을 통과시킬 수 있음 |
| Payload 평문 노출 | 암호화가 아니므로 비밀번호, 주민번호 같은 민감정보는 Payload에 절대 넣으면 안 됨 |
| Secret Key 취약 | HS256 등 대칭키 방식에서 Secret Key가 짧거나 예측 가능하면 브루트포싱으로 서명 위조 가능 |
| 만료(exp) 미검증 | 서버가 exp 클레임을 확인하지 않으면 탈취된 토큰이 영구적으로 유효해짐 |
5. 실습 - Set-Cookie와 쿠키 보안 속성
Act 1. 기본 쿠키 삭제 후 재발급 확인
Burp에서 Request 영역의 쿠키 값을 임의로 삭제한 뒤 Intercept로 요청을 전달하면, 서버가 새로운 쿠키를 재발급하는 것을 확인할 수 있다.
Act 2. 브라우저 저장소 구조 (F12 → Application)
개발자 도구의 Application 탭 상단에는 Local Storage / Session Storage / Extension Storage 등이 표시된다. 저장해야 할 데이터가 많아지면서 쿠키 외에 이런 저장소들이 추가로 생겨난 것.
| 저장소 | 서버 전송 여부 | 만료 | 용량 |
|---|---|---|---|
| Cookie | 매 요청마다 자동 전송 | 설정한 Expires/Session 종료 시 | 약 4KB |
| Local Storage | 전송 안 됨 (JS로만 접근) | 명시적으로 지우기 전까지 영구 | 약 5~10MB |
| Session Storage | 전송 안 됨 (JS로만 접근) | 탭/창을 닫으면 삭제 | 약 5~10MB |
서버가 발급(구워준)한 쿠키는 클라이언트에 저장되고, 이후 접속마다 브라우저가 해당 쿠키를 실어서 세션을 유지한다.
Set-Cookie 문법과 보안 속성
Set-Cookie: 쿠키이름=쿠키값; Expires=날짜; Path=경로; Secure; HttpOnly; SameSite=Lax
| 속성 | 설명 | 방어 대상 |
|---|---|---|
| Secure | 해당 쿠키는 HTTPS 연결에서만 전송 | 네트워크 스니핑 차단 |
| HttpOnly | 해당 쿠키는 자바스크립트(document.cookie)로 접근 불가 |
XSS 공격 방어 |
| SameSite | 다른 도메인(Cross-site)에서의 요청 시 쿠키 전송 여부 통제 | CSRF 공격 방어 |
SameSite 옵션 상세
| 값 | 동작 |
|---|---|
Strict |
같은 도메인 요청에만 쿠키 전송 (가장 엄격) |
Lax |
기본적으로 타 도메인 전송은 막되, 링크 클릭 등 최상위 탐색(top-level navigation)은 허용. 현대 브라우저의 기본값 |
None |
타 도메인 요청에도 항상 쿠키 전송 (반드시 Secure와 함께 써야 함) |
6. 실습 - 세션 하이재킹 (쿠키 재생 공격)
시나리오
스니핑을 통해 정상 사용자(A)가 로그인한 상태의 세션 쿠키를 탈취했다고 가정.
탈취한 쿠키 값: NMKNEGOCOPKOFBCGDJDIHJHO
공격 흐름
sequenceDiagram
participant A as 정상 사용자 A
participant Atk as 공격자
participant S as 서버
A->>S: 로그인
S-->>A: Set-Cookie: SESSIONID=NMKNEGOCOPKOFBCGDJDIHJHO
Atk->>Atk: 네트워크 스니핑으로 쿠키 탈취
Atk->>S: Cookie: SESSIONID=NMKNEGOCOPKOFBCGDJDIHJHO (재생)
S-->>Atk: A로 인증된 응답 (로그인 없이 접근 성공)
Burp에서는 탈취한 세션 쿠키 값을 Repeater나 Intercept로 요청 헤더에 그대로 삽입 후 재전송하여 로그인 절차 없이 해당 세션 권한으로 서버에 접근할 수 있는지 검증한다.
이 공격이 성립하는 조건 / 방어책
| 조건 | 대응 방안 |
|---|---|
| 세션ID가 평문 HTTP로 전송됨 | 전체 트래픽에 HTTPS(TLS) 강제 적용 |
| 세션ID 유효시간이 너무 김 | 짧은 타임아웃 + Idle timeout 설정 |
| 세션ID가 IP/기기 정보와 무관하게 재사용 가능 | 세션 생성 시 User-Agent, IP 등 바인딩하여 이상 접속 탐지 |
| 로그아웃해도 세션이 서버에서 무효화 안 됨 | 로그아웃 시 서버 세션 저장소에서 즉시 폐기(invalidate) |
'웹 · 앱' 카테고리의 다른 글
| 웹 애플리케이션 보안 취약점 (1) | 2026.09.12 |
|---|---|
| DVWA (0) | 2026.09.11 |
| 딥링크(Deep Link) 개념 (0) | 2026.08.15 |
| Burp Suite로 HTTP 기초 세우기 (0) | 2026.08.04 |
| 웹 · 앱 보안 실습 (0) | 2026.08.03 |