본문 바로가기

인증,보안

[인증/보안] 기초1

 

 

 

  • 학습 내용

내가 처음에는 풀스택 그리고 그 후에는 백엔드로 프로젝트를 두번 경험하면서 가장 많이 참고한 레퍼런스 문서중 하나가 바로 이번 쳅터이다. 그러면서 인증/보안을 어떻게 효율적으로 안전하게 하는가가 백엔드 개발자에게 중요한 역량이라는 것을 느꼈다. 이번 쳅터에서 다룰 부분은 아주 기초적인 부분이다. 간단히 HTTPS와 Cookie, 세션, 토큰기반인증 방식을 다룬다. 이 부분부터 잘 공부해두어야 앞으로 다룰 수많은 인증/보안 기술을 잘 다룰 수 있을 것이다. 

 

  • HTTPS 프로토콜

HTTPS는 Hyper Text Transfer Protocol Secure Socket layer의 약자이다. HTTP over SSL(TLS), HTTP over Secure 라고 부르기도 한다. HTTPS는 HTTP 요청을 SSL 혹은 TLS 라는 알고리즘을 이용해 HTTP 통신을 하는 과정에서 내용을 암호화하여 데이터를 전송하는 방법이다. 

 여기서 SSL이란 Secure Sockets Layer로 암호화 기반 인터넷 보안 프로토콜이다. 원래 웹에서의 데이터는 가로채면 누구나 읽을 수 있는 일반 텍스트 형태로 전송 되었었는데, 이런 문제 때문에 인터넷 통신의 개인정보 보호, 인증, 데이터 무결성을 보장하지 못했다. 이를 위해 Netscape가 1995년 처음으로 이 SSL을 개발했다. TLS는 SSL의 업데이트 버전으로 SSL의 최종버전인 3.0과 TLS의 최초버전의 차이가 크지 않다. 이 이유는 Netscape가 업데이트에 참여하지 않아서 소유권 변경을 위해서 였다고 한다. 결과적으로 TLS는 SSL의 업데이트 버전으로 볼 수 있다.

 이증에서 HTTPS 프로토콜을 사용해야만 하는 이유는 HTTP보다 상대적으로 안전한 방법이고 데이터 제공자의 신원을 제공자가 제공해 준 데이터를 사용할 수 밖에 없기 때문이다. 클라이언트는 서버에 데이터 요청을 하고 이후 받은 데이터를 이용해서 화면을 렌더링하는 등의 작업을 해야 한다. 이로 인해 요청 및 응답을 중간에서 가로채는 중간자 공격에 취약하다는 문제가 발생했다. 여기서 중간자 공격이란 클라이언트와 서버 사이에서 공격자가 서로의 요청, 응답의 데이터를 탈취 및 변조하여 다시 전송하는 공격을 말한다. 이게 더욱 문제가 되는 이유는 중간자 공격의 경우 있었는지 확인하는 것조차 어렵기 때문이다. 이런 중간자 공격은 추가 데이터 또는 변조를 시조하기 때문에 데이터를 암호화하는 작업이 반드시 필요한 것이다. 

 그래서 HTTPS 프로토콜의 특징 중 하나가 암호화된 데이터를 주고 받는 것이다. 이로인해 중간에 인터넷 요청이 탈취되더라도 그 내용을 알아볼 수가 없다. 그래서 데이터를 암호화하여 전송하는 HTTPS 프로토콜을 사용한다면 비밀번호와 같은 중요한 데이터가 유출될 가능성이 HTTP 프로토콜보다 현저히 적어지게 된다. 또 다른 특징 중 하나는 브라우저가 응답과 함께 전달된 인증서 정보를 확인할 수 있다는 것이다. 브라우저는 인증서에서 해당 인증서를 발급한 CA 정보를 확인하고 인증된 CA가 발급한 인증서가 아니라면 화면에 경고창을 띄워 서버와 연결이 안전하지 않다는 화면을 보여준다. 여기서 CA란 인증 기관을 말하는데 웹 사이트, 이메일 주소, 회사 또는 개인과 같은 엔티티의 신원을 확인하고 전자 문서를 발행하여 암호화 키에 바인딩하는 회사 또는 조직을 말한다. 즉, CA는 인증서를 발급해주는 기관으로 Root Certificate라고 부른다. CA는 아무 기업이나 할 수 있는 것은 아니고 신뢰성이 엄격하게 공인된 기업들만 할 수 있다. TLS 통신을 하려면 이 CA를 통해서 인증서를 발급받아야 한다. CA는 자체적으로 공개키와 비밀키를 가지고 있고 CA의 비밀키는 절대 누설 되어서는 안된다. 

 돌아가서 이렇게 브라우저는 인증서의 도메인과 데이터를 제공한 제공자의 도메인을 비교할 수 있기 때문에 인증서의 도메인 정보와 데이터 제공자의 도메인 정보가 다른 중간자 공격을 감지하여 보안 위협으로부터 사용자 및 사용자의 데이터를 보호한다.

 

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

먼저 mkcert라는 프로그램을 이용해서 로컬 환경에서 신뢰할 수 있는 인증서를 만들 수 있다. mkcert 설치가 끝나면 이와 같은 명령어로 인증서를 만든다.

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

이렇게 작성하면 localhost, 127.0.0.1(IPv4), ::1(IPv6)에서 사용할 수 있는 인증서가 완성된다. cert.pem, key.pem 이라는 파일이 생성될 것이다.

 node.js에서 HTTPS 서버는 https 내장 모듈을 이용하여 만들 수 있다. 또 express.js를 이용해서도 https 서버를 만들 수도 있다.

1) Node.js의 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);

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

 

  • Hashing

단순히 응답과 요청을 주고 받으면 보안상의 이슈가 발생할 수 있다. 요청으로 보내는 정보의 부분만 알게 되어도 모든 정보를 확인할 수 있기 때문이다. 그래서 우리는 암호화 과정을 거쳐 보안상의 이슈를 해결할 수 있다. 암호화란 일련의 정보를 임의의 방식을 사용하여 다른 형태로 변환하여 해당 방식에 대한 정보를 소유한 사람을 제외하고 이해할 수 없도록 '알고리즘'을 이용해 정보를 관리하는 과정이다. 즉, 어떤 문자열에 '임의의 연산'을 적용하여 다른 문자열로 변환하는 것이다.

 여기에 몇가지 조건이 있는데 첫째로 모든 값에 해시 값을 계산하는데 오래걸리지 않아야 한다. 만약 한번 해시값을 만드는데 엄청 오래 걸리면 기능이 제대로 작동하기 어렵다. 둘째로 최대한 해시 값을 피해야 하며 모든 값은 고유한 해시 값을 가진다. 셋째로 아주 작은 단위의 변경이라도 완전히 다른 해시 값을 가져야 한다.

 

  • Salt

Salt란 암호화해야 하는 값에 어떤 '별도의 값'을 추가하여 결과를 변형하는 것을 말한다. 만약 암호화만 해놓는다면 해시된 결과가 늘 동일하다. 그래서 해시된 값과 원래 값을 테이블(레인보우 테이블)로 만들어서 decoding 해버릴 수도 있다. 그래서 원본값에 임의로 약속된 '별도의 문자열'을 추가하여 해시를 진행하면 기존 해시값과 전혀 다른 해시값이 반환되어 알고리즘이 노출되더라도 원본값을 보호할 수 있도록 한다. 주의할 점으로 Salt는 유저와 패스워드 별로 유일한 값을 가져야 하고, 사용자 계정을 생성할 때와 비밀번호를 변경할 때 마다 새로운 임의의 Salt를 사용해서 해싱해야 한다. 또 Salt의 경우 절대 재사용해선 안되며 DB의 유저 테이블에 같이 저장되야 한다.

'인증,보안' 카테고리의 다른 글

[Git] 브랜치 관리와 고급 기능  (0) 2022.06.28
[인증/보안] 기초2  (0) 2022.06.24
[Linux] 권한과 환경변수  (0) 2021.12.22
Git 기초1  (0) 2021.07.06
Linux 기초2 패키지(package)와 런타임(runtime)  (0) 2021.07.05