[주요정보통신기반시설 웹 애플리케이션 취약점 분석·평가 21일 완성 코스] 16강 — [Day 16] 불충분한 세션 관리
[Day 16] 불충분한 세션 관리 (Insufficient Session Management)
안녕하세요! Hackerstory 공부방의 IT/보안 튜터 정다은입니다. 😊
어느덧 21일 완성 코스의 후반부인 16일 차에 접어들었습니다! 지난 시간에 다룬 악성 파일 업로드와 파일 다운로드 취약점처럼 파일 시스템을 직접 타격하는 공격도 위험하지만, 사용자 인증 상태를 위협하는 공격 역시 웹 보안에서 매우 치명적입니다.
오늘 배울 주제는 **[불충분한 세션 관리]**입니다. 웹 애플리케이션에서 세션(Session)은 "로그인한 사용자"라는 상태를 유지해 주는 놀이공원의 '자유이용권 팔찌'와 같습니다. 만약 이 팔찌의 유효기간이 없거나, 다른 사람이 내 팔찌를 쉽게 복제해서 쓸 수 있다면 어떻게 될까요? 지금부터 그 원리와 위험성, 그리고 올바른 대응책을 하나씩 차근차근 알아보겠습니다!
1. 개념 이해하기: 세션 관리란 무엇일까?
웹(HTTP)의 특성과 세션
우리가 사용하는 HTTP 프로토콜은 Stateless(비상태성) 및 **Connectionless(비연결성)**라는 특징을 가집니다. 서버는 이전 요청이 누구에게서 왔는지 기억하지 못하죠. 그래서 사용자가 로그인에 성공하면, 서버는 사용자에게 난수 형태의 **세션 ID(Session ID)**를 발급하고, 클라이언트는 이를 쿠키(Cookie) 등에 저장해 두었다가 매 요청마다 함께 전송합니다.
"불충분한 세션 관리" 취약점이란?
서버가 이 세션 ID의 생성, 발급, 유지, 만료, 폐기 과정을 소홀히 관리할 때 발생하는 보안 약점입니다. 주요 원인은 크게 세 가지로 나뉩니다.
- 세션 고정 (Session Fixation) 로그인 전 발급받았던 방문자용 세션 ID가 로그인 후에도 변경되지 않고 그대로 유지되는 현상입니다. 공격자가 미리 세션 ID를 파악해 두면, 피해자가 로그인한 후 해당 세션을 그대로 탈취할 수 있습니다.
- 세션 타임아웃 미설정 (No Session Timeout) 사용자가 일정 시간 동안 아무런 활동을 하지 않아도 세션이 영구적으로 유지되는 상태입니다. 공공장소 PC 등에서 로그아웃을 하지 않고 자리를 비웠을 때 세션 탈취 공격에 노출됩니다.
- 불충분한 세션 폐기 및 중복 로그인 허용 로그아웃 버튼을 눌렀을 때 클라이언트 측 쿠키만 삭제하고 서버 측 세션 정보는 제거하지 않거나, 동일한 계정으로 여러 기기/브라우저에서 무제한 중복 로그인을 허용하는 문제입니다.
2. 실무 예시 및 공격 시나리오
개념만으로는 조금 와닿지 않으시죠? 실무에서 흔히 발생하는 공격 시나리오와 코드 예시로 자세히 살펴보겠습니다.
시나리오 1: 세션 고정(Session Fixation) 공격 과정
[공격자] ──(1) 웹사이트 접속 (Session ID: ABC123 발급)──> [웹 서버]
│
├──(2) 피해자에게 악성 링크 전달 (예: http://site.com/login?JSESSIONID=ABC123)
│
[피해자] ──(3) 링크 클릭 후 정상 로그인 성공! ────────────> [웹 서버]
│ │ (서버: ABC123 세션을 인증 상태로 승격)
│ ▼
[공격자] ──(4) 기존 쿠키(ABC123)로 피해자 계정 재접속 ────> [웹 서버] (인증 성공!)
- 문제점: 로그인에 성공했음에도 서버가
ABC123이라는 식별자를 새것으로 바꾸지 않고 식별 권한만 높여주었기 때문에, 식별자를 알고 있던 공격자가 로그인 없이 피해자의 권한을 그대로 가져가게 됩니다.
❌ 취약한 코드 예시 (Java Servlet)
// 로그인 처리 로직
public void login(HttpServletRequest request, HttpServletResponse response) {
String id = request.getParameter("id");
String pw = request.getParameter("pw");
if (userService.authenticate(id, pw)) {
// 기존 세션을 그대로 가져와서 사용자 정보만 저장 (취약!)
HttpSession session = request.getSession(false);
session.setAttribute("user", id);
}
}
⭕ 안전한 코드 예시 (Java Servlet / Spring Security)
로그인 성공 시 기존 세션을 즉시 무효화(Invalidate)하고 새로운 세션 ID를 재발급해야 합니다.
public void login(HttpServletRequest request, HttpServletResponse response) {
String id = request.getParameter("id");
String pw = request.getParameter("pw");
if (userService.authenticate(id, pw)) {
// 1. 기존 세션 폐기
HttpSession oldSession = request.getSession(false);
if (oldSession != null) {
oldSession.invalidate();
}
// 2. 새로운 세션 생성 및 ID 재발급
HttpSession newSession = request.getSession(true);
newSession.setAttribute("user", id);
}
}
Spring Security를 사용할 경우:
.sessionManagement(session -> session.sessionFixation().newSession())또는changeSessionId()설정을 통해 기본적으로 세션 고정 공격을 방어할 수 있습니다.
시나리오 2: 불충분한 세션 만료 및 로그아웃 처리
❌ 취약한 로그아웃 처리 (Node.js Express 예시)
app.get('/logout', (req, res) => {
// 클라이언트의 쿠키만 제거하고, 서버 메모리/DB의 세션은 남겨둠 (취약!)
res.clearCookie('connect.sid');
res.redirect('/login');
});
- 문제점: 공격자가 이전에 통신 과정에서 세션 쿠키값을 훔쳐 두었다면, 피해자가 로그아웃을 눌렀더라도 해당 세션 쿠키를 이용하여 서버에 지속적으로 접근할 수 있습니다.
⭕ 안전한 로그아웃 및 타임아웃 설정
1) 서버 측 세션 완전 폐기 (Node.js Express)
app.get('/logout', (req, res) => {
// 서버 측 세션 데이터를 완전히 파기
req.session.destroy((err) => {
if (err) {
console.error(err);
}
res.clearCookie('connect.sid'); // 쿠키 삭제
res.redirect('/login');
});
});
2) 세션 타임아웃 설정 (Java web.xml 기준)
사용자의 마지막 요청으로부터 일정 시간이 지나면 서버가 세션을 자동으로 만료시키도록 설정합니다. (보통 일반 웹 서비스는 15~30분, 금융권 등은 10분 이내 권장)
<session-config>
<!-- 세션 타임아웃을 15분으로 설정 -->
<session-timeout>15</session-timeout>
</session-config>
3. 진단 방법 및 실무 보안 대책 정리
주요정보통신기반시설 가이드라인에 따라 불충분한 세션 관리 항목을 점검하고 조치할 때는 아래 가이드라인을 체크리스트로 활용하세요.
🔍 취약점 진단 절차 (점검 방법)
- 세션 고정 진단: 로그인 전 발급받은 쿠키(예:
JSESSIONID,PHPSESSID)의 값과, 로그인 성공 후 발급되어 유지되는 쿠키의 값을 비교합니다. (값이 동일하면 취약) - 세션 타임아웃 진단: 로그인 후 일정 시간(예: 30분 이상) 동안 아무 요청을 보내지 않고 대기한 뒤, 페이지를 뒤로 가거나 새로고침했을 때 세션이 유지되는지 확인합니다.
- 로그아웃 검증: 로그아웃을 수행한 후, 이전 요청 시 사용했던 세션 쿠키를 Burp Suite 등으로 재전송하여 인증이 필요한 페이지에 접근이 가능한지 확인합니다.
- 중복 로그인 점검: A 브라우저에서 로그인한 상태에서, B 브라우저로 동일 계정 로그인 시 기존 세션 차단 여부를 점검합니다.
🛡️ 종합 보안 대책 (보안 가이드)
| 구분 | 보안 대책 내용 |
|---|---|
| 세션 ID 재발급 | 로그인(인증) 성공 시 반드시 기존 세션을 파기하고 새로운 세션 ID를 발급한다. |
| 세션 타임아웃 | 일정 시간(10~30분) 비활성화 상태 지속 시 세션을 자동으로 만료시킨다. |
| 완벽한 로그아웃 | 로그아웃 요청 시 클라이언트 쿠키 삭제뿐만 아니라 서버 측 세션 객체를 완전 폐기(invalidate())한다. |
| 쿠키 보안 속성 | 세션 쿠키에 HttpOnly(스크립트를 통한 접근 차단) 및 Secure(HTTPS 전송 강제) 플래그를 설정한다. |
| 중복 로그인 제한 | 비즈니스 로직 요구사항에 따라 동일 계정의 다중 로그인을 차단하거나 이전 세션을 만료 처리(세션 바인딩)한다. |
📝 오늘 배운 내용 요약
- 세션 고정(Session Fixation): 로그인 후에도 로그인 전 세션 ID가 바뀌지 않아 생기는 취약점 ➡️ 로그인 시 세션 ID 재발급 필수!
- 세션 타임아웃 미설정: 자리를 비웠을 때 세션이 유지되는 문제 ➡️ 서버 설정으로 15~30분 비활성화 시 자동 만료!
- 불충분한 세션 폐기: 로그아웃 후에도 서버 세션이 남아있는 문제 ➡️ 로그아웃 시 서버 메모리/DB 내 세션 즉시 삭제!
오늘 강의도 수고 많으셨습니다! 세션 관리는 웹 보안의 기본이자 핵심입니다. 특히 개발을 할 때 로그인 기능만 구현하고 로그아웃이나 세션 갱신 로직을 빠뜨리는 경우가 빈번하니, 늘 꼼꼼하게 세션 생명주기(Lifecycle)를 챙겨주세요.
다음 시간인 **[Day 17]**에는 웹 서버와 브라우저 사이의 통신 보안을 다루는 **[데이터 평문 전송]**에 대해 알아보겠습니다. 민감한 데이터가 네트워크 상에서 어떻게 노출되는지, 그리고 TLS/SSL 적용의 중요성을 공부해봅시다!
궁금한 점이 있다면 언제든 댓글로 질문 남겨주세요. 다음 시간에 만나요! 👋
댓글 0
로그인하면 댓글을 작성할 수 있습니다.