가장 많이 쓰이는 암호화 방식 중에 하나인 해싱은 암호화만 가능하고 복호화는 불가능합니다.
해싱의 목적은 데이터를 사용하는 것이 아니라, 동일한 값의 데이터를 사용하고 있는지 여부만 확인하는 것이 목적이기 때문에 유저의 비밀번호를 몰라도 해싱한 값이 일치하는지를 판단하여 비밀번호를 확인할 수 있고, 비밀번호를 모르기 때문에 위험도도 줄어들게 됩니다.
해싱은 해시 함수(Hash Function)를 사용하여 암호화를 진행하는데, 해시 함수는 입력 데이터를 해시값으로 매핑하는 역할을 합니다.
<해싱함수의 특징>
- 항상 고정된 크기의 출력 값을 생성합니다.
예를 들어, 256비트 해시 함수는 항상 256비트 크기의 해시 값을 반환합니다.
결과값이 문자열이라면 문자 길이는 항상 동일합니다.- 다양한 입력에 대해 고르게 분포된 출력을 합니다.
서로 다른 문자열에 동일한 해시 함수를 사용하면 반드시 다른 결과값이 나옵니다.
입력 데이터의 작은 변화도 해시값의 크게 달라지도록 보장합니다.- 충돌방지
충돌은 서로 다른 입력에 대해 동일한 해시값이 생성되는 현상을 말합니다. 좋은 해시 함수는 충돌이 발생할 확률을 최소화하여 보장합니다. 그러나 완전히 충돌을 피하는 것은 불가능하며, 충돌이 발생할 수 있는 경우에도 안전한 시스템을 구축하기 위해 충분한 크기의 해시값을 사용합니다.- 동일한 문자열에 동일한 해시 함수를 사용하면 항상 같은 결과값이 나옵니다.
해시 함수는 일방향 함수로, 해시값을 통해 입력 데이터를 다시 복원할 수 없습니다. 즉, 해시값으로부터 원래 데이터를 유추하는 것은 매우 어렵습니다. 하지만 항상 같은 결과값이 나온다는 특성을 이용해 해시 함수를 거치기 이전의 값을 알아낼 수 있도록 기록해 놓은 표인 레인보우 테이블이 존재합니다. 레인보우 테이블에 기록된 값의 경우에는 유출이 되었을 때 해싱을 했더라도 해싱 이전의 값을 알아낼 수 있으므로 보안상 위협이 될 수 있습니다.
그래서 해싱 이전 값에 임의의 값을 더해 데이터가 유출되더라도 해싱 이전의 값을 알아내기 더욱 어렵게 만드는 방법인 솔트(Salt)가 있습니다. 솔트를 사용하게 되면 해싱 값이 유출되더라도, 솔트가 함께 유출된 것이 아니라면 암호화 이전의 값을 알아내는 것은 불가능에 가까워집니다.
비밀번호 + 솔트 | 해시 함수(SHA1) 리턴 값 예시 |
---|---|
‘password’ + ‘salt’ | ‘C88E9C67041A74E0357BEFDFF93F87DDE0904214’ |
‘Password’ + ‘salt’ | ‘38A8FDE622C0CF723934BA7138A72BEACCFC69D4’ |
‘kimcoding’ + ‘salt’ | ‘8607976121653D418DDA5F6379EB0324CA8618E6’ |
HTTP 프로토콜은 상태가 없는(stateless) 특징이 있는데 쿠키를 통해 상태 정보를 기억시켜주기 때문에 두 요청이 동일한 브라우저에서 들어왔는지 아닌지를 판단할 때 주로 사용합니다.
HTTP 쿠키(웹 쿠키, 브라우저 쿠키)는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각입니다. 브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 HTTP 요청 시 저장된 쿠키 데이터를 함께 전송합니다. 모든 요청마다 쿠키도 함께 전송되기 때문에, (특히 mobile data connections에서) 성능이 떨어지는 원인이 될 수 있습니다.
쿠키의 목적
- 세션 관리(Session management)
서버에 저장해야 할 로그인, 장바구니, 게임 스코어 등의 정보 관리- 개인화(Personalization)
사용자 선호, 테마 등의 세팅- 트래킹(Tracking)
사용자 행동을 기록하고 분석하는 용도
HTTP 요청을 수신할 때, 서버는 응답과 함께 Set-Cookie 헤더를 전송할 수 있습니다. 쿠키는 보통 브라우저에 의해 저장되며, 그 후 쿠키는 같은 서버에 의해 만들어진 요청(Request)들의 Cookie HTTP 헤더안에 포함되어 전송됩니다.
// 쿠키 만드는법
Set-Cookie: <cookie-name>=<cookie-value>
// 예시) 이 서버 헤더는 클라이언트에게 쿠키를 저장하라고 전달합니다.
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
// 이제 서버로 요청시 브라우저는 Cookie 헤더를 사용하여 저장했던 모든 쿠키들을 회신할 것입니다.
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
서버는 쿠키를 이용하여 데이터를 저장하고 원할 때 이 데이터를 다시 불러와 사용할 수 있습니다.
하지만 데이터를 저장한 이후 특정 조건들이 만족하는 경우에만 다시 가져올 수 있습니다.
이런 조건들은 쿠키 옵션으로 표현할 수 있습니다.
Cookie Options | ||
---|---|---|
Domain | 서버와 '요청 도메인'이 일치하면 쿠키 전송 | naver에서 받은 쿠키 google전송 불가 |
Path | 서버와 '요청 세부경로'가 일치하면 쿠키 전송 | Path에 설정된 URL를 만족하면 쿠키 전송 |
MaxAge or Expires | 쿠키의 유효기간 설정 | 세션쿠키와 영속성 쿠키로 나누어짐 |
HTTP Only | 스크립트의 쿠키 접근 가능 여부 결정 | true인 경우, 자바스크립트에서 쿠키 접근불가 |
Secure | HTTPS 프로토콜에서만 쿠키 전송 여부 결정 | true로 설정된 경우 HTTPS만 쿠키 전송 |
SameSite | CORS 요청의 경우 옵션 및 메서드에 따라 쿠키 전송 여부 결정 | Lax, Strict, None |
쿠키를 사용하는 것은 보안에 취약하기 때문에 민감한 정보는 쿠키에 담아서는 안됩니다.
쿠키가 데이터를 클라이언트에 저장하는 방식이였다면 세션은 데이터를 서버에 저장하고, 데이터에 대한 ID를 암호화하여 쿠키에 담아서 클라이언트에 전달하여 사용하는 방식입니다.
세션 전달을 통해 서버는 클라이언트의 상태와 데이터를 유지하고, 클라이언트와의 연속성을 유지할 수 있습니다. 이를 통해 로그인 상태 유지, 장바구니 기능, 사용자 지향적인 경험 제공 등을 구현할 수 있습니다.
단점은 서버메모리에 세션정보를 저장하므로 서버이용자가 많으면 메모리의 일정부분을 계속 차지하므로 가용메모리의 양이 줄어 서버의 성능이 줄어들 수 있습니다.
또한 세션은 서버 측에서 상태를 유지하므로 여러 서버를 사용하는 분산 환경에서 확장성이 제한될 수 있습니다.(토큰 기반 인증 시스템을 사용하면 세션의 일부 단점을 보완할 수 있습니다.)
그리고 여전히 쿠키를 사용하고 있으므로 XSS공격에 대비하여야 합니다.
클라이언트 요청: 클라이언트(웹 브라우저 등)가 서버에 요청을 보냅니다. 이 요청은 보통 HTTP 요청 메시지로 전송됩니다.
서버 응답: 서버는 클라이언트의 요청을 받고, 이에 대한 응답을 생성합니다. 응답은 보통 HTTP 응답 메시지로 전송됩니다.
세션 식별자 전달: 서버는 클라이언트에게 세션 식별자(Session Identifier)를 전달합니다. 세션 식별자는 일반적으로 쿠키(Cookie)를 통해 전달됩니다. 쿠키는 클라이언트의 웹 브라우저에 저장되고, 클라이언트가 서버에 요청을 보낼 때마다 쿠키가 함께 전송됩니다.
세션 저장: 서버는 세션 식별자를 사용하여 클라이언트의 상태와 데이터를 관리하는 세션 저장소에 저장합니다. 세션 저장소는 일반적으로 서버의 메모리, 데이터베이스, 외부 스토리지 등을 사용하여 구현될 수 있습니다.
세션 데이터 접근: 클라이언트가 서버에 추가 요청을 보낼 때마다, 클라이언트의 세션 식별자를 서버가 전달받습니다. 서버는 세션 식별자를 사용하여 해당 클라이언트의 세션 데이터를 찾고, 필요한 정보를 가져옵니다.
응답과 세션 업데이트: 서버는 클라이언트의 요청에 대한 응답을 생성하고, 필요에 따라 세션 데이터를 업데이트합니다. 업데이트된 세션 데이터는 세션 저장소에 다시 저장됩니다.
로그아웃은 사용자가 현재 세션 또는 인증된 상태를 종료하고, 웹 애플리케이션에서 더 이상 접근할 수 없도록 하는 동작입니다. 로그아웃을 통해 사용자는 개인 정보 보호와 보안을 강화할 수 있습니다.
서버가 클라이언트의 쿠키를 임의로 삭제할 수는 없습니다. 대신, set-cookie로 클라이언트에게 쿠키를 전송할 때 세션 아이디의 키값을 무효한 값으로 갱신할 수 있습니다.
쿠키는 세션 아이디, 즉 인증 성공에 대해 증명을 하고 있으므로, 탈취될 때 서버는 해당 요청이 인증된 사용자의 요청이라고 판단합니다. 그러므로 로그아웃은 다음 두 가지 작업을 해야 합니다.
로그아웃은 사용자의 세션을 종료하여 인증된 상태를 끝냅니다. 이로써 다른 사람이 해당 사용자의 계정에 접근하는 것을 방지하고, 보안을 강화할 수 있습니다.
사용자가 로그아웃하면, 웹 애플리케이션은 더 이상 해당 사용자의 정보를 유지하지 않아 개인 정보 보호 측면에서 이점을 제공합니다.