용어 사전

세션 고정(Session Fixation)이란 — 공격자가 이미 아는 ID로 피해자를 로그인시키는 공격

세션 고정은 공격자가 아는 세션 ID를 피해자가 쓰게 만든 뒤 로그인하면 피해자를 가장하는 공격입니다. 작동 원리와 로그인 시 세션 ID 재생성, 쿠키 플래그 등 방어법을 설명합니다.

게시 2026-06-11 업데이트 2026-10-06 5분 읽기
이 페이지에서

세션 고정은 피해자가 공격자가 준비한 ID로 로그인하게 되는 공격입니다. 동작 원리와 확실하게 막는 방법을 설명합니다(공격 절차 없음).

왜 통하는가

원인은 세션 ID가 로그인 전후로 바뀌지 않는 설계입니다. 바뀌지 않는다면, 공격자가 로그인 전에 알던 ID가 로그인 후에도 "인증됨"으로 여전히 작동합니다. 흔한 오해는 "로그인하면 자동으로 새 세션이 생긴다"는 것이지만 — 많은 프레임워크는 명시적으로 재생성을 호출하지 않으면 같은 ID를 그대로 이어 씁니다.

1) 공격자가 피해자에게 알려진 세션 ID를 쓰게 함 (링크 등을 통해)
↓ 피해자가 그 ID를 그대로 둔 채 로그인
2) ID가 재생성되지 않음 = 같은 ID가 "인증됨"이 됨
↓ 공격자는 그 ID를 처음부터 알고 있었음
3) 같은 ID로 접근 = 피해자를 가장함
로그인 시 ID가 바뀌지 않으면, 공격자가 미리 알던 ID가 그대로 인증된다.

CSRF 나 XSS 와 짝지을 수도 있지만, 고정 자체의 본질은 한 가지입니다. 로그인 시 ID가 재생성되지 않았다입니다.

일본 IPA(정보처리추진기구)의 가이드 "안전한 웹사이트 만드는 법"은 이를 부적절한 세션 관리의 한 형태로 다루며, 로그인 기능이 있는 모든 웹사이트가 주의해야 한다고 말합니다. 근본적인 해결책은 로그인 성공 후 새 세션을 시작하는 것입니다.

고정 vs 하이재킹 vs CSRF

이 셋은 헷갈리기 쉽습니다. 모두 로그인 상태를 악용하지만, 공격자가 무엇을 가지고 있는지와 어떤 방어가 통하는지가 다릅니다.

항목세션 고정세션 하이재킹CSRF
공격자가 가진 것직접 준비한 ID(처음부터 알고 있음)훔친, 이미 발급된 IDID는 전혀 없음
피해자에게 일어나는 일심어 둔 ID로 로그인한다발급된 ID를 도난당한다의도하지 않은 요청을 보내게 된다
주된 방어로그인 시 ID 재생성HttpOnly/Secure, XSS 방지, 짧은 유효 기간CSRF 토큰, SameSite

고정은 로그인 시 ID 재생성이라는 한 가지 조치로 근본적으로 고쳐지는 공격입니다.

방어: 로그인 시 ID를 재생성하라

1

로그인 성공 시 세션 ID 재생성 (가장 중요)

인증이 성공하는 즉시 기존 ID를 폐기하고 새 세션 ID를 발급하세요(대부분 프레임워크의 session regenerate/renew). 미리 심어 둔 ID는 즉시 무효화됩니다. 권한 상승 시(예: 관리자가 될 때)에도 재생성하세요.
2

URL을 통한 세션 ID를 받지 않기

세션 ID는 쿠키에서 다루고, URL 파라미터로 지정된 ID는 무시하세요. 공격자가 피해자에게 '고정된' ID를 채택하게 만드는 경로를 닫습니다.
3

쿠키 플래그 설정

세션 쿠키에 HttpOnly(JS가 읽을 수 없음), Secure(HTTPS만), SameSite(교차 사이트 전송 억제)를 설정하세요. 관련 하이재킹 경로도 함께 약화시킵니다.
4

세션을 합리적으로 만료시키기

유휴 타임아웃, 로그아웃, 비밀번호 변경 시 만료시켜 고정된 ID가 무한정 유효하게 남지 않게 하세요. 비밀번호를 바꿨다면 그 사용자의 다른 모든 활성 세션도 함께 끊어, 미리 심어 둔 ID가 살아남을 틈을 없애세요.

OWASP의 Session Management Cheat Sheet는 권한이 바뀔 때마다 ID를 재생성하고, 서버가 직접 생성한 ID만 받는 "strict(엄격)" 방식을 쓰라고 권장합니다. 밖에서 들어온 모르는 ID를 그대로 채택하는 "permissive(허용)" 방식은 공격자가 고른 ID가 받아들여질 여지를 남깁니다.

주요 프레임워크의 기본 동작

대부분의 프레임워크는 표준 로그인 기능을 쓰면 ID를 자동으로 재생성합니다. 위험은 로그인을 직접 작성하거나 기본 보호를 껐을 때 생깁니다.

환경기본 동작직접 작성할 때 확인할 것
PHP(순수 세션)스스로 재생성하지 않음. session.use_strict_mode 기본값은 0로그인 성공 시 session_regenerate_id(true) 호출. use_strict_mode를 1로
Laravel스타터 킷이나 Fortify를 쓰면 인증 시 자동 재생성로그인을 직접 작성한다면 $request->session()->regenerate() 호출
Spring Security기본으로 켜져 있음(Servlet 3.1 이상에서 changeSessionId)누군가 sessionFixation().none()을 설정하지 않았는지 확인

PHP에서는 세션 ID를 URL로 전달하는 설정(session.use_trans_sid 활성화, session.use_only_cookies 비활성화)이 PHP 8.4에서 비권장(deprecated)이 되었습니다. 오래된 설정 파일을 그대로 가져와 쓴다면 점검하세요.

내 사이트에서 확인하는 방법

관리하는 사이트에서 다음 네 가지를 확인하세요. 개발자 도구만 있으면 됩니다.

  1. 개발자 도구의 "Application"(Firefox는 "Storage")에서 세션 쿠키 값을 적어 두고, 로그인 후 다시 봅니다. 바뀌지 않았다면 로그인 시 ID가 재생성되지 않는 것입니다
  2. 로그인 페이지와 로그인 후 URL에 PHPSESSID=나 ;jsessionid= 같은 세션 ID가 붙어 있지 않은지 확인합니다
  3. 같은 화면에서 세션 쿠키에 HttpOnly, Secure, SameSite가 있는지 확인합니다
  4. 로그아웃한 뒤 예전 쿠키 값을 되돌려 넣고 새로고침해, 다시 로그인된 상태가 되지 않는지 확인합니다

쿠키 속성은 소유를 확인한 사이트를 검사하는 사이트 보안 점검에서도 확인할 수 있습니다. 1번 확인을 로그인 흐름을 손볼 때마다 도는 자동 테스트로 만들어 두면, 재생성이 빠졌을 때 바로 알아챌 수 있습니다.

본 사이트의 견해: 프레임워크의 '재생성'을 끄지 마라

세션 고정은 정교한 맞춤 코드가 아니라 한 가지 조치(로그인 시 ID 재생성)만으로 대부분 막을 수 있습니다. 핵심은 프레임워크가 이미 제공하는 그 메커니즘을 실수로 끄거나 호출하기를 잊지 않는 것입니다. 검증된 구현의 안전한 기본값을 쓰는 것이 직접 세션 관리를 짜는 것보다 낫습니다. 본 사이트는 "인증/키 처리를 직접 만들지 말 것, 안전한 기본값을 끄지 말 것"을 지킵니다. IDOR 와 마찬가지로, 인증/인가는 모든 요청에서 메커니즘으로 강제되어야 합니다.

출처(1차 자료)

  • IPA, "안전한 웹사이트 만드는 법" 1.4 세션 관리의 부적절 — ipa.go.jp(로그인 후 새 세션 시작, ID를 URL에 넣지 않기, 일본어)
  • OWASP Session Management Cheat Sheet — cheatsheetseries.owasp.org(권한 변경 시 재생성, strict 방식, 쿠키 속성)
  • MITRE CWE-384: Session Fixation — cwe.mitre.org
  • PHP Manual, "Runtime Configuration"(세션) — php.net(use_strict_mode 등의 기본값, 8.4의 비권장 항목)
  • Laravel 문서, "HTTP Session" — laravel.com / Spring Security, "Authentication Persistence and Session Management" — docs.spring.io

다음으로 읽기

분류 번호

CWE는 취약점의 원인이 되는 약점의 종류를, MITRE ATT&CK는 공격자의 기법을 분류한 번호 체계입니다. 둘 다 MITRE가 관리하며 취약점 정보와 탐지 규칙 분류에 널리 쓰입니다.

CWE (약점 종류)

CWE™: Copyright © 2006–2026, The MITRE Corporation. CWE is a trademark of The MITRE Corporation. The MITRE Corporation hereby grants you a non-exclusive, royalty-free license to use CWE for research, development, and commercial purposes. Any copy you make for such purposes is authorized on the condition that you reproduce MITRE’s copyright designation and this license in any such copy. CWE Terms of Use

FAQ

Q고정은 세션 하이재킹과 무엇이 다른가요?
A

하이재킹은 이미 발급된 누군가의 세션 ID를 훔칩니다. 고정은 그 반대입니다. 공격자가 이미 아는 ID를 피해자가 쓰게 만든 뒤, 피해자가 그 ID로 로그인하기를 기다립니다. 훔치는 것이 아니라, 공격자가 아는 ID를 인증된 상태로 만드는 것입니다.

Q가장 효과적인 방어법은 무엇인가요?
A

로그인하는 순간 세션 ID를 재생성하는 것입니다. 대부분의 프레임워크/세션 라이브러리에 이 기능이 있습니다(session regenerate/renew). 인증에 성공하면 기존 ID를 폐기하고 새 ID를 발급하세요. 그것만으로 공격자가 미리 심어 둔 어떤 ID도 무효화됩니다. 권한 변경 시(예: 관리자가 될 때)에도 재생성하세요.

Q세션 ID를 URL에 넣는 것이 왜 위험한가요?
A

URL의 ID는 공유 링크, Referer 헤더, 로그, 브라우저 기록을 통해 쉽게 유출되며, 공격자가 피해자에게 '고정된' ID를 쓰게 만드는 경로가 됩니다. 세션 ID는 URL 파라미터가 아니라 쿠키에서 다루고, URL로 지정된 ID는 받지 마세요.

Q내 사이트가 세션 고정에 취약한지 어떻게 확인하나요?
A

자신의 사이트에서 브라우저 개발자 도구를 열고 로그인 전후의 세션 쿠키 값을 비교하세요. 로그인 후에도 값이 같다면 ID가 재생성되지 않는 것이므로 고쳐야 합니다. URL에 세션 ID가 나타나지 않는지, 쿠키에 HttpOnly·Secure·SameSite가 설정되어 있는지도 확인하세요.

QPHP에서는 어떤 설정으로 세션 고정을 막나요?
A

로그인 성공 시 session_regenerate_id(true)를 호출해 새 ID로 바꿉니다. php.ini에서 session.use_strict_mode를 1로 설정해 서버가 발급하지 않은 ID를 거부하게 하세요(기본값은 0). session.use_only_cookies는 기본값 1, session.use_trans_sid는 기본값 0으로 유지해 ID가 URL로 전달되지 않게 합니다.

QJWT를 쓰면 세션 고정이 일어나지 않나요?
A

서버 쪽 세션 ID를 쓰지 않고 로그인 성공 시 새 토큰을 발급한다면, '미리 정해 둔 ID를 인증된 상태로 만드는' 공격은 성립하기 어렵습니다. 하지만 로그인 전에 발급한 토큰을 로그인 후에도 계속 쓴다면 같은 문제가 생길 수 있습니다. 방식과 상관없이 로그인하는 순간 새 식별자를 발급하는 것이 원칙입니다.