LabHub
Get started
배우기 러닝패스 코스

Sessions and Tokens — From the Browser to the Mesh

Redis sessions and session fixation defense

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

Redis 를 세션 저장소로 붙인 로그인 서버를 세우고, 로그인 순간 세션 ID 가 재발급되는지·절대 만료가 idle 과 무관하게 동작하는지·로그아웃이 즉시 무효화하는지를 실제 HTTP 요청으로 확인한다.

왜 중요한가

서버 세션은 상태를 서버가 쥐고 브라우저에는 열쇠만 준다. 그래서 로그아웃 한 번으로 즉시 무효화할 수 있지만, 그 열쇠가 로그인 전후로 바뀌지 않으면 남이 미리 심어 둔 열쇠로 내 로그인에 올라타는 세션 고정이 성립한다. OWASP 는 권한 수준이 익명에서 인증으로 바뀌는 순간 세션 ID 를 재발급하라고 못박는다. 또한 만료는 idle(활동 없으면 만료, 요청마다 갱신)과 absolute(만든 지 오래되면 무조건 만료) 두 가지를 함께 두어야 하는데, Redis TTL 만으로는 absolute 를 표현할 수 없어 값 안에 만든 시각을 따로 둔다. 이 실습은 그 규칙들이 실제 요청에서 지켜지는지를 스스로 증명하게 한다.

단계

  1. /root/st/session/app.py 를 127.0.0.1:8302 에 띄운다. GET /health 가 200 과 {"ok":true} 를 준다.
  2. 세션 쿠키가 __Host-sid 이름에 Secure, HttpOnly, SameSite, Path=/ 를 갖는지 /root/st/session/cookie.txt 에 Set-Cookie 헤더 한 줄로 저장한다.
  3. 익명 세션을 받아 그 ID 가 sess:<id> 키로 Redis 에 있고 TTL 과 user 를 가지는지 /root/st/session/store.txt 에 적는다.
  4. 익명 세션 ID 를 그대로 들고 로그인하면 응답이 다른 세션 ID 를 주고 옛 ID 가 사라지는지 /root/st/session/fixation.txt 에 적는다.
  5. 로그인 세션의 TTL 이 idle 상한 이하이고 요청으로 다시 차오르는지 /root/st/session/idle_ttl.txt 에 적는다.
  6. created 를 과거로 넣은 세션이 idle TTL 이 남아 있어도 인증으로 인정되지 않는지 /root/st/session/absolute.txt 에 적는다.
  7. 로그아웃 뒤 같은 쿠키가 익명으로 떨어지고 저장소 키가 사라지는지 /root/st/session/logout.txt 에 적는다.
  8. /root/st/session/e2e.sh 로 전체 흐름을 시험해 /root/st/session/e2e.out 에 네 줄을 남긴다.

참고

Redis 세션 서버 띄우기

/root/st/session/app.py 를 127.0.0.1:8302 에 띄운다. GET /health 가 200 과 {"ok":true} 를 준다.

Redis 는 이미 6379 에 떠 있습니다. 서버는 백그라운드로 띄우고 준비될 때까지 폴링하세요.

세션 쿠키 속성 점검

세션 쿠키가 __Host-sid 이름에 Secure, HttpOnly, SameSite, Path=/ 를 갖는지 /root/st/session/cookie.txt 에 Set-Cookie 헤더 한 줄로 저장한다.

__Host- 접두는 Secure 와 Path=/ 를 요구하고 Domain 을 붙이면 안 됩니다. curl -D - 로 응답 헤더를 봅니다.

세션이 Redis 에 저장되는지

익명 세션을 받아 그 ID 가 sess:<id> 키로 Redis 에 있고 TTL 과 user 를 가지는지 /root/st/session/store.txtsid= redis_key= exists=1 ttl=<양수> user=(anon) 로 적는다.

쿠키 병(-c)으로 세션 ID 를 잡고 redis-cli EXISTS/TTL/GET 으로 확인합니다.

로그인 시 세션 ID 재발급

익명 세션 ID 를 그대로 들고 로그인하면 응답이 다른 세션 ID 를 주고 옛 ID 가 저장소에서 사라지는지 /root/st/session/fixation.txtbefore= after= changed=yes old_gone=yes 로 적는다.

세션 고정 방어의 핵심입니다. 로그인 성공 시 옛 세션을 delete 하고 새 ID 를 발급해야 changed=yes 가 됩니다.

idle 타임아웃은 sliding TTL

로그인 세션의 Redis TTL 이 idle 상한 이하이고, 요청을 한 번 더 보내면 TTL 이 다시 차오르는지 /root/st/session/idle_ttl.txtttl_before= ttl_after_request= 로 적는다. 둘 다 양수이고 after 가 상한 근처여야 한다.

요청마다 EXPIRE 로 TTL 을 다시 밀면 sliding idle 이 됩니다.

absolute 만료는 TTL 과 무관

created 를 absolute 상한보다 과거로 넣고 idle TTL 은 넉넉히 남긴 세션이 GET /whoami 에서 인증으로 인정되지 않는지 /root/st/session/absolute.txtcode=200 auth=False gone=yes 로 적는다.

load_session 에서 now - created > ABSOLUTE_SEC 이면 idle TTL 이 남아 있어도 거절해야 합니다.

로그아웃 즉시 무효화

로그인 뒤 로그아웃하고 같은 쿠키로 GET /whoami 하면 익명으로 떨어지고 저장소 키가 사라지는지 /root/st/session/logout.txtrevoked_auth=False key_gone=yes 로 적는다.

서버가 상태를 쥐므로 키 하나를 지우면 즉시 무효화됩니다 — JWT 와의 차이입니다.

전체 흐름 한 번에 증명

/root/st/session/e2e.sh 로 익명→로그인 재발급→인증→로그아웃 무효화를 순서대로 시험해 /root/st/session/e2e.outreissue=yes, old_gone=yes, logged_in=True, after_logout=False 를 남긴다.

앞 스텝들을 한 스크립트로 이어 붙입니다. 네 줄이 모두 나와야 합니다.