1. Hashing
가장 많이 쓰이는 암호화 방식 중의 하나. 다른 암호화 방식들은 복호화가 가능하지만, 해싱은 암호화만 가능하다.(단방향 암호화 방식) 해시 함수(Hash Function)를 사용하여 암호화를 진행함.
해시 함수의 특징
- 항상 같은 길이의 문자열을 리턴
- 서로 다른 문자열에 동일한 해시 함수를 사용하면 반드시 다른 결과값이 리턴
- 동일한 문자열에 동일한 해시 함수를 사용하면 항상 같은 결과값이 리턴
해싱의 목적
데이터 자체를 사용하는 것이 아니라 동일한 값의 데이터를 사용하고 있는지의 여부를 확인하는 것.
정확한 값을 알지 못해도 해싱한 값이 일치한다면 정확한 데이터를 입력했다는 것을 알 수 있다.
=> 민감한 데이터를 다루는 상황에서 데이터 유출의 위험성은 줄이고, 데이터의 유효성은 검증할 수 있다.
레인보우 테이블과 솔트(Salt)
레인보우 테이블
동일한 문자열에 동일한 해시 함수를 사용하면 항상 같은 결과값이 나온다는 특성을 이용해 해시 함수를 거치기 이전의 값을 알아낼 수 있도록 기록해 놓은 표. 기록된 값의 경우에는 유출시 해싱하더라도 해싱 이전의 값을 알아낼 수 있으므로 보안상 위협이 될 수 있음.
https://www.thesecurityblogger.com/understanding-rainbow-tables/
솔트(Salt)
소금을 치듯 해싱 이전의 값에 임의의 값을 더해 데이터가 유출되더라도 해싱 이전의 값을 알아내기 더욱 어렵게 만드는 방법. 해싱 값이 유출되더라도 솔트가 함께 유출 된 것이 아니라면 암호화 이전의 값을 알아내는 것은 불가능에 가까움.
2. Token
세션 기반 인증
- 서버에서 유저의 상태를 관리
- 하나의 서버에서만 접속 상태를 가짐으로 분산에 불리. 다수의 서버를 사용할 경우 서버간 세션 데이터 공유 필요함
- => 토큰 기반 인증 방식 등장
토큰(Token)
사용자 인증 정보와 권한 정보를 포함한 정보를 담은 암호화된 문자열. 클라이언트에서 인증 정보를 저장할 수 있다.
=> 토큰 인증 방식을 사용하면 유저의 인증 정보를 클라이언트에 저장할 수 있기 때문에 세션 인증 방식과 비교해 서버의 부하나 메모리 부족 등의 문제를 줄일 수 있다.
토큰 인증 방식의 흐름
- 사용자가 인증 정보를 담아 서버에 로그인 요청
- 서버가 데이터베이스에 저장된 사용자의 인증 정보를 확인
- 인증 성공시 해당 사용자의 인증 및 권한 정보를 서버의 비밀 키와 함께 토큰으로 암호화
- 생성된 토큰은 클라이언트로 전달
- Authorization 헤더 사용 / 쿠키로 전달
- 전달받은 토큰을 클라이언트가 저장
- Local Storage, Session Storage, Cookie 등
- 클라이언트가 서버로 리소스를 요청할때 토큰을 함께 전달
- Authorization 헤더 사용 / 쿠키로 전달
- 서버가 전달받은 토큰을 서버의 비밀 키를 통해 검증.
=> 토큰의 위조 여부, 또는 토큰의 유효기간이 만료되었는지 확인 가능 - 토큰이 유효하다면 클라이언트의 요청에 대한 응답 데이터 전송
토큰 인증 방식의 장점
- 무상태성
서버가 유저의 인증상태를 관리하지 않음. 서버는 비밀 키를 통해 클라이언트에서 보낸 토큰의 유효성만 검증하면 됨
=> 무상태적인 아키텍처 구축 가능 - 확장성
다수의 서버가 공통된 세션 데이터를 가질 필요 없음
=> 서버 확장이 용이 - 어디서나 토큰 생성 가능
토큰의 생성과 검증이 하나의 서버에서 이루어지지 않아도 되기 때문에 토큰 생성만을 담당하는 서버 구축 가능
=> 여러 서비스 간의 공통된 인증 서버 구현 가능 - 권한 부여가 용이
토큰은 인증 상태, 접근 권한 등 다양한 정보를 담을 수 있기 때문에 사용자 권한 부여에 용이.
=> 관리자 권한 부여 및 정보에 접근 할 수 있는 범위 설정 가능
토큰 인증 방식의 한계
- 무상태성
인증 상태를 관리하는 주체가 서버가 아니다. 즉 토큰이 탈취되더라도 해당 토큰을 강제로 만료시킬 수 없다.
=> 토큰이 만료될때까지 사용자로 가장해 계속 요청할 수 있음 - 유효 기간
토큰이 탈취되는 상황을 대비해 유효기간 설정
- 유효기간을 짧게 설정할 경우 : 사용자가 토큰이 만료될때마다 다시 로그인 해야함. 좋지 않은 사용자 경험 제공
- 유효기간을 길게 설정할 경우 : 토큰이 탈취될 경우 더 치명적으로 작용할 수 있음
- 토큰의 크기
토큰에는 여러 정보를 담을 수 있는 만큼, 데이터를 많이 담으면 암호화 하는 과정이 길어지고 토큰의 크기도 커진다.
=> 네트워크 비용 문제 발생
JWT (JSON Web Token)
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
JSON 객체에 정보를 담고 이를 토큰으로 암호화 하여 전송할 수 있는 기술.
클라이언트가 서버에 요청시 인증정보를 암호화된 JWT 토큰으로 제공하고, 서버는 이 토큰을 검증하여 인증정보를 확인할 수 있음
구성
점이 찍힌 부분을 기준으로 세 부분으로 나눌 수 있다. 각각 Header, Payload, Signature라고 한다.
Header
토큰 자체를 설명하는 데이터. 토큰의 종류, 시그니처를 만들때 사용할 알고리즘을 JSON 데이터 형태로 작성함
=> base64방식으로 인코딩 하면 Header 완성.
{
"alg": "HS256",
"typ": "JWT"
}
base64방식은 원한다면 얼마든지 디코딩할 수 인코딩 방식임으로 비밀번호 등 민감한 정보를 담지 않도록 주의해야 한다.
Payload
HTTP의 페이로드처럼 전달하려는 내용물을 담고 있는 부분.
권한, 개인정보, 토큰의 발급 시간 및 만료 시간 등의 정보들을 JSON 형태로 담는다.
base64 방식으로 인코딩하면 Payload 완성.
{
"sub": "someInformation",
"name": "phillip",
"iat": 151623391
}
Signature
토큰의 무결성을 확인하는 부분. Header와 Payload를 서버의 비밀키(암호화에 추가할 salt)와 Header에서 지정한 알고리즘(alg)을 사용하여 해싱한다.
예를 들어, 만약 HMAC SHA256 알고리즘을 사용한다면 Signature는 아래와 같은 방식으로 생성된다
HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);
토큰을 발급할때 사용한 Secret(비밀키)를 정확하게 알고 있지 않다면 유효한 Signature를 만들 수 없기 때문에, 서버가 검증하는 단계에서 올바르지 않은 토큰임을 알아낼 수 있다.
액세스 토큰(Access Token)과 리프레시 토큰(Refresh Token)
토큰 인증의 한계를 극복하기 위해 고안된 방법들 중 가장 대표적인 구현 방법.
Access Token
서버에 접근하기 위한 토큰. 보안을 위해 보통 24시간 정도의 짧은 유효기간이 설정되어 있다.
Refresh Token
액세스 토큰이 만료되었을때 새로운 액세스 토큰을 발급받기 위해 사용되는 토큰. 액세스 토큰보다 긴 유효기간을 설정한다.
=> 액세스 토큰이 만료되더라도 리프레시 토큰의 유효기간이 남아있다면
재로그인할 필요 없이 지속해서 인증 상태를 유지 할 수 있음
물론 리프레시 토큰의 도입도 모든 문제를 해결해주지 않는다.
리프레시 토큰은 긴 유효기간을 가지고 있어 해당 토큰마저 탈취되면 토큰의 긴 유효기간 동안 계속해서 액세스 토큰을 생성해 사용자의 정보를 해킹할 수 있다.
중요한 것은 보안과 사용자 경험 사이의 적절한 균형을 찾는것이다.
'study > TIL' 카테고리의 다른 글
23.03.13 - 기술면접 (0) | 2023.03.13 |
---|---|
23.03.09 - OAuth (0) | 2023.03.09 |
23.03.07 - Cookie, Session (0) | 2023.03.07 |
23.03.06 - TCP/IP, 네트워크 계층 모델, HTTP, HTTPS (0) | 2023.03.06 |
23.03.02 ~ 03 - 웹 접근성, WAI-ARIA (0) | 2023.03.02 |