Cookie 인증
쿠키는 Key와 Value로 이뤄진 일종의 단위로, 서버가 클라이언트에게 쿠키를 발급하면,
클라이언트는 서버에 요청을 보낼 때마다 쿠키를 같이 전송합니다.
서버는 클라이언트의 요청에 포함된 쿠키를 확인해 클라이언트를 구분할 수 있습니다.
용도
일반적으로 쿠키는 클라이언트의 정보 기록과 상태 정보를 표현하는 용도로 사용합니다.
상태 정보
많은 웹 사이트에서는 회원 가입과 로그인을 통해 개개인에게 맞춤형 서비스를 제공합니다.
웹 서버에서는 수많은 클라이언트의 로그인 상태와 이용자를 구별해야 하는데,
이때 클라이언트를 식별할 수 있는 값을 쿠키에 저장해 사용합니다.

단점 - 쿠키 변조
쿠키는 클라이언트의 브라우저에 저장되고 요청에 포함되는 정보입니다. 따라서, 악의적인 클라이언트는 쿠키 정보를 변조해 서버에 요청을 보낼 수 있습니다. 만약 서버가 별다른 검증 없이 쿠키를 통해 이용자의 인증 정보를 식별한다면 공격자가 타 이용자를 사칭해 정보를 탈취할 수 있습니다.

세션 인증
쿠키에 인증 상태를 저장하지만 클라이언트가 인증 정보를 변조할 수 없게 하기 위해 세션(Session)을 사용합니다.
세션은 인증 정보를 서버에 저장하고 해당 데이터에 접근할 수 있는 키(유추할 수 없는 랜덤한 문자열)를 만들어 클라이언트에 전달하는 방식으로 작동합니다. 해당 키를 일반적으로 Session ID라고 합니다.
브라우저는 해당 키를 쿠키에 저장하고 이후에 HTTP 요청을 보낼 때 사용합니다.서버는 요청에 포함된 키에 해당하는 데이터를 가져와 인증 상태를 확인합니다.
쿠키는 데이터 자체를 이용자가 저장, 세션은 서버가 저장
쿠키에는 세션 정보가 저장되어 있고 서버는 이를 통해 이용자 식별하고 인증을 처리합니다.
공격자가 이용자의 쿠키를 훔칠 수 있으면 세션에 해당하는 이용자의 인증 상태를 훔칠 수 있는데,
이를 세션 하이재킹 (Session Hijacking)이라고 합니다.

Token 인증
토큰 기반 인증 시스템은 클라이언트가 서버에 접속을 하면 서버에서 해당 클라이언트에게 인증되었다는 의미로 '토큰'을 부여한다. 이 토큰은 유일하며 토큰을 발급받은 클라이언트는 또 다시 서버에 요청을 보낼 때 요청 헤더에 토큰을 심어서 보낸다. 그러면 서버에서는 클라이언트로부터 받은 토큰을 서버에서 제공한 토큰과의 일치 여부를 체크하여 인증 과정을 처리하게 된다.
기존의 세션기반 인증은 서버가 파일이나 데이터베이스에 세션정보를 가지고 있어야 하고 이를 조회하는 과정이 필요하기 때문에 많은 오버헤드가 발생한다. 하지만 토큰은 세션과는 달리 서버가 아닌 클라이언트에 저장되기 때문에 메모리나 스토리지 등을 통해 세션을 관리했던 서버의 부담을 덜 수 있다. 토큰 자체에 데이터가 들어있기 때문에 클라이언트에서 받아 위조되었는지 판별만 하면 되기 떄문이다.
토큰은 앱과 서버가 통신 및 인증할때 가장 많이 사용된다. 왜냐하면 웹에는 쿠키와 세션이 있지만 앱에서는 없기 때문이다.
Token 방식의 단점
쿠키/세션과 다르게 토큰 자체의 데이터 길이가 길어, 인증 요청이 많아질수록 네트워크 부하가 심해질수 있다.
Payload 자체는 암호화되지 않기 때문에 유저의 중요한 정보는 담을 수 없다.
토큰을 탈취당하면 대처하기 어렵다. (따라서 사용 기간 제한을 설정하는 식으로 극복한다)

JWT ( JSON Web Token )
json-web-token
JWT(JSON Web Token)란 인증에 필요한 정보들을 암호화시킨 JSON 토큰을 의미한다. 그리고 JWT 기반 인증은 JWT 토큰(Access Token)을 HTTP 헤더에 실어 서버가 클라이언트를 식별하는 방식이다
JWT는 JSON 데이터를 Base64 URL-safe Encode 를 통해 인코딩하여 직렬화한 것이며, 토큰 내부에는 위변조 방지를 위해 개인키를 통한 전자서명도 들어있다. 따라서 사용자가 JWT 를 서버로 전송하면 서버는 서명을 검증하는 과정을 거치게 되며 검증이 완료되면 요청한 응답을 돌려준다.
JWT 구조

헤더 (Header)
- typ: 토큰의 타입을 지정합니다. = JWT
- alg: 해싱 알고리즘을 지정합니다. 해싱 알고리즘으로는 보통 HMAC SHA256 혹은 RSA 가 사용되며, 이 알고리즘은, 토큰을 검증 할 때 사용되는 signature 부분에서 사용됩니다.
{
"typ": "JWT",
"alg": "HS256"
}
정보 (payload)
Payload 부분에는 토큰에 담을 정보가 들어있습니다. 여기에 담는 정보의 한 ‘조각’ 을 클레임(claim) 이라고 부르고, 이는 name / value 의 한 쌍으로 이뤄져있습니다. 토큰에는 여러개의 클레임 들을 넣을 수 있습니다.
클레임 의 종류는 다음과 같이 크게 세 분류로 나뉘어져있습니다:
- 등록된 (registered) 클레임
- 공개 (public) 클레임
- 비공개 (private) 클레임
#1 등록된 (registered) 클레임
등록된 클레임들은 서비스에서 필요한 정보들이 아닌, 토큰에 대한 정보들을 담기위하여 이름이 이미 정해진 클레임들입니다. 등록된 클레임의 사용은 모두 선택적 (optional)이며, 이에 포함된 클레임 이름들은 다음과 같습니다:
- iss: 토큰 발급자 (issuer)
- sub: 토큰 제목 (subject)
- aud: 토큰 대상자 (audience)
- exp: 토큰의 만료시간 (expiraton), 시간은 NumericDate 형식으로 되어있어야 하며 (예: 1480849147370) 언제나 현재 시간보다 이후로 설정되어있어야합니다.
- nbf: Not Before 를 의미하며, 토큰의 활성 날짜와 비슷한 개념입니다. 여기에도 NumericDate 형식으로 날짜를 지정하며, 이 날짜가 지나기 전까지는 토큰이 처리되지 않습니다.
- iat: 토큰이 발급된 시간 (issued at), 이 값을 사용하여 토큰의 age 가 얼마나 되었는지 판단 할 수 있습니다.
- jti: JWT의 고유 식별자로서, 주로 중복적인 처리를 방지하기 위하여 사용됩니다. 일회용 토큰에 사용하면 유용합니다.
#2 공개 (public) 클레임
공개 클레임들은 충돌이 방지된 (collision-resistant) 이름을 가지고 있어야 합니다. 충돌을 방지하기 위해서는, 클레임 이름을 URI 형식으로 짓습니다.
{
"https://brains88.com/jwt_claims/is_admin": true
}
#3 비공개 (private) 클레임
등록된 클레임도아니고, 공개된 클레임들도 아닙니다. 양 측간에 (보통 클라이언트 <->서버) 협의하에 사용되는 클레임 이름들입니다. 공개 클레임과는 달리 이름이 중복되어 충돌이 될 수 있으니 사용할때에 유의해야합니다.
{
"username": "brains88"
}
Payload 예시
{
"iss": "brains88.com",
"exp": "1485270000000",
"https://brains88.com/jwt_claims/is_admin": true,
"userId": "11028373727102",
"username": "brains88"
}
서명 (signature)
JSON Web Token 의 마지막 부분은 바로 서명(signature) 입니다. 이 서명은 헤더의 인코딩값과, 정보의 인코딩값을 합친후 주어진 비밀키로 해쉬를 하여 생성합니다.
서명 부분을 만드는 슈도코드(pseudocode)의 구조는 다음과 같습니다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
이렇게 만든 해쉬를, base64 형태로 나타내면 됩니다 (문자열을 인코딩 하는게 아닌 hex → base64 인코딩을 해야합니다)

JWT 장점
JSON 웹 토큰의 사용을 권장하는 몇 가지 이유는 다음과 같다.
- URL 파라미터와 헤더로 사용
- 수평 스케일이 용이
- 디버깅 및 관리가 용이
- 트래픽 대한 부담이 낮음
- REST 서비스로 제공 가능
- 내장된 만료
- 독립적인 JWT
JWT 단점
- 토큰은 클라이언트에 저장되어 데이터베이스에서 사용자 정보를 조작하더라도 토큰에 직접 적용할 수 없습니다.
- 더 많은 필드가 추가되면 토큰이 커질 수 있습니다.
- 비상태 애플리케이션에서 토큰은 거의 모든 요청에 대해 전송되므로 데이터 트래픽 크기에 영향을 미칠 수 있습니다.
JWT의 Access Token / Refresh Token
다만 이 JWT도 제 3자에게 토큰 탈취의 위험성이 있기 때문에, 그대로 사용하는것이 아닌 Access Token, Refresh Token 으로 이중으로 나누어 인증을 하는 방식을 현업에선 취한다.
Access Token 과 Refresh Token은 둘다 똑같은 JWT이다. 다만 토큰이 어디에 저장되고 관리되느냐에 따른 사용 차이일 뿐이다.
- Access Token : 클라이언트가 갖고있는 실제로 유저의 정보가 담긴 토큰으로, 클라이언트에서 요청이 오면 서버에서 해당 토큰에 있는 정보를 활용하여 사용자 정보에 맞게 응답을 진행
- Refresh Token : 새로운 Access Token을 발급해주기 위해 사용하는 토큰으로 짧은 수명을 가지는 Access Token에게 새로운 토큰을 발급해주기 위해 사용. 해당 토큰은 보통 데이터베이스에 유저 정보와 같이 기록.
정리하자면, Access Token은 접근에 관여하는 토큰, Refresh Token은 재발급에 관여하는 토큰의 역할로 사용되는 JWT 이라고 말할 수 있다.
OAuth 2.0
"OAuth 2.0 승인 프레임워크를 사용하면 타사 애플리케이션이 리소스 소유자 및 HTTP 서비스 간의 승인 상호작용을 조정하여 리소스 소유자 대신 액세스하거나 타사 애플리케이션이 자체적으로 액세스하도록 허용하여 HTTP 서비스에 제한적으로 액세스하도록 할 수 있습니다."
반드시 알아 두어야 할 사항은 OAuth 2.0은 사용자가 앱에 로그인 사용자 인증 정보를 증명하지 않아도 앱이 사용자의 보호된 리소스(예: 은행 계좌 또는 사용자가 앱에서 액세스하려고 할 수 있는 기타 민감한 정보)에 제한적으로 액세스하도록 허용한다는 사실입니다.
팁: 여러 은행 계좌에 액세스할 수 있는 앱을 발견했다고 가정해 보겠습니다. 앱이 세금 관련 업무를 처리하거나 예산을 관리하는 데 사용될 수도 있습니다. 앱으로 관리하려는 은행 계좌가 3개 있고 계좌마다 사용자 이름과 비밀번호가 다릅니다. 이제 앱에서 은행 계좌에 액세스하려면 민감한 사용자 인증 정보가 필요합니다. 기본적으로 이러한 민감한 정보를 앱에 제공합니다. 앱이 비밀번호 및 사용자 이름을 소유하는 것을 신뢰할 수 있나요? 앱이 해킹되면 어떻게 될까요? 이제 각 계정의 은행 사용자 인증 정보를 변경해야 한다는 점을 기억해야 합니다. 이는 OAuth 2.0이 해결하는 근본적인 문제입니다. 자세한 내용은 아래를 참조하세요.
OAuth 2.0 흐름

알아야 할 용어
- 클라이언트: 앱이라고도 합니다. 휴대기기 또는 기존 웹 앱에서 실행되는 앱일 수 있습니다. 앱은 리소스 소유자를 대신하여 보호된 애셋에 대해 리소스 서버에 요청을 보냅니다. 리소스 소유자는 보호된 리소스에 액세스할 수 있는 권한을 앱에 부여해야 합니다.
- 리소스 소유자: 최종 사용자라고도 합니다. 일반적으로 보호 대상 리소스에 대한 액세스 권한을 부여할 수 있는 사람(또는 다른 주체)입니다. 예를 들어 앱이 소셜 미디어 사이트 중 하나의 데이터를 사용해야 하는 경우 리소스 소유자만이 데이터에 대한 액세스 권한을 앱에 부여할 수 있습니다.
- 리소스 서버: 리소스 서버는 Facebook, Google 또는 Twitter와 같은 서비스, 인트라넷의 HR 서비스 또는 B2B 엑스트라넷의 파트너 서비스라고 생각하면 됩니다. Apigee는 OAuth 토큰 검증이 필요할 때마다 API 요청을 처리하는 리소스 서버입니다. 리소스 서버는 보호된 리소스를 앱에 제공하기 전에 일종의 승인을 요구합니다.
- 승인 서버: 승인 서버는 OAuth 2.0 사양을 준수하여 구현되며, 승인 부여 검증 및 리소스 서버에서 사용자 데이터에 액세스할 수 있는 권한을 앱에 부여하는 액세스 토큰 발급을 담당합니다. Apigee에서 토큰 엔드포인트를 구성할 수 있습니다. 이 경우 Apigee가 승인 서버의 역할을 수행합니다.
- 승인 부여: 최종 사용자를 대신하여 액세스 토큰을 검색할 수 있는 권한을 앱에 부여합니다. OAuth 2.0은 4가지 구체적인 '부여 유형'을 정의합니다. OAuth 2.0 부여 유형이란을 참조하세요.
- 액세스 토큰: 보호된 리소스에 액세스하는 데 사용되는 사용자 인증 정보 역할을 하는 긴 문자열입니다. 액세스 토큰이란?을 참조하세요.
- 보호된 리소스: 리소스 소유자가 소유한 데이터입니다. 예를 들면 사용자의 연락처 목록, 계정 정보, 기타 민감한 정보가 있습니다.
로그인 인증 로직 5가지
1. Cookie
2. 세션 인증
3. Token 인증
4. JWT ( JSON Web Token )
5. OAuth 2.0
'Security > Web' 카테고리의 다른 글
| [SQL Injection] 로그인 CASE와 우회방법 (0) | 2023.04.16 |
|---|---|
| [Python] RSA 암호 구현 (0) | 2023.04.11 |
| [Wargame] [Python] 미스터 브루트 (0) | 2023.04.09 |
| XOR 연산을 이용한 암호화 / 복호화 / 공격 (0) | 2023.04.05 |
| Background: HTTP/HTTPS (0) | 2023.04.03 |