[인증/보안] HTTPS, Hashing, Cookie, CSRF

윤태영 | Taeyoung Yoon·2022년 5월 23일
0

TIL (Today I Learned)

목록 보기
43/53
post-thumbnail

HTTPS

Hyper Text Transfer Protocol Secure Socket layer의 약자로
HTTP over SSL(TLS),
HTTP over Secure 이라고 부르기도 한다.

HTTP 요청을 SSL 혹은 TLS 라는 알고리즘을 이용해 HTTP통신 과정의 내용을 암호화하여 데이터를 전송하는 방법이다.

  • 기밀성
    메시지를 가로챌 수 없음
  • 무결성
    메시지가 조작되지 않음

인증서 (Certificate)

HTTPS 프로토콜의 특징 중 하나로 브라우저가 응답과 함께 전달된 인증서 정보를 확인할 수 있다.

데이터 제공자 신원 보장

데이터를 제공한 서버가 정말로 데이터를 보낸 서버인지 인증 확인한다

도메인 종속

인증서에는 서버의 도메인 관련 정보가 있어서 데이터 제공자 인증을 쉽게 해준다.

요청을 받으면 서버는 인증서와 함께 응답을 전송한다.
응답을 받은 클라이언트는 인증서에 작성된 도메인과 응답객체에 작성된 도메인을 비교한다.

두 도메인이 같다면 서버가 확실하다는 것을 인지한다.

중간자 공격으로 도메인이 변경되면 서버가 확실하다는 것을 보장할 수 없게 된다.
그러면 클라이언트에서 서버 제공자가 아니라 다른 제공자라는 것을 알 수 있게 된다.

암호화

  • 대칭키 암호화
    키 1개로 암호,복호
  • 비대칭키 암호화
    개인키로 암호, 공개키로 복호 = 전자서명
    공개키로 개인키로 = 암호화

비대칭 키 암호화

서로 다른 키 한쌍으로 암호화와 복호화를 할 수 있으며
어떤 키로 암호화를 할 경우 다른키로 복호화를 해야한다.

HTTPS 프로토콜을 사용하는 서버는 한쌍의 키중에서 하나는 숨겨두고 다른 하나는 클라이언트에게 공개해서 데이터를 안전하게 통신한다.

공개키 방식은 모든 통신에 사용하기에는 연산이 복잡한 알고리즘이기 때문에 통신의 초기에 비밀키를 만들기 위해 사용한다.

HTTPS 성립 이후 이 비밀키를 바탕으로 데이터 송수신에 필요한 동일키 암호화 및 복호화를 진행한다

A한테만 쿠키값을 줬으니 쿠기값을 정확하게 아는 애가 A이다
로그인 다시 안해도 A이다.

헤더의 set-cookie라는 공간에 cookie를 실어보낸다.
서버는 stateless이므로 매번 쿠키를 보낸다.

쿠키는 실제 파일에 저장되므로 취약하다.

session은 서버가 로그인값을 갖고있으며
로그아웃할때 서버에서 session을 파괴해야한다.

사설 인증서 발급 HTTPS 서버구현

CA (Certificate Authority)

인증서를 발급해주는 기관
각각의 브러우저는 신뢰하는 CA정보를 가지고 있다.
자격을 유지하거나 박탈할 수 있다.

브라우저는 인증서에서 해당 인증서를 발급한 CA정보를 확인하고
인증된 CA가 발급한 인증서가 아니라면
안전하지 않다는 경고창을 화면에 띄운다.

설치

mkcert라는 프로그램을 이용해서 로컬 환경(내 컴퓨터)에서 신뢰할 수 있는 인증서를 만들 수 있다.

macOS

brew install mkcert

firefox를 사용할 경우 추가 설치
brew install nss

인증서 생성

mkcert -install

로컬을 인증된 발급기관으로 추가한다.


mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1

localhost로 대표되는 로컬 환경에 대한 인증서를 만든다.
해당 디렉토리에 cert.pem, key.pem 이라는 파일이 생성된다.


HTTPS 서버 작성

Node.js https 모듈 이용

인증서 파일들을 HTTPS 서버에 적용해 주는 작업

const https = require('https');
const fs = require('fs');

https
  .createServer(
    {
      key: fs.readFileSync(__dirname + '/key.pem', 'utf-8'),
      cert: fs.readFileSync(__dirname + '/cert.pem', 'utf-8'),
    },
    function (req, res) {
      res.write('Congrats! You made https server now :)');
      res.end();
    }
  )
  .listen(3001);

express.js 이용

callback 함수를 Express 미들웨어로 교체하면 된다.

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 + '/cert.pem', 'utf-8'),
    },
    app.use('/', (req, res) => {
      res.send('Congrats! You made https server now :)');
    })
  )
  .listen(3001);

Hashing

들어가기 전에


사용자 정보를 서버에 저장하는 단순한 구조로 만들면
누구라도 이메일 정보를 알고있으면 모든 정보에 접근할 수 있는 보안상 이슈가 발생한다.

해커가 DB에 접근해 password을 알아낼 수 있으므로 데이터베이스에 password를 암호화하여 저장해야 한다.

알고리즘을 통해 암호화를 한다.

Hashing이란

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

  • 모든 값에 대해 해시 값을 계산하는데 오래 걸리지 않아야 한다.
  • 최대한 해시 값을 피해야 하며, 모든 값은 고유한 해시 값을 가진다.
  • 아주 작은 단위의 변경이라도 완전히 다른 해시 값을 가져야 한다.

salt

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

  • 암호화만 해놓는다면 해시된 결과가 늘 동일해지므로 해시된 값과 원래값을 테이블로 만들어 디코딩 해버릴 수 있다.
  • 원본값에 임의로 약속된 별도의 문자열을 추가하여 해시를 진행하면 기본 해시값과 전혀 다른 해시값이 반환되어 알고리즘이 노출되더라도 원본값을 보호할 수 있다.

기존

암호화 하려는 값 => 해시값

salt 사용

암호화 하려는 값 + salt용 값 => 해시값

salt 사용 시 주의점

  • salt는 유저와 패스워드 별로 유일한 값을 가져야 한다.
  • 사용자 계정을 생성할 때와 비밀번호를 변경할 때 마다 새로운 임의의 salt를 사용하여 해싱해야 한다.
  • salt는 절대 재사용하지 않아야 한다.
  • slat는 DB의 유저테이블에 같이 저장되어야 한다.

HTTP는 stateless(무상태성)이므로 쿠키를 이용해 사용자의 정보를 유지시켜줄 수 있다.
쿠키는 서버가 클라이언트에 데이터를 저장하는 방법의 하나이며 서버는 클라이언트에서 쿠키를 이용해 데이터를 가져올 수 있다.

하지만 기본적으로는 쿠키는 오랜 시간 동안 유지될 수 있고, 자바스크립트를 이용해서 쿠키에 접근할 수 있기 때문에 쿠키에 민감한 정보를 담는 것은 위험하다.

서버는 쿠키를 이용해 데이터를 불러와 사용할 수 있지만 데이터를 저장한 이후 아무 때나 데이터를 가져올 수 없다.
데이터를 저장한 이후 특정 조건들이 만족하는 경우에만 다시 가져올 수 있으며 이런 조건들은 쿠키 옵션으로 표현할 수 있다.

Domain

쿠키 옵션에서 도메인은 포트 및 서브 도메인 정보, 세부 경로를 포함하지 않는다.
클라이언트에서는 쿠키의 도메인 옵션과 서버의 도메인이 일치해야만 쿠키를 전송한다.

Path

서버가 라우팅할 때 사용하는 경로이다.
Path 옵션의 특징은 설정된 path를 전부 만족하는 경우 요청하는 Path가 추가로 더 존재하더라도 쿠키를 서버에 전송할 수 있다.

MaxAge or Expires

쿠키가 유효한 기간을 정하는 옵션이다.

  • MaxAge: 앞으로 몇 초 동안 쿠키가 유효한지 설정하는 옵션
  • Expires: 쿠키가 언제까지 유효한지 클라이언트 시간 기준 날짜를 지정하는 옵션

두 옵션이 모두 지정되지 않는 경우에는 브라우저의 탭을 닫아야만 쿠키가 제거된다.

Secure

프로토콜에 따른 쿠키 전송 여부를 결정한다.
해당 옵션이 true로 설정된 경우, 'HTTPS' 프로토콜을 이용하여 통신하는 경우에만 쿠키를 전송할 수 있다.

HttpOnly

자바스크립트에서 브라우저의 쿠키에 접근 여부를 결정한다.
해당 옵션이 true로 설정된 경우, 자바스크립트에서는 쿠키에 접근이 불가하다.
기본값은 false이며 이 경우 XSS공격에 취약하다.

SameSite

Cross-Origin 요청을 받은 경우 요청에서 사용한 메소드와 해당 옵션의 조합으로 서버의 쿠키 전송 여부를 결정하게 된다.

  • Lax :Cross-Origin 요청이면 'GET' 메소드에 대해서만 쿠키를 전송
  • Strict : Cross-Origin이 아닌 same-site 인 경우에만 쿠키를 전송
  • None: Secure옵션이 true일 경우 항상 쿠키를 전송

CSRF (Cross Site Request Forgery)

다른 오리진에서 유저가 보내는 요청을 조작 하는 것
ex)메시지에 첨부된 링크를 누르면 은행계좌의 돈이 빠져나감
해커가 직접 데이터를 접근할 수 없다.
ex)다른 오리진이기 때문에 응답에 직접 전근할 수 없음

Web application Security

개잘자들이 웹사이트, 모바일 어플, 웹 API 등을 만들 때에 해커들의 공격을 막기 위해서 Security는 필수 사항이다.

여러가지 공격들

  • SQL injection
  • XSS
  • CSRF

작동조건

쿠키를 사용한 로그인
유저가 로그인 했을 때 쿠키로 어떤 유저인지 알 수 있어야 함
예측할 수 있는 request/parameter를 가지고 있어야 함
request에 해커가 예측할 수 없는 정보가 담겨있으면 안됨

GET 요청으로 공격

사용자가 은행 웹사이트에 로그인을 하면 현재 session이 살아있고 로그인 정보가 쿠키안에 담겨져 있다.

<a href="https://bank/transfer?account_number=사용자계좌번호&amount=1000000W">
<a href="https://bank/transfer?account_number=공격자계좌번호&amount=1000000W">
공격자는 사용자가 작성한 계좌를 공격자계좌로 바꿔 요청 API를 준비한다.

링크를 클릭하세요 등의 메시지
공격자는 사용자가 사용자의 브라우저환경에서 공격자가 바꾼 GET요청을 보내게 만든다.

은행에서는 사용자가 로그인이 되어 있는 상태이고 그 사용자가 공격자계좌로 이체 요청을 보냈으므로 요청을 받아들인다.

POST 요청으로 공격

메타인지

🎯 오늘의 학습목표

  • HTTP와 HTTPS의 차이점을 이해할 수 있다.
  • 암호화와 hashing, salting 등의 개념을 이해할 수 있다.
  • 권한 부여(Authorization)와 인증(Authentication)에 대해 이해할 수 있다.
  • 쿠키의 작동 원리를 이해할 수 있다.

😎 학습할 내용 중에 알고 있는 것

HTTP

✏️ 오늘 새롭게 학습한 것

HTTPS, hashing, salting, cookie

🧷 오늘 학습한 내용 중 아직 이해되지 않은 부분

session 인증 방식 스프린트에서 클라이언트 영역의 코드작성이 미흡했다.

💡 이해되지 않은 내용을 보완하기 위해 무엇을 할까

session 스프린트 클라이언트를 다시 작성해본다.

0개의 댓글