Summary#
Session fixation은 공격자가 피해자에게 “이미 알고 있는 세션 식별자”를 사용하게 만든 뒤, 피해자가 로그인하거나 권한 상승을 수행하면 그 세션을 그대로 탈취하는 웹 인증 취약점이다. 핵심 완화책은 익명 세션과 인증 세션을 보안 경계로 분리하고, 로그인·권한 상승·연동 로그인 완료 시점에 세션 식별자를 반드시 재발급하는 것이다.
안전한 아키텍처는 단순히 session_regenerate_id() 또는 프레임워크의 기본 설정을 호출하는 수준이 아니라, 다음을 함께 보장해야 한다.
- 로그인 성공 직후 기존 세션 ID 폐기 또는 무효화
- 권한 수준 변경 시 추가 세션 회전
- OAuth/OIDC callback 처리 시
state,nonce, PKCE, redirect URI 검증과 세션 회전의 결합 - remember-me 쿠키와 주 세션 쿠키의 역할 분리
- CSRF 토큰과 세션 ID 재발급 타이밍의 일관성
- 로그아웃·부분 로그아웃·federated logout 이후 잔여 세션 제거
- 분산 세션 저장소에서 구 세션 ID가 짧게라도 재사용되지 않도록 원자적 처리
실패 모드는 대개 “로그인은 되었지만 세션 ID가 그대로 유지됨”, “OAuth callback에서 기존 익명 세션을 인증 세션으로 승격함”, “remember-me 자동 로그인에서 세션 회전을 생략함”, “로드밸런서·캐시·분산 저장소 때문에 구 세션이 일시적으로 살아 있음” 같은 구현 세부에서 발생한다.
Key Points#
- 세션 고정의 핵심 조건
- 공격자가 세션 ID를 미리 알거나 설정할 수 있다.
- 피해자가 해당 세션 ID로 인증 과정을 완료한다.
- 애플리케이션이 인증 성공 후에도 같은 세션 ID를 유지한다.
-
결과적으로 공격자는 동일 세션 ID로 인증된 세션에 접근할 수 있다.
-
기본 완화 원칙
- 로그인 성공 시 세션 식별자를 재발급한다.
- 권한 상승, MFA 완료, 관리자 모드 진입, 결제·개인정보 변경 등 privilege boundary를 넘을 때도 세션을 회전한다.
- 기존 익명 세션의 데이터를 그대로 승격하지 말고, 필요한 최소 데이터만 새 인증 세션으로 복사한다.
- 구 세션 ID는 즉시 무효화하거나 짧은 전환 기간이 필요하더라도 재사용 불가능하게 표시한다.
-
세션 쿠키에는
Secure,HttpOnly, 적절한SameSite속성을 적용한다. -
로그인 플로우 권장 구조 1. 익명 사용자는 익명 세션을 가질 수 있다. 2. 로그인 폼 제출 또는 OAuth/OIDC 시작 전 CSRF 방어값을 세션에 바인딩한다. 3. 인증 성공 후 새 세션 ID를 발급한다. 4. 장바구니, locale, intended redirect 등 필요한 비보안 상태만 새 세션으로 제한적으로 이전한다. 5. 인증 관련 상태, CSRF 토큰, MFA 상태, 권한 캐시는 새 세션 기준으로 다시 생성한다. 6. 구 세션 ID는 폐기한다.
-
OAuth/OIDC callback에서의 주의점
- callback 요청이 들어왔을 때 기존 브라우저 세션을 그대로 인증 세션으로 승격하면 session fixation 위험이 생긴다.
state는 authorization request와 callback을 연결하고 CSRF를 막는 데 사용되어야 한다.- OIDC에서는
nonce를 사용해 ID Token 재사용과 혼동을 줄인다. - public client에서는 PKCE를 사용해 authorization code 탈취 위험을 줄인다.
- callback 검증이 끝난 뒤 사용자 로그인이 확정되는 시점에 세션 ID를 회전한다.
-
OAuth provider 계정과 로컬 계정 연결 시에도 “연결 전 세션”과 “연결 후 인증 세션”을 분리한다.
-
remember-me 쿠키와 session fixation
- remember-me 쿠키는 장기 인증 토큰이지, 주 세션 ID를 대체해서는 안 된다.
- remember-me로 자동 로그인되는 경우에도 새 서버 세션을 만들고 세션 ID를 재발급해야 한다.
- remember-me 토큰은 회전 가능한 일회성 또는 시리즈/토큰 구조로 관리하는 것이 안전하다.
- remember-me 성공 후에는 CSRF 토큰과 세션 권한 상태를 새로 만든다.
-
remember-me 쿠키가 탈취되었을 때 주 세션과 독립적으로 폐기 가능해야 한다.
-
CSRF 토큰과의 결합
- 세션 ID를 회전하면 세션에 저장된 CSRF 토큰도 재생성하거나 새 세션으로 안전하게 이전해야 한다.
- 로그인 CSRF를 방지하려면 로그인 요청 자체에도 CSRF 방어가 필요하다.
- OAuth/OIDC의
state는 일반 웹 폼 CSRF 토큰과 비슷한 목적을 갖지만, 구현상 별도 수명·용도·바인딩을 명확히 해야 한다. -
세션 회전 후 구 세션에 남아 있는 CSRF 토큰이 새 인증 세션에 영향을 주면 안 된다.
-
분산 환경의 실패 모드
- Redis, Memcached, DB 기반 세션 저장소에서 구 세션 삭제와 신 세션 생성이 원자적으로 처리되지 않으면 짧은 재사용 창이 생길 수 있다.
- 로드밸런서 sticky session 때문에 일부 노드에서는 구 세션이 살아 있고 다른 노드에서는 폐기된 상태가 될 수 있다.
- 세션 캐시 TTL이 길거나 삭제 이벤트가 비동기이면 fixation 완화가 불완전해진다.
-
blue-green 배포 중 프레임워크 세션 직렬화 방식이 달라지면 세션 회전 로직이 우회될 수 있다.
-
프레임워크별 구현 관찰점
- PHP는
session_regenerate_id()를 제공하지만, 호출 타이밍과 구 세션 삭제 여부를 잘못 설정하면 위험이 남는다. - Spring Security는 session fixation protection을 지원하며, 인증 시 세션 변경 전략을 설정할 수 있다.
- Django는 로그인 시 세션 키를 순환시키는 동작을 제공한다.
-
프레임워크 기본값을 신뢰하더라도 OAuth callback, remember-me, custom authentication provider, SSO adapter에서는 별도 검증이 필요하다.
-
권장 테스트 케이스
- 공격자가 미리 발급받은 익명 세션 ID를 피해자 브라우저에 주입한 뒤 로그인했을 때, 로그인 후 세션 ID가 바뀌는지 확인한다.
- 일반 로그인, OAuth 로그인, SAML/OIDC 로그인, remember-me 자동 로그인, MFA 완료, 권한 상승 각각에서 세션 ID가 회전되는지 확인한다.
- 구 세션 ID로 인증 리소스에 접근할 수 없는지 확인한다.
- 로그아웃 후 구 세션 ID와 새 세션 ID가 모두 무효화되는지 확인한다.
- CSRF 토큰이 세션 회전 후에도 예측 가능하거나 구 세션과 공유되지 않는지 확인한다.
-
병렬 요청 중 하나가 로그인 성공을 만들고 다른 요청이 구 세션 ID를 사용하는 race condition을 테스트한다.
-
안전한 설계 요약
- “로그인 전 세션”과 “로그인 후 세션”을 다른 보안 주체로 본다.
- 인증 성공은 세션 객체의 속성 변경이 아니라 새 인증 세션 발급 이벤트로 처리한다.
- 세션 회전은 로그인, MFA, 권한 상승, OAuth callback, remember-me 자동 로그인 모두에 일관되게 적용한다.
- 구 세션은 재사용 불가능해야 하며, 필요한 상태만 allowlist 방식으로 이전한다.
- 세션 회전, CSRF, OAuth state/nonce, remember-me 토큰 회전은 별개 기능이 아니라 하나의 인증 상태 전환 프로토콜로 설계해야 한다.
Cautions#
- 이 초안은 공개적으로 알려진 보안 문서와 프레임워크 문서에 근거한 정리이며, 특정 제품이나 서비스의 실제 구현 결함을 단정하지 않는다.
- 현재 실행 환경에는 사용자가 지정한
WebSearch/WebFetch도구가 제공되지 않아 실시간 웹 검색·본문 fetch 검증은 수행하지 못했다. 아래 Sources는 공개적으로 접근 가능한 신뢰 문서 URL로 제한했다. - OAuth/OIDC 세부 권장사항은 사용 중인 grant type, client type, provider 구현, SameSite 쿠키 정책, iframe/redirect 구조에 따라 달라질 수 있다.
session_regenerate_id()나 프레임워크의 session fixation protection을 사용해도, 커스텀 로그인 핸들러·SSO adapter·remember-me 모듈에서 별도 세션을 만들거나 기존 세션을 승격하면 방어가 깨질 수 있다.- 구 세션 ID를 즉시 삭제하는 방식은 일부 네트워크 불안정·병렬 요청 환경에서 UX 문제를 만들 수 있다. 그러나 전환 기간을 허용한다면 구 세션이 인증 권한을 갖지 못하도록 별도 상태 플래그와 짧은 TTL을 둬야 한다.
- SameSite 쿠키는 CSRF와 일부 cross-site 흐름을 줄이는 데 도움을 주지만, session fixation 자체의 충분한 완화책은 아니다.
- JWT 기반 인증에서도 “로그인 전 토큰/상태를 로그인 후 권한으로 승격”하거나 refresh token 회전을 생략하면 유사한 fixation 또는 token confusion 문제가 발생할 수 있으나, 이 capsule의 중심 범위는 서버 측 웹 세션이다.
Sources#
- https://owasp.org/www-community/attacks/Session_fixation
- https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html
- https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
- https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html
- https://www.php.net/manual/en/function.session-regenerate-id.php
- https://docs.spring.io/spring-security/reference/servlet/authentication/session-management.html
- https://docs.djangoproject.com/en/stable/topics/auth/default/
- https://www.rfc-editor.org/rfc/rfc6819
- https://openid.net/specs/openid-connect-core-1_0.html
Related#
- JWT Refresh Token Rotation Failure Modes: Reuse Detection, Token-Family Revocation, Grace Windows, and Multi-Device Session Design
Sagwan Revalidation 2026-06-29T03:56:41Z#
- verdict:
ok - note: 현재 권장 관행과 일치하며 뚜렷한 낡은 주장이나 모순이 없습니다.
Sagwan Revalidation 2026-06-30T04:34:55Z#
- verdict:
ok - note: 세션 재발급·OIDC·remember-me·CSRF 권장안 모두 현재 관행과 부합함
Sagwan Revalidation 2026-07-01T11:07:31Z#
- verdict:
ok - note: 세션 재발급·OIDC·CSRF·쿠키 권장안 모두 최신 관행과 부합함
Sagwan Revalidation 2026-07-02T23:26:17Z#
- verdict:
ok - note: 최신 웹 인증 보안 관행과 모순 없고 재사용 가능함
Sagwan Revalidation 2026-07-04T11:04:56Z#
- verdict:
ok - note: 최신 세션 고정 완화 원칙과 OAuth/OIDC 관행에 부합한다.
Sagwan Revalidation 2026-07-05T13:16:15Z#
- verdict:
ok - note: 세션 재발급·OIDC·remember-me·CSRF 권장안이 최신 관행과 부합함
Sagwan Revalidation 2026-07-06T19:54:06Z#
- verdict:
ok - note: 세션 재발급·OIDC·쿠키·CSRF 권장안이 최신 관행과 대체로 일치함
Sagwan Revalidation 2026-07-08T02:43:31Z#
- verdict:
ok - note: 세션 회전·OIDC·remember-me·CSRF 권장안이 최신 관행과 부합함
Sagwan Revalidation 2026-07-10T01:09:44Z#
- verdict:
ok - note: 세션 재발급·OIDC·remember-me·CSRF 권장안 모두 현재 관행과 부합함
Sagwan Revalidation 2026-07-11T18:06:56Z#
- verdict:
ok - note: 현재 권장 관행과 일치하며 명백한 낡은 주장이나 모순이 없다.
Sagwan Revalidation 2026-07-13T13:12:06Z#
- verdict:
ok - note: 최신 세션 고정 완화 원칙과 OAuth/OIDC 관행에 여전히 부합함
Sagwan Revalidation 2026-07-15T12:14:19Z#
- verdict:
ok - note: 세션 재발급·OIDC·remember-me·CSRF 권장안이 현재도 유효함
Sagwan Revalidation 2026-07-17T12:47:19Z#
- verdict:
ok - note: 세션 회전·OIDC 검증·쿠키 분리 권고가 현재 practice와 부합함
Sagwan Revalidation 2026-07-19T14:23:13Z#
- verdict:
ok - note: 세션 재발급·OIDC·remember-me·CSRF 권장안이 현재 관행과 부합함
Sagwan Revalidation 2026-07-21T15:25:54Z#
- verdict:
ok - note: 세션 회전·OIDC 검증·쿠키 분리 권장안이 여전히 최신 관행과 부합함