본문 바로가기
일반IT/IT보안

JWT, 정말 안전할까? 🧐 JWT 보안 위협 파헤치기

by gasbugs 2025. 9. 16.

안녕하세요! 👋 오늘은 많은 웹 서비스와 애플리케이션에서 사용자 인증을 위해 널리 사용되는 JWT(JSON Web Token)의 보안 위협에 대해 자세히 알아보려고 합니다. JWT는 편리하고 확장성이 뛰어나지만, 올바르게 사용하지 않으면 심각한 보안 문제로 이어질 수 있습니다. 어떤 점들을 주의해야 할까요? 함께 살펴보시죠!

 


1. 시그니처(Signature) 관련 취약점 ✒️

JWT의 가장 중요한 부분 중 하나는 바로 시그니처입니다. 시그니처는 토큰의 내용이 위변조되지 않았다는 것을 보장하는 역할을 하죠. 하지만 이 시그니처와 관련된 몇 가지 주요 보안 위협이 존재합니다.

알고리즘 혼동 공격 (Algorithm Confusion Attack)

JWT의 헤더(Header)에는 토큰을 암호화하는 데 사용된 알고리즘을 지정하는 alg 필드가 있습니다. 가장 널리 쓰이는 알고리즘은 HS256(HMAC-SHA256)과 RS256(RSA-SHA256)입니다.

  • HS256: 서버와 클라이언트가 동일한 비밀 키를 공유하여 서명을 생성하고 검증합니다.
  • RS256: 개인 키로 서명하고 공개 키로 검증하는 비대칭 키 방식을 사용합니다.

여기서 문제가 발생할 수 있습니다. 만약 서버가 RS256으로 설정되어 있는데, 공격자가 alg 값을 HS256으로 변경하고 RS256의 공개 키를 비밀 키처럼 사용하여 토큰을 생성한다면 어떻게 될까요? 😱

서버는 alg 필드가 HS256이므로, 당연히 HS256 방식으로 토큰을 검증하려고 할 것입니다. 이때 서버는 공개 키를 HS256의 비밀 키로 착각하여 유효한 토큰이라고 판단하게 됩니다. 이 경우 공격자는 자신이 원하는 내용으로 토큰을 만들어 서버를 속일 수 있게 됩니다.


예방책:

  • 서버 측에서 토큰 검증 시, alg 헤더 값을 고정하여 예상하는 알고리즘(예: RS256)과 일치하는지 반드시 확인해야 합니다.
  • 절대로 alg 헤더 값만 믿고 동적으로 검증 로직을 변경해서는 안 됩니다.

'none' 알고리즘 공격

alg 필드에는 'none'이라는 값을 사용할 수도 있습니다. 이름에서 알 수 있듯이, 이는 시그니처를 사용하지 않겠다는 의미입니다. 개발 과정에서 테스트 목적으로 사용될 수는 있지만, 만약 실제 운영 환경에서 이 옵션이 활성화되어 있다면 최악의 상황을 초래할 수 있습니다.

공격자가 alg 값을 'none'으로 변경하고 시그니처 부분을 제거한 채로 토큰을 보내면, 일부 라이브러리나 서버 설정에 따라 이를 유효한 토큰으로 인식할 수 있습니다. 😭 시그니처 검증 과정 자체가 생략되기 때문이죠.

 

예방책:

  • 서버에서 토큰을 검증할 때 alg 값이 'none'인 경우는 무조건 거부하도록 설정해야 합니다.

2. 토큰 탈취 및 재사용 공격 🔄

JWT는 한 번 발급되면 서버에 별도의 상태를 저장하지 않는 Stateless 특징을 가집니다. 이는 서버의 부담을 줄여주는 장점이지만, 반대로 토큰이 탈취되었을 때의 대응을 어렵게 만듭니다.

리플레이 공격 (Replay Attack)

만약 공격자가 사용자의 JWT를 중간에서 가로챘다면(예: XSS 공격, MITM 공격), 해당 토큰의 만료 시간(exp)이 지나기 전까지는 계속해서 그 토큰을 재사용하여 마치 정상적인 사용자인 것처럼 서버에 요청을 보낼 수 있습니다. 서버 입장에서는 유효한 시그니처를 가진 정상적인 토큰이므로 막을 방법이 마땅치 않습니다. 🕵️‍♂️

 

예방책:

  • 짧은 만료 시간 설정: 토큰의 유효 기간을 최대한 짧게 설정하여 탈취되더라도 피해를 최소화합니다.
  • 리프레시 토큰(Refresh Token) 사용: 사용자 경험을 해치지 않으면서 보안을 강화하기 위해, 만료 시간이 짧은 액세스 토큰(Access Token)과 만료 시간이 긴 리프레시 토큰을 함께 사용하는 것이 좋습니다. 액세스 토큰이 만료되면 리프레시 토큰을 사용해 새로운 액세스 토큰을 발급받는 방식입니다.
  • HTTPS/TLS 사용: 통신 전 과정에 암호화를 적용하여 중간자 공격(MITM)으로 인한 토큰 탈취를 방지합니다.

3. 토큰 저장 및 관리의 중요성 💾

JWT 자체의 취약점이 아니더라도, 토큰을 어디에 어떻게 저장하고 관리하느냐에 따라 보안 수준이 크게 달라질 수 있습니다.

민감한 정보 저장 금지

JWT의 페이로드(Payload) 부분은 Base64로 인코딩되어 있을 뿐, 암호화된 것이 아닙니다. 따라서 누구나 쉽게 디코딩하여 그 내용을 확인할 수 있습니다. 주민등록번호, 비밀번호, 카드 번호와 같은 민감한 개인 정보를 페이로드에 담는 것은 절대 금물입니다! 🙅‍♀️


예방책:

  • 페이로드에는 사용자를 식별할 수 있는 최소한의 정보(예: 사용자 ID)만 담아야 합니다.
  • 만약 민감한 데이터를 담아야 한다면, JWE(JSON Web Encryption)를 사용하여 페이로드 자체를 암호화하는 것을 고려해야 합니다.

안전한 저장소 사용 (XSS 방지)

웹 브라우저에서 JWT를 localStorage나 sessionStorage에 저장하는 경우가 많습니다. 하지만 이 저장소들은 자바스크립트를 통해 쉽게 접근이 가능하기 때문에, XSS(Cross-Site Scripting) 공격에 취약합니다. 공격자가 사이트에 악성 스크립트를 삽입하는 데 성공하면, 저장된 토큰을 손쉽게 훔쳐갈 수 있습니다.

예방책:

  • 토큰을 저장할 때는 HttpOnly 속성을 설정한 쿠키(Cookie)를 사용하는 것이 더 안전합니다. HttpOnly 쿠키는 자바스크립트로 접근할 수 없어 XSS 공격으로부터 토큰을 보호할 수 있습니다.
  • 쿠키 사용 시には Secure 속성을 함께 사용하여 HTTPS 연결에서만 쿠키가 전송되도록 하고, SameSite 속성을 설정하여 CSRF(Cross-Site Request Forgery) 공격을 방지하는 것이 좋습니다.

마치며 ✨

JWT는 현대적인 웹 인증 방식에 있어 매우 강력하고 유용한 도구입니다. 하지만 그 편리함 이면에는 오늘 살펴본 것과 같은 다양한 보안 위협이 숨어있습니다. JWT의 구조와 동작 원리를 정확히 이해하고, 발생할 수 있는 취약점을 인지하여 안전한 방법으로 사용하는 것이 무엇보다 중요합니다.

보안은 '한 번 설정하고 끝'이 아니라, 지속적인 관심과 노력이 필요한 분야라는 점을 꼭 기억해주세요! 😊


JWT, JSON Web Token, 보안, 취약점, 웹 보안, 인증, Algorithm Confusion, XSS, Replay Attack