시큐어코딩/JAVA

[시큐어코딩]Java에서 부적절한 세션 종료 보안 이슈와 안전한 처리 방법4

ICT리더 리치 2025. 4. 10. 10:29
반응형

세션(Session)은 로그인 사용자의 인증 정보를 유지하는 핵심 수단입니다. 하지만 세션 종료를 명확히 처리하지 않으면, 공격자는 이전 세션을 재사용하거나 탈취해 민감한 기능을 악용할 수 있습니다.

이번 포스팅에서는 Java 기반 웹 애플리케이션에서 부적절한 세션 종료로 발생할 수 있는 보안 위험을 진단하고, Spring MVC 및 Spring Security 환경에서 이를 안전하게 처리하는 실전 예제를 소개합니다. 실제 로그아웃 처리 시 주의해야 할 점들과 보안 강화를 위한 팁도 함께 확인해보세요.

1. 부적절한 세션 종료란?

세션(Session)은 로그인한 사용자의 인증 상태를 유지하기 위해 서버 측에서 관리하는 일시적 정보입니다. 로그아웃 시 세션을 명확히 종료하지 않으면, 브라우저를 닫아도 인증 정보가 남아 공격자가 동일 세션을 재사용할 수 있습니다. 특히 공용 PC, 네트워크 공유 환경, 또는 브라우저 캐시가 강하게 유지되는 경우, 로그아웃했지만 인증된 상태가 유지되는 치명적인 보안 문제가 발생할 수 있습니다.

Java 및 Spring 기반 시스템에서는 반드시 HttpSession.invalidate() 또는 Spring Security의 .invalidateHttpSession(true) 설정을 통해 세션을 명확히 종료해야 합니다.

2. 실무에서 자주 보이는 취약한 코드

다음은 Spring MVC에서 로그아웃 처리를 구현했지만, 세션을 명시적으로 종료하지 않아 사용자 인증 정보가 남아있는 구조입니다. 실제 현업에서 테스트용으로 시작한 코드가 운영에 그대로 반영되는 경우가 많습니다.


// 로그아웃 시 세션을 무효화하지 않음
@GetMapping("/logout")
public String logout(HttpServletRequest request) {
    // 세션 처리 누락
    return "redirect:/";
}

세션 무효화가 누락된 이 코드는 사용자가 로그아웃해도 세션이 서버에 그대로 남습니다. 이 경우 공격자가 동일 브라우저 또는 세션 ID를 이용해 사용자의 권한을 그대로 탈취할 수 있으며, 이는 세션 하이재킹, 세션 고정(Session Fixation) 공격으로도 이어질 수 있습니다.

3. 안전한 로그아웃 처리 방법

아래는 Spring Boot 환경에서 로그아웃 시 세션을 명확하게 종료하고, 재사용을 방지하는 안전한 코드 예제입니다. HttpSession을 통해 세션을 직접 무효화하고, 로그아웃 성공 후에는 리디렉션을 처리해 보안 효과를 강화합니다.


// 로그아웃 컨트롤러 – 세션 종료 처리
@GetMapping("/logout")
public String logout(HttpServletRequest request, HttpServletResponse response) {
    HttpSession session = request.getSession(false); // 세션이 존재할 때만
    if (session != null) {
        session.invalidate(); // 세션 종료
    }

    // 쿠키 삭제 (선택적 보강)
    Cookie cookie = new Cookie("JSESSIONID", null);
    cookie.setMaxAge(0);
    cookie.setPath("/");
    response.addCookie(cookie);

    // 로그아웃 후 로그인 페이지로 이동
    return "redirect:/login?logout";
}

위 코드는 HttpSession 객체를 명시적으로 종료하고, 세션 쿠키도 삭제하여 세션 재사용을 방지합니다. 로그아웃 후에는 인증이 해제된 상태에서 로그인 페이지로 리디렉션되므로, 보안성과 사용자 흐름을 모두 만족하는 구성입니다.

4. 실무 Q&A

Q. Spring Security를 사용하는 경우 별도 로그아웃 처리가 필요할까요?

Spring Security는 기본적으로 /logout 요청을 처리하며, 세션 무효화와 인증 정보 제거를 자동으로 수행합니다. 하지만 csrf()가 활성화된 경우 POST 요청만 허용되므로, 로그아웃 링크에는 주의가 필요합니다.

Q. 로그아웃 시 세션 쿠키도 삭제해야 하나요?

세션 자체를 무효화하면 서버에서는 정보가 사라지지만, 클라이언트의 브라우저에는 JSESSIONID 쿠키가 남아있을 수 있습니다. 이를 삭제하면 사용자 경험과 보안 모두 향상됩니다.

Q. 세션 타임아웃 설정은 어떻게 하나요?

Spring Boot에서는 application.properties 또는 yaml에서 설정합니다. 예: server.servlet.session.timeout=15m 너무 길거나 짧은 설정은 사용자 불편 혹은 보안 취약점이 될 수 있으므로 적절한 시간 유지가 필요합니다.

Q. 세션 고정(Session Fixation)을 막으려면 어떻게 해야 하나요?

Spring Security에서는 로그인 시 자동으로 세션을 새로 생성합니다. 커스텀 로그인 처리 시에도 request.getSession().invalidate() 후 새 세션을 발급하면 안전합니다. 또한 sessionManagement().sessionFixation().newSession() 설정도 권장됩니다.

5. 마무리 요약

세션 종료는 단순한 기능처럼 보이지만, 실제로는 세션 탈취·고정·재사용을 방지하는 핵심 보안 요소입니다. Spring Boot와 같은 프레임워크에서도 세션 무효화와 쿠키 삭제가 명확히 처리되어야 안전한 로그아웃이 가능합니다. 실무에서는 자동화된 보안 기능만 의존하지 말고, 명시적인 세션 종료 로직을 항상 포함하는 습관이 필요합니다.

  • 세션 무효화: session.invalidate() 명시적 호출
  • 세션 쿠키 삭제: JSESSIONID 삭제로 재사용 방지
  • Spring Security 사용 시 logout 설정 검토
  • CSRF 설정이 logout 동작에 영향을 줄 수 있음
  • 타임아웃 설정 확인: application.properties 또는 Java 코드로 지정
반응형