JWT 관리와 탈취대응 시나리오 ( 1 )

2024. 4. 9. 14:46·⚙️ BE
반응형
JWT를 사용하던 중 이를 어떻게 관리하면 효율적이고 안전할까 고민해보고 작성한 글입니다.

 

AccessToken & RefreshToken

가장 기본적인 방법 입니다.

유효기간이 다른 두가지 형태의 JWT를 생성하고 클라이언트는 토큰 재발급시 리프레시 토큰을 서버로 전송 합니다.

리프레시 토큰에 담긴 사용자 식별값을 토대로 유저를 식별하고 새로운 엑세스 토큰을 발급하여 전달 합니다.

 

이 방식은 가장 기본적이고 편한 방식이지만 리프레시 토큰이 탈취되었때 대비가 하나도 되어있지 않습니다.

리프레시 토큰이 탈취되면 해커는 해당 토큰으로 계속 재발급을 받아 자신이 해당 유저인 척 할 수 있습니다.

 

무상태성이라는 특성이 악용에 활용된 전형적인 사례입니다.

 

 

 RTR ( Refresh Token Rotate )

엑세스 토큰과, 리프레시 토큰을 사용하는 방식에서 전략이 추가된 방식입니다.

주로 Redis와 함께 이전략을 사용합니다.

 

기존 방식에서는 리프레시 토큰이 탈취되면 사용자건 서버 관리자건 아무런 대응도 할 수 없습니다.

 

이 방식은 리프레시 토큰을 딱 한번만 사용하고 다시 발급받습니다.

엑세스토큰이 만료되어 재발급 요청을 보내면 서버는 엑세스 토큰, 리프레시 토큰 두가지를 모두 재발급 합니다.

 

만약 해커가 토큰을 탈취 했다고 해도, 기존에 사용하던 유저가 토큰 만료로 인해 재발급 요청을 하면 이 해커가 탈취한 토큰은 사용할 수 없도로 하는 형태 입니다.

 

유저는 서비스를 사용하다 엑세스 토큰이 만료되고 재발급 요청을 보내면 완전히 새로운 토큰이 생성되기에

기존에 쓰던 리프레시 토큰은 쓸 수 없는 상태가 되는 것을 목표로 하는 전략 입니다.

 

별도의 저장없이 위 방식대로만 처리하면 RTR을 사용하지 않는 것과 전혀 차이가 없습니다.
결국에는 어디든 저장을 해야하는데 이 전략에서는 주로 Redis를 활용합니다.

 

전통적인 세션 방식과 유사한 형태로 처리하는데, 우선 세션 방식부터 알아보겠습니다.


 

세션

 

전통적인 세션 방식에서는 서버의 부하가 늘어날지언정 결국 관리를 서버에서 하기 때문에 어느정도 일차 방어선이 구축되어있습니다.

세션은 주로 아래와 같은 방식으로 처리합니다

 

  1. 로그인 하면 세션 생성 ( uuid와 유저식별값으로 구성되어있음 )
  2. key (uuid) : value (유저 식별값) 으로 세션 저장소에 저장 
  3. 인메모리 저장소에 세션을 저장하고 유저에겐 해당 저장소에 접근하기 위한 식별값 (id)만 전달함
  4. 이 값을 http only 쿠키로 전달, 프론트엔드에선 별도의 작업이 필요없음

별도의 저장소에 저장하고 있기 때문에 세션을 만료시키면 해당 유저는 다시 로그인을 해야하기에 탈취가 의심되거나, 유저가 해킹 의심 신고를 하면 세션을 즉시 삭제하는 신속한 1차 대응을 할 수 있습니다.

 


 

다시 본론으로 돌아와서 RTR 전략과 함께 Redis를 사용하는 시나리오에 대해 알아보겠습니다.

 

  1. 로그인 하면 엑세스토큰, 리프레시 토큰 생성
  2. key ( token ) : value ( uuid 유저식별값 )
  3. Redis 저장소에 이 값들을 저장하고 유저에게 엑세스 토큰과 리프레시 토큰을 전달함
  4. 엑세스 토큰 만료시 유저는 리프레시 토큰을 애플리케이션 서버에 전달하여 재발급 요청
  5. Redis 저장소에서 해당 리프레시 토큰 (key)로 저장된 값이 있는지 체크
  6. 재발급시 기존에 Redis에 저장된 값을 삭제, 새로 생성된 리프레시 토큰으로 새로운 값 생성
  7. 사용자에게 전달

이런식으로 처리하면 토큰 재발급 시 Redis에 저장된 값도 삭제되어서, 해커가 들고있던 리프레시 토큰은 Redis에 없기 때문에 토큰 만료 처리를 할 수 있게 됩니다.

 

얼핏 보면 완벽해보입니다.

하지만 이 전략에는 여러가지 한계점이 존재합니다.

 

전략의 한계

 

얼핏 보면 나름 확실하게 방어가 되어있는 듯한 모습을 보입니다.

이전략도 아래와 같은 경우에 문제가 생길 수 있습니다.

 

  • 해커가 토큰을 탈취하자마자 재발급 받았을 때
  • 유저가 탈취당한 사실을 모르고 더 이상 서비스 내에서 어떠한 활동도 하지 않을 때

첫번째 시나리오 ( 해커가 토큰을 탈취하자마자 재발급 받았을 때 )

  1. 해커가 토큰 탈취
  2. 탈취 후 재발급
  3. 기존 엑세스 토큰은 아직 만료되려면 한참 남음
  4. 해커는 기존 엑세스 토큰의 유효기간 만큼 해당 사용자로 위장할 수 있음

 

대응

위 시나리오는 엑세스 토큰의 유효기간을 짧게 설정하면 어느정도 대응이 가능합니다.

예를들어 엑세스토큰의 유효기간이 10초이고, 해커가 토큰을 탈취한 뒤 재발급 받아 해당 사용자로 위장 하려고 한다고 가정하겠습니다.

 

해커는 RTR 전략으로 인해 사용자가 다시 로그인 하기 전 까지만 해당 사용자로 위장할 수 있습니다.

RTR 전략에서 Redis에 새로운 리프레시 토큰을 저장한다고 했는데, 해커가 토큰을 재발급 받으면 Redis에 이 정보가 저장됩니다.

 

기존 사용자는 엑세스 토큰이 만료되고 재발급 요청을 보내니 Redis에 내가 처음에 받은 리프레시 토큰 정보가 없습니다.

그럼 로그인 페이지로 가고 다시 로그인을 합니다.

 

이때 로그인을 하면서 새로운 엑세스 토큰과 리프레시 토큰이 발급되고, Redis에 새로운 정보가 저장됩니다.

엑세스 토큰의 유효시간이 짧아서 해커의 토큰도 만료되었다면 해커는 더 이상 해당 유저인 척 할 수 없는 상태가 됩니다.

 

다시 재발급 요청을 보내도 Redis에는 이미 새로운 토큰이 발급되어있기 때문에 다시 탈취하는 과정을 거쳐야 합니다.

 

 

고민해봐야할 문제

엑세스 토큰의 만료기한을 줄여서 어느정도 문제를 보완 하였지만 아직 생각해보아야 할 부분이 몇가지 있습니다.

 

  • 정상 사용자의 일시적 접근 중단
  • 리프레시 토큰을 사용자 측으로 보내는게 맞을까

정상 사용자의 정상 행위가 일시적으로 중단되는 모습은 사용자 경험에 심각한 영향을 끼칩니다.

탈취 사실을 사전에 체크 하는 방안을 모색해야 할 것 같습니다.

 

리프레시 토큰을 사용자 측으로 보내는게 맞을까 하는 생각도 듭니다.

하지만 리프레시 토큰을 사용자 측으로 보내지 않고 서버에서 관리하게되면 세션과 별 차이가 없기 때문에 고민이 필요해 보입니다.


 

 

두번째 시나리오 ( 유저가 탈취당한 사실을 모르고 더 이상 어떠한 활동도 하지 않을 때 )

  1. 해커가 토큰 탈취 후 바로 재발급
  2. 유저는 브라우저를 이용하다가 그대로 켜두고 외출함
  3. 해커는 탈취한 토큰으로 재발급 요청을 보냄
  4. 애플리케이션 서버 입장에서는 탈취한 토큰이 정상적인 토큰이라면 재발급해줌

사용자가 어떠한 활동도 하고 있지 않기 때문에 해커는 지속적으로 재발급을 받으며 해당 사용자인 척 할 수 있는 말도안되는 상황이 벌어집니다.

 

대응

해당 시나리오는 사용자의 로그아웃 혹은 애플리케이션 서버에서 탈취 사실을 인지하는 대응 방법 밖에 없는 것 같습니다.


 

다음 글에서는 RTR 이외에 다른 전략에 대해 알아보도록 하겠습니다.

 

 


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'⚙️ BE' 카테고리의 다른 글

csrf  (0) 2024.04.09
XSS ( Cross-site scripting ) ( 1 )  (0) 2024.04.09
JWT 관리와 탈취대응 시나리오 ( 2 )  (1) 2024.04.09
Spring Boot Profile  (0) 2024.04.09
Spring Security + JWT  (0) 2024.02.26
'⚙️ BE' 카테고리의 다른 글
  • XSS ( Cross-site scripting ) ( 1 )
  • JWT 관리와 탈취대응 시나리오 ( 2 )
  • Spring Boot Profile
  • Spring Security + JWT
jobey
jobey
주로 프로그래밍 관련 내용을 기록하고, 관심있는 섹터 관련 내용도 기록합니다.
  • jobey
    jobey
    jobey
  • 전체
    오늘
    어제
    • 분류 전체보기 (35)
      • 🖥️ FE (0)
      • ⚙️ BE (10)
      • 🗃️ Database (1)
      • 💻 Computer Science (3)
      • 🏗️ Architecture (0)
      • 🔍 Sector Insights (5)
        • Dev (3)
        • Finance (2)
      • 🚀 Toy Project (0)
      • ☁️ AWS (1)
      • Rust (9)
      • 자료구조 (1)
      • 알고리즘 (0)
      • Unity (3)
      • Python (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • dbdiagram
  • 공지사항

  • 인기 글

  • 태그

    ABAC
    JWT
    Spring Security
    github actions
    튜플
    nginx
    스킨커스텀가이드
    NoSQL
    docker
    chat gpt assistants
    메서드
    RBAC
    similairy
    security
    Rust
    owner ship
    구독기반 비즈니스 모델
    Chat GPT
    구조체
    vector embedding
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
jobey
JWT 관리와 탈취대응 시나리오 ( 1 )
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.