TIL(2021.04.14 - 04.16)

한국·2021년 4월 24일
0

TIL

목록 보기
33/33
post-thumbnail


*출처 코드스테이츠

  • 위 그림을 보면 패스워드가 노출되어 있는게 보일것이다. 혹여나 어느하나의 패스워드가 뚫리게 된다면 은행, 페이스북, 구글같은 유명한사이트에 다 접속을 해봐서 접근을 하게되는 문제가 발생할수 있다. 그런데 만약 비밀번호를 암호화해서 저장하게 된다면 이런 문제가 발생하지 않게 될것이다.
  • 암호화 : 일련의 정보를 임의의 방식을 사용하여 다른 형태로 변환하여 해당 방식에 대한 정보를 소유한 사람을 제외하고 이해할 수 없도록 '알고리즘'을 이용해 정보를 관리하는 과정

Hashing

  • 어떠한 문자열에 '임의의 연산'을 적용하여 다른 문자열로 변환 하는것

    • 모든 값에 대해 해시 값을 계산하는데 오래 걸리지 않아야 한다.

    • 최대한 같은 해시 값을 피해야하며, 모든 값은 고유한 해시 값을 가진다.

    • 아주 작은 단위의 변경이라도 완전히 다른 해시 값을 가져야 한다.

  • 혹여나 데이터베이스가 뚫려 비밀번호가 노출된다고 하더라도, 해싱된 비밀번호를 다른 사이트에 대입을 해봐도 뚫일일이 낮기 때문에 악용될 여지가 줄어든다.

  • 이해를 돕기위한 단순한 암호화의 예

Salt

  • 암호화해야 하는 값에 어떤 '별도의 값'을 추가하여 결과를 변형하는 것

  • 암호화만 해놓는다면 해시된 결과가 늘 동일 하기 때문에 해시된 값과 원래 값을 테이블(레인보우 테이블)로 만들어서 decoding 해버리는 문제가 발생 할 수 있다.

  • 원본값에 임의로 약속된 '별도의 문자열'을 추가하여 해시를 진행한다면 기존 해시값과 전혀 다른 해시값이 반환되어서 알고리즘이 만약 노출이 되더라도 원본값을 보호할 수 있는 확률이 더 올라간다.

  • 해싱만 했을경우 : (암호화 하려는 값) => (hash값)

  • salt를 같이 사용할 경우 : (암호화 하려는 값) + (Salt 값) => (hash) 값

Salt사용시 주의 할 점

  • Salt는 유저와 패스워드 별로 유일한 값을 가져야 한다.

  • 사용자 계정을 생성할 때와 비밀번호를 변경할 때 마다 새로운 임의의 Salt를 사용해서 해싱해야 한다.

  • Salt는 절대 재사용하지 말아야 한다.

  • Salt는 DB의 유저 테이블에 같이 저장되어야 한다.



*출처:https://blog.webf.zone/ultimate-guide-to-http-cookies-2aa3e083dbae

  • HTTP는 stateless (무상태성) 인데 어떻게 우리의 정보가 유지가 되는가? 바로 쿠키 덕분이다.

  • 쿠키란? 서버에서 클라이언트에 데이터를 저장하는 방법의 하나

  • 서버가 원한다면 서버는 클라이언트에서 쿠키를 이용하여 데이터를 가져올 수 있다.

  • 쿠키를 이용하는 것은 단순히 서버에서 클라이언트에 쿠키를 전송하는 것만 의미하지 않고 클라이언트에서 서버로 쿠키를 전송하는 것도 포함

  • 하지만 데이터를 저장한 이후 아무 때나 데이터를 가져올 수 없다. 데이터를 저장한 이후 특정 조건들이 만족하는 경우에만 다시 가져올 수 있다.

  • 그 특정 조건들에 대한 정보는 MDN SetCookie 에 잘나와있다.

  • 이러한 쿠키의 특성을 이용하여 서버는 클라이언트에 인증정보를 담은 쿠키를 전송하고, 클라이언트는 전달받은 쿠키를 요청과 같이 전송하여 Stateless 한 인터넷 연결을 Stateful 하게 유지할 수 있다.

  • 하지만 기본적으로는 쿠키는 오랜 시간 동안 유지될 수 있고, 자바스크립트를 이용해서 쿠키에 접근할 수 있기 때문에 쿠키에 민감한 정보를 담는 것은 위험하다.이런 인증정보를 탈취하여 서버에 요청을 보낸다면 서버는 누가 요청을 보낸 건지 상관하지 않고 인증된 유저의 요청으로 취급하기 때문에, 개인 유저 정보 같은 민감한 정보에 접근이 가능하다.


Session

  • 사용자가 인증에 성공한 상태를 세션이라한다.

  • 서버와 클라이언트에 각각 필요한 것은?

    • 서버는 사용자가 인증에 성공했음을 알고 있어야 한다
    • 클라이언트는 인증 성공을 증명할 수단(세션아이디)을 갖고 있어야 한다.
  • 웹사이트에서 로그인을 유지하기 위한 수단으로 쿠키를 사용하며. 쿠키에는 서버에서 발급한 세션 아이디를 저장

  • 사용자가 만일 정확한 아이디와 비밀번호를 입력했다면, 서버는 인증(Authentication)에 성공했다고 판단할 것이다. 그렇다면, 다음 번에 인증을 필요로 하는 작업을 요청할 경우, 또 로그인 과정을 거쳐야 할까? 서버는 아이디 및 비밀번호의 해시를 이미 알고 있기 때문에, "인증에 성공했음"을 서버가 알고 있다면, 매번 로그인을 할 필요가 없을 것이다.(인증에 따라 리소스의 접근 권한(Authorization) 이 달라진다는 뜻이다)

  • 서버가 Client에 유일하고 암호화된 ID를 부여한다.

  • 중요한 데이터는 서버에서 관리한다.

  • 로그아웃 기능은 어떻게 구현 할수 있을까?

    • 서버의 세션 정보를 삭제
    • 클라이언트의 쿠키를 갱신
  • 이러한 세션을 대신 관리해주는 모듈중에 express-session 이 있다.

  • Session의 단점

    • Session같은 경우 서버의 메모리에 세션 정보를 저장한다. 만약 서버에 이용자가 매우 많은경우라면 메모리의 일정부분을 항상 차지하고 있으므로, 가용 메모리의 양이 줄어들어서 서버의 성능이 안좋아지는 상황이 발생하기도 한다.
    • 기존쿠키를 완전히 대체한것이 아니기때문에 쿠키를 사용하고 있으므로 XSS공격으로 인해 세션 쿠키가 탈취 되는 경우 개인정보가 유출될수가 있으므로 로그아웃을 습관화 해야한다.

Token

  • 클라이언트가 토큰을 가지고 있다면 보통의 다른(돈을 내지 않은) 유저들과는 다르게 서버에서 제공하는 다양한, 더 프리미엄한 기능을 요청할수 있다.

  • 토큰은 유저 정보를 암호화한 상태로 담을 수 있고, 암호화 했기 때문에 클라이언트에 담을 수 있다.

  • 토큰기반 인증의 장점

    • 서버는 클라이언트에 대한 정보를 저장할 필요 없다 (토큰 해독이 되는지만 판단)
      * 클라이언트는 새로운 요청을 보낼때마다 토큰을 헤더에 포함시키면 된다.
    • 서버를 여러개 가지고 있는 서비스라면 더더욱 빛을 발휘한다 (같은 토큰으로 여러 서버에서 인증가능하므로)
    • 암호화 한 토큰을 사용하고, 암호화 키를 노출 할 필요가 없기 때문에 안전
    • 토큰을 확인하는 서버가 토큰을 만들어야 하는 법이 없다. (어디서든 생성이 가능하다)
    • 토큰 생성용 서버를 만들거나, 다른 회사에서 토큰관련 작업을 맡기는 것 등 다양한 활용이 가능
    • 토큰의 payload(내용물) 안에 어떤 정보에 접근 가능한지 정할 수 있다 (예로 서비스의 사진과 연락처 사용권한만 부여)

JWT(JSON Web Token)

  • Access Token

  • 보호된 정보들(유저의 이메일, 연락처, 사진 등)에 접근할 수 있는 권한부여에 사용합니다. 클라이언트가 처음 인증을 받게 될 때(로그인시), access, refresh token 두가지를 다 받지만, 실제로 권한을 얻는데 사용하는 토큰은 access token이다.

  • Refresh Token

    • 권한을 부여 받는데엔 access token만 가지고 있으면 된다. 하지만 access token을 만약 악의적인 유저가 얻어냈다면 어떻게 될까? 이 악의적인 유저는 자신이 00유저인것 마냥 서버에 여러가지 요청을 보낼 수 있게 된다(만약 돈과 관련된 문제라면 큰일이 날 수 있다).

    • 그렇기 때문에 access token에는 비교적 짧은 유효기간 을 주어 탈취 되더라도 오랫동안 사용할 수 없도록 하는것이 좋다. Access token의 유효기간이 만료된다면 refresh token을 사용하여 새로운 access token을 발급 받습니다. 이때, 유저는 다시 로그인 할 필요가 없다

    • 유저의 편의보다 정보를 지키는 것이 더 중요한 웹사이트들은 refresh token을 사용하지 않는 곳이 많다. 세상에 완벽한 보안은 없기 때문에 각 방법들의 장단점을 참고하며 필요에 맞게 사용하는 것이 좋다.

JWT의 구조

    • 이것이 어떤 종류의 토큰인지(지금의 경우엔 JWT), 어떤 알고리즘으로 sign(암호화) 할지가 적혀있습니다. JSON Web Token 이라는 이름에 걸맞게 JSON형태로 이런 형태를 볼수 있다.
      이 JSON 객체를 base64 방식으로 인코딩하면 JWT의 첫번째 부분이 완성이 된다.
      {
      "alg": "HS256",
      "typ": "JWT"
      }
  • Payload

    • Payload에는 정보가 담겨 있다. 어떤 정보에 접근 가능한지에 대한 권한을 담을 수도 있고, 사용자의 유저이름 등 필요한 데이터는 이곳에 담아 암호화 시킨다. 물론 암호화(헤더에서 정의한)가 될 정보지만, 민감한 정보는 되도록 담지 않는 것이 좋습니다. 첫번째 부분과 마찬가지로, 위 JSON 객체를 base64로 인코딩하면 JWT의 두번째 블럭이 완성된다.
      {
      "sub": "someInformation",
      "name": "phillip",
      "iat": 151623391
      } 
  • Signature

    • base64로 인코딩 된 첫번째, 그리고 두번째 부분이 완성 되었다면, 원하는 비밀 키(암호화에 추가할 salt)를 사용하여 암호화 한다. base64 인코딩을 한 값은 누구나 쉽게 디코딩할 수 있지만, 서버에서 사용하고 있는 비밀키(salt)를 보유한게 아니라면 해독해내는데 엄청난 시간과 노력이 들어갈 것이다. 예를들어, 만약 HMAC SHA256 알고리즘(암호화 방법중 하나)을 사용한다면 signature는 아래와 같은 방식으로 생성 될 것이다.
	HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);

Token 기반 인증 절차


*출처 코드스테이츠

  • 1) 클라이언트가 서버에 아이디/비밀번호를 담아 로그인 요청을 보낸다.
  • 2) 아이디/비밀번호가 일치하는지 확인하고, 클라이언트에게 보낼 암호화된 토큰을 생성한다.
  • 3) access/refresh 토큰을 모두 생성한다.
  • 4) 토큰에 담길 정보(payload)는 유저를 식별할 정보, 권한이 부여된 카테고리(사진, 연락처, 기타등등)이 될 수 있다.
  • 5) 두 종류의 토큰이 같은 정보를 담을 필요는 없다.
  • 6) 토큰을 클라이언트에게 보내주면, 클라이언트는 토큰을 저장한다.
  • 7) 저장하는 위치는 local storage, cookie, react의 state 등 다양하다.
  • 8) 클라이언트가 HTTP 헤더(authorization 헤더)에 토큰을 담아 보낸다.
  • 9) bearer authentication을 이용한다.
  • 10) 서버는 토큰을 해독하여 내가 발급해준 토큰이 맞다 라는 판단이 될 경우, 클라이언트의 요청을 처리한 후 응답을 보내준다.


OAuth 2.0

  • 인증을 위한 표준 프로토콜의 한 종류로 보안 된 리소스에 액세스하기 위해 클라이언트에게 권한을 제공(Authorization)하는 프로세스를 단순화하는 프로토콜 중 한 방법(소셜로그인)

  • OAuth를 왜쓸까?

    • 1) 유저 입장에서 생각해보자면, 우리는 웹 상에서 굉장히 많은 서비스들을 이용하고 있고 각각의 서비스들을 이용하기 위해서는 회원가입 절차가 필요한 경우가 많다. 그 서비스별로 ID와 Password를 다 기억하는 것은 매우 귀찮은 일이기때문에 OAuth 를 활용한다면 자주 사용하고 중요한 서비스들(예를 들어 google, github, facebook) 의 ID와 Password만 기억해 놓고 해당 서비스들을 통해서 소셜 로그인을 할 수 있게 되므로 매우 편리해진다.

    • 2) 보안상의 이점도 있다. 검증되지 않은 App에서 OAuth를 사용하여 로그인한다면, 유저의 민감한 정보가 App에 노출될 일이 없고 인증 권한에 대한 허가를 미리 유저에게 구해야 되기 때문에 더 안전하게 사용할 수 있게 된다.

  • OAuth에서 꼭 알아야할 용어

    • Resource Owner: 액세스 중인 리소스의 유저, 만약 나의 네이버 계정을 이용하여 어떠한 App에 로그인을 하게될 경우, 이 때 Resource Owner는 내가 될것이다.

    • Client: Resource owner를 대신하여 보호된 리소스에 액세스하는 응용프로그램

    • Resource server : client의 요청을 수락하고 응답할 수 있는 서버입니다.

    • Authorization server : Resource server가 액세스 토큰을 발급받는 서버입니다. 즉 클라이언트 및 리소스 소유자를 성공적으로 인증한 후 액세스 토큰을 발급하는 서버를 말합니다.

    • Authorization grant : 클라이언트가 액세스 토큰을 얻을 때 사용하는 자격 증명의 유형.

    • Authorization code : access token을 발급받기 전에 필요한 code 입니다. client ID로 이 code를 받아온 후, client secret과 code를 이용해 Access token 을 받아온다.

    • Access token : 보호된 리소스에 액세스하는 데 사용되는 credentials. Authorization code와 client secret을 이용해 받아온 이 Access token으로 이제 resource server에 접근을 할 수 있다.

    • Scope : scope는 토큰의 권한을 정의한다. 주어진 액세스 토큰을 사용하여 액세스할 수 있는 리소스의 범위.

*모든출처 코드스테이츠

profile
소통하는 개발자를 꿈꾸는

0개의 댓글