HTTPS / Hashing / Cookie / Session

jungseo·2023년 7월 7일
0

Spring

목록 보기
20/23

HTTPS

  • HTTPS(Hyper Text Transfer Protocol Secure Socket layer)
    HTTP 요청을 SSL 혹은 TLS 알고리즘을 이용해 통신 과정 중 데이터를 암호화하여 전송하는 방법

1. 대칭 키와 비대칭 키

1) 대칭 키

  • 양쪽이 공통의 비밀 키를 공유하여 데이터 암호화 및 복호화
  • 클라이언트와 서버가 데이터를 주고받을 때 대칭키 방식 사용

2) 비대칭 키

  • 각각 공개 키와 비밀 키를 가지고 상대가 나의 공개 키로 암호화한 데이터를 개인이 가진 비밀 키로 복호화
  • 인증, 대칭 키를 주고받을 때 비대칭 키 방식 사용

2. 인증서

  • 서버의 신원을 보증
  • CA(Certificate Authority) : 인증서를 발급, 보증
  • 발급 기관, 공개키 정보 등 정보 포함

1) 인증 과정

  1. 서버가 클라이언트에게 CA의 비밀키로 암호화된 인증서를 전달
  2. 클라이언트는 OS 또는 브라우저에 미리 내장되어 있던 CA 리스트를 통해 브라우저에서 인증된 CA에서 발급받은 인증서인지 확인
  3. 확인 되었다면 CA기관의 공개 키로 서버 인증서를 복호화

    서버와 클라이언트 간의 CA를 통해 서버를 인증하는 과정과 데이터를 암호화하는 과정을 아우른 프로토콜을 TLS 또는 SSL이라고 함
    (*SSL과 TLS는 사실상 동일한 규약을 뜻하며 SSL이 표준화되며 바뀐 이름이 TLS)

2) HTTPS 사설 인증서 발급 및 서버 구현해보기

mkcert 프로그램을 이용해 로컬 환경에서 신뢰할 수 있는 PKCS12 형식의 인증서 생성

(1) Spring 프로젝트 생성 및 Spring Web 라이브러리 의존성 추가

(2) 설치

$ sudo apt install libnss3-tools
$ wget -O mkcert https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-amd64
$ chmod +x mkcert
$ sudo cp mkcert /usr/local/bin/
  • libnss3-tools:
    Network Security Services(NSS) 라이브러리에 관련된 도구와 유틸리티 모음

* MacOS의 경우

$ brew install mkcert

(3) 명령어를 통해 로컬을 인증된 발급기관으로 추가

$ mkcert -install

(4) PKCS12 인증서 생성

$ mkcert -pkcs12 localhost

(5) 생성된 localhost.p12 파일을 미리 생성해둔 프로젝트의 resource 디렉토리로 이동

(6) application.yml에 관련 설정을 추가

server:
  ssl:
    key-store: classpath:localhost.p12   # 인증서 경로
    key-store-type: PKCS12               # 인증서 형식
    key-store-password: changeit         # 인증서 비밀번호

(7) 애플리케이션 실행하여 확인

main] o.s.b.w.embedded.tomcat.TomcatWebServer  :
Tomcat initialized with port(s): 8080 (https)

3. Hashing

  • 복호화가 가능한 다른 암호화 방식들과 달리, 암호화만 가능
  • 해시 함수(Hash Function)를 사용하여 암호화를 진행
    • 항상 같은 길이의 문자열을 리턴
    • 서로 다른 문자열에 동일한 해시 함수를 사용하면 반드시 다른 결과값 리턴
    • 동일한 문자열에 동일한 해시 함수를 사용하면 항상 같은 결과값 리턴

1) 레인보우 테이블과 솔트(Salt)

  • 레인보우 테이블 : 항상 같은 결과값이 나온다는 특성을 이용해 해시 함수를 거치기 이전의 값을 알아낼 수 있도록 기록해 놓은 표
    • 유출이 되었을 때 해싱을 했더라도 해싱 이전의 값을 알아낼 수 있으므로 보안상 위협
  • 솔트 : 이전 값에 임의의 값을 더해 데이터가 유출되더라도 해싱 이전의 값을 알아내기 더욱 어렵게 만드는 방법
    • 'password' = 5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8
    • 'password' + 'salt' = 1D390E205862F15F174AEE7002E1CBE3B30F35C6
  • 솔트를 사용하게 되면 해싱 값이 유출되더라도, 솔트가 함께 유출된 것이 아니라면 암호화 이전의 값을 알아내는 것은 불가능

2) 복호화가 불가능한 암호화 방식 사용 이유

  • 해싱의 목적은 데이터 그 자체를 사용하는 것이 아니라, 동일한 값의 데이터를 사용하고 있는지 여부만 확인하는 것이 목적
  • 해싱한 값끼리 비교해서 일치하는지 확인
  • 정확한 값을 몰라도, 해싱한 값이 일치한다면 정확한 비밀번호를 입력했다는 뜻

  • 서버에서 클라이언트에 데이터를 저장하는 방법 중 하나
  • 서버가 원한다면 서버는 클라이언트에서 쿠키를 이용하여 데이터 읽기 가능
  • 쿠키를 이용하는 것은 단순히 서버에서 클라이언트에 쿠키를 전송하는 것뿐만 아니라 클라이언트에서 서버로 쿠키를 전송하는 것도 포함

쿠키 옵션

  • 데이터를 저장한 이후 특정 조건들이 만족하는 경우에만 다시 가져올 수 있음

1) Domain

  • "www.google.com" 과 같은 서버에 접속할 수 있는 이름
  • 쿠키 옵션에서 도메인은 포트 및 서브 도메인 정보, 세부 경로를 포함하지 않음
  • 쿠키 옵션에 도메인 정보가 존재한다면 클라이언트에서는 쿠키의 도메인 옵션과 서버의 도메인이 일치해야만 쿠키를 전송 가능

2) Path

  • 세부 경로는 서버가 라우팅 할 때 사용하는 경로
  • 요청 URL이 "http://www.localhost.com:3000/users/login" 일때
    Path, 세부 경로는 "/users/login"
  • 명시하지 않았을 시 기본값 "/"
  • 설정된 path를 전부 만족하는 경우 요청하는 Path가 추가로 더 존재하더라도 쿠키를 서버에 전송 가능
    • Path가 "/users" 로 설정 되어있고
      요청 경로가 "/users/login" 인 경우 쿠키 전송 가능

3) MaxAge/Expires

  • 쿠키의 유효기간을 설정
  • MaxAge : 몇 초 동안 쿠키가 유효한지 설정
  • Expires 얼마나 유효할지 date로 지정
  • 지정된 시간, 날짜를 초과하게 되면 쿠키는 자동으로 파괴
  • 옵션 여부에 따라 세션 쿠키와 영속성 쿠키로 구분
    • 세션 쿠키(Session Cookies)
      • MaxAge 또는 Expires 옵션이 없는 쿠키, 브라우저가 실행 중일 때 사용할 수 있는 임시 쿠키
      • 브라우저 종료 시 쿠키 삭제
    • 영속성 쿠키(Persistent Cookies)
      • 브라우저 종료와 상관없이 지정된 유효시간 만큼 사용 가능한 쿠키

4) Secure

  • 쿠키를 전송해야 할 때 사용하는 프로토콜에 따른 쿠키 전송 여부를 결정
  • true로 설정한 경우 'HTTPS' 프로토콜을 이용하여 통신하는 경우에만 쿠키를 전송 가능
  • 옵션이 없다면 프로토콜에 상관없이 쿠키 전송 가능

5) HttpOnly

  • 자바스크립트에서 브라우저의 쿠키에 접근 여부를 결정
  • true로 설정할 경우 자바스크립트에서 쿠키 접근이 불가능
  • 명시되지 않는 경우 기본 false
    • 자바스크립트에서 쿠키에 접근이 가능해 'XSS' 공격에 취약

6) SameSite

  • Cross-Site 요청을 받은 경우, 요청에서 사용한 메서드(GET, POST …)와 해당 옵션의 조합을 기준으로 서버의 쿠키 전송 여부를 결정
    • Cross-Site : eTLD+1이 다른 경우
      • TLD(Top Level Domain) : .com, .org 같은도메인의 가장 마지막 부분
      • eTLD+1 : TLD 바로 왼쪽 하위 레벨 도메인을 합한 것

        .io의 경우 바로 왼쪽 주소 하나를 더한 것이 TLD

    • Cross-Origin : 서버의 도메인, 프로토콜, 포트 중 하나라도 다른 경우
  • 사용 가능한 속성
    • Lax : Cross-Site 요청이라면 GET 메서드에 대해서만 쿠키 전송 가능

    • Strict : Cross-Site가 아닌 Same-Site인 경우에만 쿠키 전송 가능

    • None : 항상 쿠키 전송 가능

      • 쿠키 옵션 중 Secure 옵션 필요

쿠키를 이용한 상태 유지

  • 쿠키의 특성을 이용하여 서버는 클라이언트에 인증정보를 담은 쿠키를 전송하고, 클라이언트는 전달받은 쿠키를 요청과 함계 전송하여 인터넷 연결을 Stateful 하게 유지 가능
  • 쿠키는 오랜 시간 동안 유지될 수 있고, 자바스크립트를 이용해서 쿠키에 접근할 수 있기 때문에 쿠키에 민감한 정보를 담는 것은 위험함

5. Session

  • 세션 : 사용자가 인증에 성공한 상태

1) 흐름

  • 서버는 일종의 저장소에 세션을 저장
    in-memory, 세션 스토어(redis 등과 같은 트랜잭션이 빠른 DB)에 저장
  • 세션이 만들어질때 각 세션을 구분할 수 있는 세션 아이디도 만들어지며 보통 클라이언트에 세션 성공을 증명할 수단으로써 세션 아이디를 전달
  • 웹사이트에서 로그인을 유지하기 위한 수단으로 쿠키를 사용하며 쿠키에는 서버에서 발급한 세션 아이디를 저장
  • 쿠키를 통해 유효한 세션 아이디가 서버에 전달되고 세션 스토어에 해당 세션이 존재한다면 서버는 해당 요청에 접근 가능하다고 판단

2) 로그아웃

  • 세션 아이디가 담긴 쿠키는 클라이언트에 저장되어 있으며, 서버는 세션을 저장하고 있고 서버는 세션 아이디로만 인증 여부를 판단
  • 쿠키는 세션 아이디, 즉 인증 성공에 대해 증명을 하고 있으므로, 탈취될 때 서버는 해당 요청이 인증된 사용자의 요청이라고 판단
  • 로그아웃 시 서버는 세션 정보를 삭제, 클라이언트는 쿠키를 갱신
    • 서버가 클라이언트의 쿠키를 임의로 삭제는 불가능하며 set-cookie로 클라이언트에게 쿠키를 전송할 때 세션 아이디의 키 값을 무효한 값으로 갱신 가능

6. 보안 공격

1) SQL Injection

  • 데이터베이스에서 임의의 SQL 문을 실행할 수 있도록 명령어를 삽입하여 공격
  • 데이터베이스를 비정상적으로 조작
  • 사용자가 input form에 직접 무언가 작성하는 상황에서 발생

로그인시 예시 코드

SELECT * 
FROM users
WHERE auth='admin'
AND id='jungseo';

공격시 예시 코드

SELECT * 
FROM users
WHERE auth='admin'
AND id='' OR '1'='1';
  • WHERE 절에서 OR는 AND보다 연산 순위가 낮으므로 OR 절인 ‘1’ = ‘1’ (항상 참)이 가장 나중에 실행되어 결국 로그인에 성공

대응 방안

  • 입력(요청) 값 검증

    • 화이트리스트 방식으로 해당 키워드가 들어오면 다른 값으로 치환하여 SQL Injection에 대응
    • 화이트리스트란 기본 정책이 모두 차단인 상황에서 예외적으로 접근이 가능한 대상을 지정하는 방식 또는 그 지정된 대상
  • Prepared Statement 구문 사용

    • 사용자의 입력이 SQL 문으로부터 분리
    • 사용자의 입력값이 전달되기 전에 데이터베이스가 미리 컴파일하여 SQL을 바로 실행하지 않고 대기
    • 사용자의 입력값을 단순 텍스트로 인식
    • 입력값이 SQL 문이 아닌 단순 텍스트로 적용되며 공격에 실패
  • Error Message 노출 금지

    • Error Message를 통해 테이블 컬럼 등 정보를 얻을 수 있어 발생 SQL문과 에러 내용이 노출 되지 않도록 에러 핸들링 필요

2) CSRF(Cross-Site Request Forgery)

  • 사이트 간 요청 위조
  • 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청
  • 사이트간 요청 위조는 특정 웹사이트가 사용자의 웹 브라우저를 신용하는 상태를 노림
  • 사용자가 웹사이트에 로그인한 상태에서 사이트간 요청 위조 공격 코드가 삽입된 페이지를 열면, 공격 대상이 되는 웹사이트는 위조된 공격 명령이 믿을 수 있는 사용자로부터 발송된 것으로 판단하게 되어 공격에 노출

과정

  1. 이용자는 웹사이트에 로그인하여 정상적인 쿠키를 발급
  2. 공격자는 도착지를 변조한 이미지 태그를 가진 HTML 페이지 링크를 이메일이나 게시판 등의 경로를 통해 이용자에게 전달
  3. 이용자가 공격용 페이지를 열면, 브라우저는 이미지 파일을 받아오기 위해 공격용 URL 엶
  4. 이용자의 승인이나 인지 없이 출발지와 도착지가 등록됨으로써 공격이 완료

대응 방안

  • CSRF 토큰 사용
    • 웹 애플리케이션에서는 사용자의 세션과 관련된 CSRF 토큰을 생성하고 이를 웹 요청에 포함
    • 서버는 요청을 처리하기 전에 CSRF 토큰을 확인하여 유효성을 검증
  • SameSite 쿠키 속성 설정
    • 속성을 "Strict"로 설정하면, 같은 사이트에서만 쿠키가 전송되고 외부 도메인으로의 요청에서는 쿠키가 포함되지 않음

3) XSS(Cross-Site Scrption)

  • 사이트 간 스크립팅
  • 웹사이트 관리자가 아닌 이가 웹 페이지에 악성 스크립트를 삽입
  • 사용자의 정보(쿠키, 세션 등)를 탈취하거나, 자동으로 비정상적인 기능을 수행 가능
  • 주로 다른 웹사이트와 정보를 교환하는 식으로 작동

과정

  1. 웹 애플리케이션의 입력 폼, 코멘트 기능, 사용자 입력을 표시하는 부분 등을 통해 악성 스크립트를 삽입
  2. 악성 스크립트는 사용자가 웹 애플리케이션을 요청할 때 서버에서 클라이언트(웹 브라우저)로 전달
    스크립트는 주로 웹 페이지의 일부로서 실행될 수 있도록 HTML 태그나 이벤트 핸들러에 삽입
  3. 웹 브라우저는 악성 스크립트를 받고, 스크립트를 실행
  4. 스크립트는 웹 페이지의 콘텍스트 내에서 실행되어 사용자의 권한으로 웹 페이지를 조작하거나, 다른 웹 사이트로 사용자의 정보를 전송하는 등의 악의적인 행위를 수행 가능

대응 방안

  • 입력 검증
    • 사용자 입력 데이터를 신뢰할 수 있는 형식으로 변환 또는 제한
    • 입력 필드에서 예상되는 데이터 형식을 확인하고, 허용되지 않은 문자나 코드를 필터링
    • 입력 데이터를 검증하는 서버 측 및 클라이언트 측의 유효성 검사를 수행
  • 출력 이스케이프
    • 웹 애플리케이션이 사용자 입력을 표시할 때는, 특수 문자를 이스케이프하여 사용자 입력이 스크립트로 인식되지 않도록 처리
    • HTML, JavaScript, CSS 등의 웹 기술을 사용하는 출력에 대해 이스케이프 처리를 적용
    • 이스케이프 함수 또는 라이브러리를 사용하여 적절한 형태로 출력을 변환

0개의 댓글