[JWT] 쿠팡 개인정보 유출 사건의 원인과 재발 방지를 위한 고찰
포스트
취소

[JWT] 쿠팡 개인정보 유출 사건의 원인과 재발 방지를 위한 고찰

개요

이번 쿠팡 개인정보 유출 사건을 보고, JWT 인증 방식에 대해 다시한번 생각해보고 어떻게 하면 이와 유사한 사고를 방지할 수 있을지 생각해 보기 위해 작성한 글 입니다.

쿠팡 개인정보 유출 사건

2025년 11월 6일, 쿠팡에서 엑세스 토큰을 사용한 개인정보 유출이 발생했습니다. 쿠팡은 이 사실을 12일이나 지난 18일에 고객의 민원으로 알게되었고, 후속 조사를 통해 29일에 3,370만개의 고객 정보다 무단으로 유출되었다고 발표했습니다. 그리고 이런 개인정보 무단 접근은 무려 6월 25일부터 약 6개월이나 쿠팡도 모르게 진행되었다고 합니다. 우리나라 국민이 약 5,000만명인걸 고려하면 사실상 쿠팡 가입자가 모두 유출된거나 다름없습니다.
유출된 데이터는 배송지로 사용되던 주소, 새벽배송을 위한 공동현관 비밀번호, 이름, 전화번호 등 정말 다양한 데이터가 광범위하게 유출되었습니다.

유출 경로

그렇다면 도대체 해킹범들은 어떻게 이렇게나 많은 사용자들의 데이터에 무단으로 접근이 가능했을까요?
2025년 12월 5일 기준으로 아직 명확한 발표는 없으나, 여러 기사를 통해 나온 정보로 유추해 보겠습니다.

유출 경로를 설명하는 기사에 따르면, 해킹범은 서명키를 이용해 로그인 토큰을 생성해서 정보에 접근했다고 설명합니다. 그리고 해킹범은 현재는 퇴사한 이전에 쿠팡에서 인증 처리를 담당하던 개발자였다고 합니다.

유출에 대한 기술적 분석

여기부터 작성 내용은 기사를 통해 공개된 한정된 정보로 도출한 내용입니다. 사실과 다를 수 있음을 미리 밝힙니다.

JWT 인증 방식에 대해 접해본 분들이라면 토큰과 서명키에서 이번 해킹이 어떤식으로 이루어진건지 대충 눈치채셨을 겁니다. 우선 이해를 위해서는 JWT 인증 방식에 대해 이해가 필요한데, 일단은 이 글은 JWT 인증에 대해 중간중간 필요한 정도만 설명하겠습니다. JWT 인증에 대해 자세한 정보가 궁금하시다면 [JWT] Json Web Token를 읽으시는것을 추천드립니다.

JWT는 많은 서비스에서 사용중인 인증 방식입니다. JWT는 정해진 구조에 맞게 인증/인가 처리에 필요한 여러 정보들을 넣고 암호화 하여 인증 토큰을 만들고, 서버에서 토큰을 뜯어서 어떤 요청/데이터에 접근할 권한이 있는지 확인하는데 사용됩니다.
토큰에는 사용자의 고유 id, 토큰 생성 시간과 만료 시간 등 다양한 정보를 넣어 인증/인가 처리에 활용합니다. 그래서 특정 서비스의 서버에서 어떤 형식의 JWT를 구성해서 사용하는지 알면 제3자도 손쉽게 모방하여 정상적인 요청인척 할 수 있습니다.

이런 문제점을 개발자들도 알고 있기 때문에, 서버에서 토큰을 발급해줄때 이 서버에서 만든 토큰이 맞다는 의미로 서명을 합니다. 무작위의 문자열로 구성된 긴 문자열을 이용해 만들어진 JWT를 RS25과 같은 암호화 알고리즘으로 변환하여 JWT 맨 뒤에 추가함으로써 서명을 합니다. 이때 서명에 사용되는 무작위 문자열을 서명키라고 하는데, 해당 정보는 절대로 외부에 공개되지 않아야 합니다. 서명은 서버에서 생성한 토큰이라는걸 보증하는 과정인데, 서명키가 유출되면 누구나 서버에서 생성된것 처럼 위장이 가능하기 때문입니다.

이제 대략적인 유출 경로를 유추 할 수 있습니다. 해킹범은 쿠팡의 인증 처리 개발을 담당하던 직원이었습니다. 해킹범은 개발 과정에서 아마 JWT의 형식을 봤을것이고, 서명에 사용되는 서명키에도 접근이 가능했을겁니다. 해당 기능을 담당하던 직원이었으니까요.
해킹범은 쿠팡을 재직하며 확보한 정보들을 바탕으로 외부에서 임의의 액세스 토큰을 생성한 후, 훔쳐온 서명키를 이용해 서명하여 마치 서버에서 정상적으로 생성된 토큰인척 서버에 요청을 보냈을겁니다. 서버는 서명키도 같고 토큰 형식도 문제가 없으니 정상적인 요청이라고 판단했고, 의심 없이 요청한 정보를 제공했을겁니다.

물론 인증/인가 처리를 위해서는 토큰을 구성할때 요청하려는 유저의 고유 id와 같이 사전에는 알기 어려운 정보도 필요합니다. 제 생각에는 아예 어드민 계정의 인증 토큰을 만들어 어드민 권한으로도 사용자들의 일부 데이터를 얻은 뒤, 이렇게 얻은 정보로 각 사용자의 액세스 토큰을 만들어 개인정보를 열람하지 않았을까 싶습니다. 어드민 계정은 딱 한 사람에 대한 정보만 알아도 광범위한 정보를 얻을 수 있을테니까요.

JWT 인증 방식의 허점?

이번 사건은 JWT 인증 방식의 허점을 제대로 찌른 사건이라고 생각됩니다.
JWT 인증 방식에서는 보통 토큰을 일일히 서버에 저장해뒀다가 들어오는 토큰이 서버가 발급한게 맞는지 대조하면서 비교하지 않습니다. 서버는 들어온 토큰의 서명을 확인하고, 안에 있는 정보를 꺼내와 인증/인가 처리를 합니다. 이는 JWT 인증 방식의 장점중 하나로, Stateless하다고 합니다. 발급된 토큰을 저장하지 않기때문에 서버의 부담이 줄고, 빠른 인증/인가 처리가 가능합니다.

물론 JWT 인증 방식은 토큰이 제3자에게 노출되었을때를 대비한 여러 대비책이 있습니다. 토큰의 유효 기간 설정, 토큰 사용 범위 표기, AT-RT 토큰 인증 방식, RT 로테이션 등 정말 다양한 방법으로 토큰이 유출되었을때 얼마 못가 만료시키려고 합니다. 더 나아가 jti와 같이 토큰을 한 번만 사용이 가능하게 하여 토큰이 유출되어도 단 한번만 사용 가능하게 만들기도 합니다.
근데 위와같은 대비책은 어디까지나 외부에서는 서명키를 알 수 없어 직접 토큰을 새로 생성할 수 없을때 적용되는 대비책입니다. 서명키를 알게되는 순간 엑세스 토큰을 한번이라도 확보하면 구현 방식에 따라 다르긴 하지만 만료시간을 자체적으로 갱신하며 무한으로 토큰 갱신할 수 있습니다.

사실 서명키가 유출된건 정말 이례적인 경우입니다. 마치 도어락 비밀번호를 20자리로 설정해서 맞히기 어렵게 만들어놨는데, 마스터키가 유출된것 같은 상황이죠. 그래서 JWT 인증 방식의 허점이라고만 하기에는 어려운게, 이렇게 내부자가 작정하고 유출해버리면 아무리 어떤 대비책을 만들어도 답이 없습니다.

대비책

그렇다면 이번 쿠팡과 같은 유출 사고가 일어나지 않게 하려면 어떻게 해야할까요?

1. 서명키 주기적으로 바꾸기

가장 먼저 생각나는 대비책은 서명키를 주기적으로 바꾸는 방법입니다. 사실 이 사건 전까지 저는 서명키를 바꿀 생각은 한번도 안해봤습니다. 보통은 서버 내부에서 외부에서는 접근이 불가능하게 관리되니까요.
그러나 이러한 사고를 방지하려면 서명키를 주기적으로 바꾸는 방법이 가장 괜찮아보입니다. 서명키에 접근 가능했던 담당자가 일을 그만둘 때 마다 바꾸는 것도 좋을것 같습니다.

2. 서명키 접근 권환 최소화 하기

서명키에 접근이 가능한 사람을 애초에 최소화 하는 방법입니다. 개발 과정에서 구체적인 서명 키는 몰라도 모든 JWT 인증 로직은 구현이 가능합니다. 인증 개발 부서의 최고관리자만 접근 가능하게 하고, 다른 사람들은 모두 접근이 불가한 방식으로 권환을 최소화 하는 방법도 괜찮아 보입니다. 이렇게 하면 1번 방식을 적용해야하는 상황도 적게 나올테니까요.

3. 다른 인증 방식 사용하기

JWT가 아닌 아예 다른 인증 방식을 사용하는 방법입니다. 대표적으로 세션 인증 방식이 있습니다.
세션 인증 방식은 id/pw와 같이 인증된 사용자에게 세션 id를 발급 후 서버에 세션 id를 저장하여, 요청시 같이 온 세션 id가 유효한 세션 id인지 검사하는 방식입니다. 이 방식은 서버에서 저장된 데이터와 직접적으로 비교를 하기때문에 이번 사건과 같은 방식으로 유출이 불가능합니다.
물론 이는 JWT의 장점과 완전히 반대되는 인증 방식이므로 완전한 대비책이라고 하기엔 무리가 있습니다.


여러 대비책을 생각해 봤지만, 내부자가 직접 서명키를 유출해서 정보 유출을 일으키는 사건은 정말 대비가 어려운건 사실인것 같습니다. 이번 쿠팡 개인정보 유출 사건은 정말 어려운 사건이라고 생각됩니다. 대부분의 개발자들도 보통은 서버 내부에 있고 외부에 노출되지 않는 데이터는 유출될 일이 거의 없다고 생각해서 이런식으로 유출되는 상황을 많이 생각해보지 않았을 것 같습니다. 저 역시도 이전까지는 이런식으로 정보가 유출될 수 있다는걸 생각해본적이 없습니다. 이번 사건을 통해 저도 어떤식으로 중요한 정보를 관리해야 더욱 안전하게 관리가 가능한지 생각해 볼 수 있었던 것 같습니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

[Project] 하이스코어 프로젝트 1차 목표 달성 및 후기

[Project] Cloudflare 장애 대응 후기