[인증/보안] 기초

Ethan KIM·2022년 8월 21일
0

Achievement Goals

목록 보기
5/7
post-thumbnail
  • 암호화와 hashing, salting 등의 개념을 설명하시오.
  • 암호화란?

    일련의 정보를 임의의 방식을 사용하여 다른 형태로 변환하여 해당 방식에 대한 정보를 소유한 사람을 제외하고 이해할 수 없도록 '알고리즘'을 이용해 정보를 관리하는 과정.

    Hashing?

    : 어떠한 문자열에 '임의의 연산'을 적용하여 다른 문자열로 변환하는것.
    일단, 해싱을 프로그램적으로 말하면, 원본 메시지를 해시함수에 넣어서, digest 결과값을 도출하는 행위로, digest만 서버나 데이터베이스에 저장이 된다.
    해시 알고리즘은 5가지 요구사항이 있다.

    One Way : 단방향. 원본데이터를 해시함수를 통해 해시값을 얻는 것이지 이 반대는 안됨. 레인보우 테이블같은 복호화 시트로 해시함수로 암호화된 데이터를 복호화 할 수 있기 때문에, Salt값을 원본 데이터에 넣어주어야한다.
    Deterministic : 동일한 해시함수를 사용할때, 늘 동일한 해시값이 나와야 한다.
    Fast Computation : 연산은 빨라야한다.
    The Avalanche Effect : 1비트라도 변화를 가했을때 해시값은 완전히 달라져야한다.
    Must withstand collision : A라는 데이터랑 B라는 데이터가 충돌할 경우가 나오면 안됨.

    아래 그림은 Hashing 과정을 나타내고 salt값을 추가하는 과정이 나온다.

    5번과 6번과정중,
    서버는 클라이언트에서 받은 이메일과 패스워드를 비교하는데, 3번에서 서버에게로 넘겨준 이메일은 4번 데이터베이스에서 서버로 넘겨준 값과 동일한데, 패스워드는 해싱으로 암호화된 digest이기 때문에, 다르다. 그래서 서버는 3번에서 넘겨준 password를 암호화하는 과정을 거치며 이때, 해싱에 미리 데이터베이스에 저장해 놓은 salt를 추가해 암호화 한 결과를 원래 있던 2번의 password와 비교한다. 비교해서 맞으면, db는 서버에 데이터를 전송해주고 서버는 클라이언트에게 데이터를 전송해준다.

  • HTTP와 HTTPS의 차이점을 설명하시오
  • HTTPS 프로토콜 (Hyper Text Transfer protocol Secure Socket layer).

    HTTP over SSL 이라고도 부름. 전통적인 SSL 은 TLS 의 등장으로 없어졌고, 현재는 "SSL", "SSL/TLS"라고 부름.

    그래서 이 SSL을 설명하면, 일반적으로 HTTP 는 프로토콜의 한 종류로서, 서버와 웹브라우저간의 통신 규약을 말하는데, 제 3자가 그 HTTP 프로토콜을 그냥 볼 수 있었음.
    그 결과, 제 3자가 프로토콜 메시지를 가로채서, 정보를 뺴돌릴 수 있었고, 중간자공격으로 요청과 응답을 가로챌 수 있었음. 이렇듯, 제 3자가 볼 수 있는 권한을 악용하는 사례가 많아지게됨.

    그래서, 이를 secure 하기 위한 프로토콜을 개발했는데, 그것이 HTTPS임. HTTP프로토콜에, authentication 과 encrypted links를 추가해서, 브라우저와 서버간의 통신을 암호화 하는 방향으로 발전한 결과가 HTTPS이다.

    SSL certificate

    해당 브라우저를 암호화된 키 쌍(public key, private key)으로 묶어준 디지털 문서이다. public key 는 웹브라우저에 위치하며, HTTPS 프로토콜을 이용해 서버와 암호화된 통신을 주고받는 역할을 하고, private Key는 주로 서버에 보관한 상태로, 웹브라우저가 public key로 암호화된 메시지를 전달하면, 서버는 그 메시지를 복호화 한 후, private key로 다시 암호화된 메시지를 전달하는 역할을 한다.

    아래 그림은, CA 에서 SSL 인증서를 발급하는 과정이다.
    과정.
    브라우저는 공인된 기관의 목록을 가지고 있고, CA의 공개키 또한 가지고 있다. CA에 인증서를 등록할때, CA 에선 공개키를 준다.
    1. 서버에 접속하면
    2. 서버는 브라우저에게 SSL 인증서를 제공한다.
    3. 브라우저는 인증서를 발급한 CA가 브라우저 CA리스트에 있는지 확인하고
    4. 만약 리스트에 있다면, CA의 공개키를 이용해(이미 존재함) SSL인증서를 복호화 함.

    Private key 는 서버에서 안전하게 보관되며, 웹 페이지 및 기타 문서에 디지털 서명하는데 사용됨.

    구체적 과정

    3가지 과정으로 나눔.
    Hand Shake : 클라이언트가 어떠한 요청을 보내면, 서로를 확인하고 서버는 클라이언트에게 공개키, 인증서 정보를 전달한다.

    Hand Shake 에대한 자세한 내용.

    비밀 키 생성 : 클라이언트는 전달바는 공개키를 이용해서 임의의 정보를 암호화해서 서버에 전달한다. 이에 서버는 클라이언트와 마찬가지로 임의의 정보를 암호화해서 클라이언트에 전달한다. 이렇게 서로 만들고 교환한 정보를 바탕으로 비밀키를 생성하게 된다.

    상호 키 검증 : 각자 생성한 키를 바탕으로, 클라이언트는 암호화된 메시지를 전달하고, 이에대한 응답으로 서버는 클라이언트가 보낸 암호화된 메시지를 복호화 한 후 다시 암호화 해서 응답을 보낸다.

    그럼 CA 와 SSL 의 관계는 무엇일까?
    결국 서버가가 인증서를 보내주고 key를 보내주어 브라우저가 암호화된 데이터를 서버에 전달 할 수 있게 만들어 주는것이 HTTPS의 역할인데, 그럼 그 인증서를 누가 인증할 건지에 대한 물음이 생긴다. 아무나 인증할 수 있다면, 그건 제대로된 인증 방식이 아닐것이기 때문에, 공공성이 있는 발급 기관이 필요하다. symantec, Comodo With, GoDaddy with 등이 CA인증 기업들이다. 현재는 로컬 환경에서 인증서를 생성하고 이를 이용한 서버를 만드는 과정만 하는데, open source tool을 이용해 보통 SSL을 만든다.
    pem : Privacy Enhanced Mail file. PEM, initially invented to make e-mail secure, is now an Internet security standard.
    key.pem : contains the private encryption key.
    cert.pem : contains certificate information.

    TO THE TOP

    node.js 를 이용한 서버 구현.

    const https = require('https');
    const fs = require('fs');
    
    //createServer 의 첫번째 인자로 key, cert 인증서가 객체로 추가.
    https
    	.createServer(
        {
        	key : fs.readFileSync(__dirname + '/key.pem', 'utf-8'),
            cert : fs.readFileSync(__dirname + '/cert.pem', 'utf-8')
        },
        function (req, res) {
        	res.write('Hello World new server!')
            res.end();
          }    
        )
        .listen(PORT)

    express.js 를 이용한 서버 구현

    const https = require('https');
    const fs = require('fs');
    const express = require('express');
    
    const app = express();
    
    https
    	.createServer(
        {
        	key : fs.readFileSync(__dirname + '/key.pem', 'utf-8'),
            cert : fs.readFileSync(__dirname + '/key.pem', 'utf-8'),
        },
        app.use('/' (req, res) => {
        	res.send('Hello World new server')
        })
      )
      .listen(PORT)
  • 권한 부여와 인증에 대해 설명하시오
  • 보안상, 인가 (권한 부여)와 인증에 대해 알아보자.

    권한을 부여한다.
    : Authorization = 사용자에게 특정 리소스나 기능에 엑세스할 수 있는 권한을 부여하는 프로세스. 대표적으로 서버에서 특정 파일을 다운로드할 수 있는 권한을 부여하거나, 개별 사용자에게 관리자 권한으로 어플리케이션에 엑세스할 수 있는 권한을 부여하는 경우. 항상 인증 이후에 진행 되어야함.


    인증을 한다.
    : Authentication = 사용자의 신원을 검증하는 행위로서 보안 프로세스에서 첫 번째 단계.
    비밀번호. : 가장 많이 사용되는 인증 요소.
    일회용핀. : 단일 세션이나 트랜잭션에 한하여 액세스 허용.
    인증앱. : 엑세스를 허용하는 외부기관을 통해 보안코드 생성. Google Athentication
    생체인식. : 사용자가 시스템에 엑세스하기 위해 지문이나 망막스캔을 제출.

  • 쿠키의 작동 원리를 설명하시오
  • : 서버에서 클라이언트에 데이터를 저장하는 방법의 하나.

    왜 생겼음?

    HTTP의 특성인 stateless 와 Connectionless 문제로 인해서, 서버의 부담이 심해서.
    이게 무슨말이냐면, 쿠키를 사용하면, 아래의 단점을 커버 할 수 있다는 말임.

    서버가 클라이언트(브라우저)에 쿠키를 저장한다. 주로 쿠키 스토리지가 따로 있어, 그곳에 저장함. 이러면, 클라리언트가 동일한 서버에 요펑을 보낼 때 이 쿠키와 같이 보내게 되서, 서버는 이 쿠키를 읽고, 저번에 요청한 사용자라는 것을 알게됨.

    실생활에서 쿠키의 예시는,

    쿠팡을 들 수 있음. 장바구니에 물건을 담아두고, 결제를 하기전 앱을 종료했지만, 장바구니엔 물건이 그대로 상태로 남아 있음. 쿠키를 전달해서 장바구니 물건들이 그대로 상태로 남아있게 되는것.
    다크모드도 쿠키임. 브라우저상에 다크모드 쿠키를 저장해 놓고, 클라이언트가 브라우저를 킬때마다 이 쿠키를 서버에 같이 보내주어서, 서버가 다크모드가 된 홈페이지를 렌더링해줌.
    자바스크립트에서도 쿠키를 저장할 수 있는데, SSL 공격에 취약. httpOnly 옵션이 false일때만 사용이 가능.

    쿠키옵션.

    1.Domain: 쿠키 옵션에서 도메인은 포트 및 서브 도메인정보, 세부 경로를 포함시키지 않음. 2번의 Path 에서 설정해줘야함. 쿠키옵션에서 도메인 정보가 존재하면, 클라이언트에서는 쿠키의 도메인 옵션과 서버의 도메인이 일치해야만 쿠키를 전송할 수 있다.
    2.Path: 서버가 라우팅할 때 사용하는 경로. 명시하지 않으면 기본으로 / 로 설정. 설정된 path를 전부 만족하는 경우 요청하는 Path가 추가로 더 존재하더라고 쿠키를 서버에 전송가능. 즉, 앞에 path만 맞으면 전송 가능함. 하지만 세부경로만 맞으면 쿠키 전송 불가.
    3.Maxage or Expires: 쿠키의 유효기간을 정하는 옵션. MaxAge는 앞으로 쿠키가 몇 초 동안 유효한지 설정. Expries는 Date를 지정하여 이때 까지 유효한 쿠키설정. *클라이언트 기준. 지정된 시간 경과하면 알아서 쿠키 파괴. 두 옵션이 지정되지 않을 겨웅엔 브라우저의 탭을 닫으면 쿠키 삭제.
    4.Secure: true로 설정된 경우 HTTPS 프로토콜을 이용하여 통신하는 경우에만 쿠키 전송 가능.
    5.HttpOnly: 자바스크립트에서 브라우저의 쿠키에 접근 여부를 결정. true일 경우 자바스크립트에선 쿠키에 접근 불가. 명시되지 않을 경우 default 는 false라서, 자바스크립트에서 쿠키에 접근이 가능하므로 XSS 공격에 취약함.(malicious script를 보내는 공격.)
    6.SameSite: Cross-Origin 요청을 받은 경우 요청에서 사용한 메소드와 해당 옵션의 조합으로 쿠키 전송 여부를 결정.
    Lax : Cross-Origin 요청이면 'GET' method에 대해서만 쿠키전송 가능.
    Strict : Cross-Origin이 아닌 same-site인 경우에만 쿠키 전송 가능.
    None : 항상 쿠키를 보내줄 수 있음. Secure 옵션 필요.
    Same-site : 요청을 보낸 Origin 과 서버의 도메인이 같은 경우를 말함.

    이러한 옵션들을 지정한 다음 서버에서 클라이언트로 쿠키를 처음 전송하게 되면 헤더에 Set-Cookie라는 프로퍼티에 쿠키를 담아 쿠키를 전송하게 된다.

  • 세션 및 쿠키/토큰/Oauth를 통해 인증 구현을 해보시오
  • Session.

    쿠키는 클라이언트 쿠키 스토리지에 저장.
    세션은 서버에 세션_id 형태로 저장.
    세션은 여러가지 개념이 있음. 아래가 세션의 다양한 개념임.

    근데 여기서 의미하는 session은 session token의 형태임.
    Session Token = 서버에서 클라이언트로 전송하는것. 클라이언트는 해당 토큰을 Cookie 스토리지 또는 메모리에 저장

    서버가 세션을 클라리언트에 보내주고 클라이언트는 해당 세션을 저장하는 과정.

    1. 먼저 클라이언트가 post 로 아이디를 등록한다(서버에 요청한다.).
    2. 서버는 그 아이디를 세션 저장소에 저장한다. 여기서 세션 저장소라 함은 DB가 될 수도있고 서버의 in memory가 될 수도 있음. 그리고 세션토큰을 클라이언트에게 돌려준다.이때, 서버는 쿠키에 Session_id를 포함해서 전송한다.
    3. 클라이언트는 서버에서 쿠키와 함께 보내준 세션토큰을 쿠키 스토리지나 메모리에 저장한다.
    4. 이후, 클라이언트가 원하는 데이터가 있으면, 이 세션토큰과 함께 쿠키를 보내서, 유효한 세션아이디가 서버에 전달되면, 원하는 데이터를 Get 요청으로 얻어 낼 수 있다.
    5. 로그아웃을 하면, 서버의 세션 정보를 삭제하고, 클라이언트의 쿠키를 무효한 값으로 갱신 해주어야 한다. 왜냐하면 쿠키 스토리지에 아직 Session_id가 담긴 쿠키가 남아있기 때문에.

    세션의 한계.

    1. 세션은 기본적으로 서버 측 메모리에 생성되므로, 메모리의 크기가 유한하기 때문에 꼭 필요한 경우만 생성해서 사용해야한다.
    2. 세션은 여전히 쿠키를 사용하고 있기 때문에, 쿠키가 탈취 당할 수 있고 변하지 않는 값이기 때문에, 오랜 시간이 지나도 해당 값으로 악의적인 요청을 할 수 있음. XSS 공격에 취약.
    3. 확장성 + 보안적 한계가 있어서, 최소한의 보안을 위해서라면 꼭 세션이 종료되면 세션 destroy를 통해 세션을 없애야한다.

    express-session

    Token-based Authentication

    세션 기반 인증은 서버(혹은 DB)에 유저 정보를 담는 인증 방식이었으나, 서버에서 클라이언트의 요청마다 데이터베이스를 살펴보는것이 불편하고, 부담이 됨.
    그래서 토큰기반 인증이 나오게 되고, 그중 JWT에 대해 알아보자.

    토큰?

    클라이언트에서 인증 정보를 보관하는 방법으로 토큰 기반 인증이 생겨남. 근데 쿠키를 클라이언트에 저장하는것이 위험해서 세션을 서버에 저장하는 방법으로 보안을 강화했는데, 토큰은 괜찮음? ㅇㅇ 괜찮음 유저 정보를 암호화 하거든. 쿠키와 세션은 쿠키와 같이 오는 유저 정보를 암호화 할 순 없음. 하지만, JWT는 그 유저정보를 암호화해서 정보를 저장함. 하지만 이것도 탈취할 수 있음.

    JWT(JSON WEB TOKEN)

    2가지 종류가 있다.
    1. AccessToken. : 보호된 정보들 (유저정보)에 접근할 수 있는 권한부여에 사용함. 클라이언트가 처음 인증받을때 (로그인시) Access Token 과 Refresh Token 두가지를 받지만, 실제로 권한을 얻는 데 사용하는 토큰은 Access Token이다. Access 토큰은 짧은 유효기간을 주어야함.
    2. RefreshToken. : Access Token의 유효기간이 만료된다면 Refresh Token 을 사용하여 새로운 Access Token 을 발급 받는다. 이때, 유저는 다시 로그인 할 필요가 없음.

    JWT 구조


    . 으로 3부분이 나누어져서 존재함.
    1. Header. : 어떤 종류의 토큰인지, 어쩐 알고리즘으로 sign할지가 적혀있음.

    {
      "alg": "HS256"
      "typ": "JWT"
    }

    2.Payload. : 정보가 담겨있음. 어떤 정보에 접근 가능한지에 대한 권한을 담을 수도 있고, 사용자의 유저 이름 등 필요한 데이터는 이곳에 담아 암호화를 시킨다. 민감한 정보는 담지 않는게 좋음.

    {
      "sub": "someInformation"
      "name": "phillip"
      "iat": 151392811
    }

    3.Signature. : base64로 인코딩된 첫번쨰, 그리고 두번째 부분이 완성되면, 원하는 비밀키를 사용하여 암호화 한다.(salt역할) 서버에서 사용하는 비밀키를 보유한게 아니면, 해독해 내는데 엄청난 시간이 걸림.
    예를들어, HMAC SHA256알고리즘을 사용하면,
    HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret)

    절차

    1. 클라이언트가 서버에 아이디/비밀번호를 담아 로그인 요청을 보낸다.
    2. 아이디/비밀번호가 일치하는지 확인하고, 클라이언트에게 보낼 암호화된 토큰을 생성.
      access/refresh 토큰은 이때 생성함.
      두 토큰이 같은 정보를 담을 필요는 없고. payload엔 유저를 식별할 정보, 권한이 부여된 카테고리를 담을 수 있음.
    3. 토큰을 클라이언트에게 보내주면, 클라이언트는 토큰을 저장한다.
      저장 위치는 다양함. local storage or cookie, react의 state
    4. 클라이언트가 HTTP 헤더에 토큰을 담아 보냄
      Bearer authentication 을 이용.
    5. 서버는 토큰을 해독하게 되는데 이때 서버에 저장된 salt값을 추가해서 복호화를함.
  • 클라이언트, 서버, 데이터베이스의 전체 동작을 설명하시오
  • 회원가입 및 로그인 등의 유저 인증에 대해 구현하고, 이해하시오
  • 서비스의 보안과 관련된 방법을 알아보고 원리 및 장점 및 단점을 설명하시오.
  • profile
    좋아하는것만 함

    0개의 댓글