-
---
---
인터넷에 널려 있는 jwt로 회원기능 구현하는 강의들 많은데, 아무생각없이 그거 따라쳐서 회원기능 구현하면 코딩인생이 금방 끝날 수도 있다 왜?그냥하면 보안상의 헛점이 많아져서 그래. 이걸 알아볼거야
---
그 전에 회원기능 구현하는 법부터
사이트를 만들었는데 로그인한 사람만 볼 수 있게 하려면 코드를 어떻게 짜야 할까?
인터넷을 보면 2가지를 소개한다. session방식과 jwt를 이용한 token방식
---
이게 뭐냐면 둘다 동작방식은 유사해
회원인증방식의 기본은
1.유저가 로그인(id/pw)
2.서버가 유저한테 입장권 발급
3.사이트에서 뭐 할 때마다 유저에게 입장권 제시하게 만들면 됨
4.입장권 제출
5.입장권에 별문제가 없군 확인
6.유저에게 내용 보내준다
---
session vs token은 입장권에 써 있는 정보가 다르다
session은 입장권에 써있는 정보들이 별로 없고 발급번호 정도
회원이 입장권을 제시하면 서버가 메모리나 DB에 따로 만들어둔 입장권발급목록 엑셀파일 같은게 있다 session store라고
이 번호를 가진 입장권을 발급했었는지 조회, 별 문제 없으면 유저 통과 시켜주는 식
---
jwt방식은 입장권에 써 있는 정보가 많다
그래서 서버는 입장권을 검사할 때 입장권 자체 하나만 딱 까보고 유효기간이 별 문제 없으면 통과.
장점 : stateless, 회원이 많아질수록 서버의 부담이 상대적 덜해진다.
->기존의 세션 방식은 회원이 입장권을 제시할 때마다 저 엑셀파일도 조회해봐야되니까 힘들어
그래서 jwt쓰세요 좋습니다~ 하는건데
---
그냥 jwt로 대충 구현하면 심각한 보안이슈 4개 생김
일단 jwt입장권이 어떻게 생겼냐면
저 왼쪽이 jwt입장권인데, 저걸 어떻게 만드냐면
HEADER:에 기본 세팅값 같은것 입력
PAYLOAD:에 입장권 자체에 기록해둘 데이터
이것을 짧은 문자로 인코딩 해버린게(base64로 문자 압축) jwt입장권이다.
그리고
여기에 시크릿비번같은걸 입력할 수 있는데 이 비번이 달라지거나 PAYLOAD기존값이 좀 바뀌면
jwt입장권 문자도 기존과 달라지기 때문에 위조여부도 쉽게 알 수 있어
---
사람들이 잘 모르는 jwt의 헛점들이 있다
1.
여기 있는 알고리즘 부분을 none으로 적어놓고 jwt를 만드는 사람들이 있다. 그럼 안되고 HS256으로 잘 채워 넣으래
문제는 none으로 만든 입장권들을 서버로 보내는 악성유저들이 있다
왜냐면 어떤 서버들은 none으로 만든 jwt입장권들을 입장시켜 주는 경우가 있어
none으로 만든 jwt들을 거절하는 기능이 있는지 잘 봐야 한다(최신라이브러리들 잘 쓰면 걱정 안해도 된다)
---
2.
JWT는 디코딩이 매우 쉽다
다 나와, 민감한 유저 정보 그대로 집어 넣으면 안돼. 최소한의 정보들만
---
3.
시크릿키는 개발자 마음대로 결정할 수 있는데, 이걸 대충 적는 사람이 너무 많다
대충적으면 때려 맞추기 너무 쉽다
브루트포스 어택이라고 하는데, 뚫리는 서버들이 많다고 기사가 난적도 있어
유명한 블로그 글, 유튜브 강의에 있던 시크릿 키들 그대로 적어보면 꽤 적중률이 좋을거다
시크릿 키 털리면 입장권을 맘대로 발행할 수 있는 것
솔루션
- 키를 매우 길게 적든지
- 공유금지 등 안전하게 관리 잘하기
- 키를 생성용키 / 검증용키 2개 사용(private key + public key), 구현하려면 귀찮기 때문에 jwt라이브러리 쓰는게 있으면 이런거 지원해주는지 알아봐
---
4.
jwt 탈취
기본적으로
누군가가 헬스장 입장권, 신용카드 잃어버리면 그 사람 책임이듯이 개발자는 굳이 생각할 필요 없거든
카드회사면 누가 카드 도난당했을 때 그 카드를 사용정지 시킨다든지 하면 조치는 취해줄 수 있어야 한다. 웹서비스도 마찬가지로 가능해야해
jwt방식은 구조상 입장권을 회수하거나 사용정지 시키거나 그런일이 어렵다
그래서 그 입장권의 유효기간이 지나기까지 계속 쓸 수 있어
솔루션
- 훔치기 어렵게 만들어둔 저장소가 있어
- 입장권 블랙리스트 운영, 특정 입장권들은 입장이 불가능하게 목록 따로 저장, 누가 입장권을 제시할 때마다 검사하는 것임. 근데 이러면 옛날 세션 방식이랑 다를게 없잖아
- 입장권의 유통기한을 매우 짧게 유지하는 것
이러면 입장권 재발급을 위한 refresh token이란 것을 따로 운영해야해
물론 refresh token도 탈취 당하는 경우도 있기 때문에 refresh token rotation이라는 방법을 갖다 써. refresh token을 재사용하거나 재발급요청을 발견하면 입장권을 발급해 주지 않는 식으로
복잡하지만 라이브러리 잘 찾아보면 있다
---
참고
nodejs 개발할 때 이런 라이브러리 갖다 쓰라고 배운적 있죠
이 라이브러리는 원래 토큰 생성 검증만 하는 라이브러리이기 때문에 보안기능 딱히 없다 refresh token이라든지..
제대로 쓰려면 추가기능을 직접 개발하거나 해야 한다.
---
결론
대부분의 서비스들은 session방식으로 회원인증 구현. 매우 간단하기 때문
---
회원이 1억명이라 DB에서 회원입장권 목록을 조회하는게 힘이든다면, microservice같은게 많다면, jwt쓰는게 더 나을수도 있어
보안이 중요한 사이트를 만들 때
jwt를 대충 가져다 쓰는 곳은 없다. jwt의 헛점들을 땜빵하기 위해 이것저것 복잡하게 운영하거나 session방식과 비슷하게 운영하고 있을 것
아니면 다른 업체의 인증서비스를
대신 이용하고 있거나
---
무슨 기술을 도입하기 전에 장점은 뭔지 단점은 뭔지 정확히 따진 후에 도입하는게 좋다
'기타' 카테고리의 다른 글
Markdown (1) 2022.12.29 왜 서버 거쳐서 DB연결? (1) 2022.12.28 CORS (0) 2022.12.20 WordPress 강의 (1) 2022.12.08 행렬 (0) 2022.06.04