선행 지식
CA (Certificate Authority)
: 인증서를 발급해주는 기업. SSL을 적용하기 위해 인증서가 필요한데, 인증서는 서비스의 정보, 서버 측의 공개키가 포함되어 있다.Handshake
: 통신 시작 시 클라이언트와 서버가 서로 신분을 확인하고, 필요한 정보를 주고받는 과정이다.- 대칭키, 비대칭키
HTTP 통신의 허점
우리가 기본적인 HTTP 프로토콜을 사용하는 웹서버(웹앱서버)를 띄워 로그인 API를 호출할 때, 아이디와 비밀번호를 서버로 보내면 입력한 텍스트는 누구든 알아볼 수 있는 평문으로 보내진다. 만약 누군가가 중간에서 이 정보를 탈취한다면 유저의 아이디와 비밀번호를 고스란히 알게 된다.
이러한 치명적인 보안적 허점을 해결하기 위해 인증서를 발급받고, 그 인증서를 기반으로 데이터를 인코딩해서 주고받는다. 이는 다른 누군가가 탈취하더라도 알아볼 수 없게 된다. 이 방법이 HTTPS
이다.
HTTPS란?
기존의 HTTP
는 TCP/IP
위의 애플리케이션 계층에서 사용되는 프로토콜이다. HTTPS
는 TCP/IP
계층 위에 SSL(TLS)
를 얹어 보안을 강화한 프로토콜 방식이다. 이를 통해 모든 HTTP 요청과 응답은 암호화된다.
만일 HTTPS
에서 대칭키를 사용할 경우 최초 한 번은 서버에서 클라이언트로 암호화에 사용할 키를 전달해야 하는데, 그 과정에서 암호화 키를 누군가 탈취한다면 누군가 암호화/복호화 가능한 키를 가지고 있기 때문에 암호화 통신을 하더라도 무용지물이 된다. (누군가 데이터를 복호화해서 정보를 다 해석할 수 있다.)
비대칭키를 사용할 경우 서버는 개인키/공개키를 둘 다 가지고 있고, 클라이언트에서 요청할 때 공개키만 준다. 이 공개키로 암호화한 데이터는 서버만 가지고 있는 '개인키'로만 복호화 가능하다. 그리하여 누군가 공개키를 탈취하고 데이터를 탈취하더라도 데이터를 복호화할 수 없게 된다. 하지만 처리 속도가 느려 성능에 문제가 생길 수 있다.
HTTPS
는 각각의 단점을 보완하기 위해 대칭키/비대칭키 방식을 혼합하여 사용한다. 최초 한 번 서버가 공개키/개인키를 가지고 있다가 클라이언트가 요청 시 공개키를 전달해준다. 클라이언트는 실제 데이터 전달에 사용할 대칭키를 공개키로 암호화하여 서버에 전달한다. 서버는 개인키를 사용해 대칭키를 복호화하고 그 후 대칭키로 실제 통신이 이루어진다. (이러한 방식을 사용하면 최초 핸드셰이킹 시에만 비대칭키 알고리즘을 사용하니 속도 저하의 문제도 해결되고, 대칭키 전달 시 대칭키를 비대칭키로 암호화하니 중간에 대칭키가 탈취되어도 누군가가 복호화할 수 없는(사용할 수 없는) 키가 되기에 보안적으로도 안전하다.)
이러한 대칭키는 HTTPS 통신 과정에서 세션키
로 불린다.
SSL 및 TLS
앞서 SSL
은 TCP/IP
계층의 위에서 동작하는 프로토콜, 인터넷을 통해 전송되는 데이터의 인증, 암호화, 복호화를 위한 프로토콜(계층)이라는 것을 간접적으로 알아봤다.
사실 SSL
은 TLS(Transport Layer Security)
라는 또 다른 프로토콜의 이전 버전이다. 그래서 TLS 암호화 및 TLS Handshake라고 부르는 게 바람직하지만, SSL이 더 잘 알려져있기에 그냥 SSL로 부르거나 TLS/SSL로 명명하기도 한다. 필자는 SSL이라고 명시하겠다.
TCP 3-way Handshake 과정
- 클라이언트는 서버에게 접속 요청을 위한 메시지(SYN)를 보낸다. 18503218같이 의미없는 난수를 같이 보낸다. (SEQ넘버)
- 서버는 클라이언트에게 SYN 요청을 받은 다음, 연결을 수락(ACK)한다. 서버에서도 85291953같이 난수를 보낸다. (ACK넘버)
- 클라이언트는 서버에 접속 수락 확인(SYN)을 보낸다. 이때 서버측에서 넘겨준 ACK넘버에 1을 더해 같이 보내준다. TCP 연결이 성립, 서버는 ESTABLISHED 상태가 된다.
SSL Handshake 과정
HTTPS
는 TCP 위에 SSL 계층이 있는 구조이므로 TCP 3-way Handshake 과정을 거친 후 SSL Handshake 과정에 들어간다.
SSL Handshake 과정은 아래와 같은 순서로 이루어진다.
1. Client : Client Hello
클라이언트가 먼저 서버에 접속해 말을 건넨다. 브라우저는 TCP 3-way Handshake를 통해 해당 웹서버가 HTTPS를 사용한다는 것을 알게 되며, 아래 정보를 이 단계에서 서버로 보낸다.
- 브라우저가 사용하는 SSL 버전 정보
- 브라우저가 지원하는 암호화 방식 모음 (
cipher suite
) - 브라우저가 순간적으로 생성한 임의의 난수 (숫자)
- 만약 이전에 SSL Handshake가 완료돤 상태라면, 그때 생성된
Session ID
- 기타 확장 정보 (Extension)
참고) cipher suite
란 보안의 목표 달성을 위해 사용하는 방식들을 패키지의 형태로 묶어놓은 것을 의미한다. (암호화 알고리즘, 전달 대상 인증, 메시지 무결성 확인 알고리즘 등)
2. Server : Server Hello
서버 또한 클라이언트의 인사에 응답하면서, 아래 정보를 클라이언트에 제공한다.
- 브라우저의 암호화 방식 중, 서버가 선택한 암호화 방식 (
cipher suite
) - 서버의 공개키가 포함된 SSL 인증서 (인증서는 CA의 비밀키로 암호화되어 발급된 상태)
- 서버가 순간적으로 생성한 임의의 난수 (숫자)
- 클라이언트 인증서 요청 (선택사항)
3. Client : 서버의 SSL 인증서 신뢰성 확인
브라우저에는 검증된 CA들의 정보 및 CA가 만든 공개키가 이미 설치되어 있다. 서버가 보낸 SSL 인증서를 내장된 CA 공개키로 복호화하여 정말 CA가 만든 것인지 확인한다.
만약 위조된 인증서이거나 등록된 CA가 아니라면 이 과정에서 발각되며, 브라우저에 경고를 보낸다.
4. Client : 클라이언트의 난수, 서버의 난수를 활용해 premaster secret 생성
클라이언트는 자신이 이전에 생성했던 난수와 서버가 보내준 난수를 사용해 premaster secret이라는 데이터를 만들고, SSL 인증서에 딸려온 웹서버의 공개키로 이 premaster secret를 암호화한다. 또한 이를 서버로 전송한다.
5. Server : premaster secret 복호화
서버는 클라이언트에게서 받은 premaster secret을 자신의 개인키(비밀키)를 활용하여 복호화한다. 이를 사용해 세션 키를 생성한다.
앞에 말했던 HTTPS에서 쓰이는 대칭키가 이 세션키인 것이다. 이 세션키를 사용해 브라우저-서버 사이에 주고받는 데이터를 암호화/복호화한다.
6. SSL Handshake 종료
이로써 SSL Handshake는 정상적으로 완료되었고, 이제 웹상에서 데이터를 주고받을 때 세션 키를 이용해 암호화/복호화할 수 있다.
HTTPS 통신이 완료되는 시점에 서로에게 공유된 세션 키를 폐기한다. 만약 세션이 여전히 유지되고 있다면 브라우저는 세션 ID만 서버에게 알려주면 된다. (1에서 언급)
참고) SSL 핸드셰이크 과정은 키 교환 알고리즘 종류마다 다르지만, 원리는 같다. 위는 RSA 키 교환 알고리즘을 따랐다.
HTTPS는 100% 안전한가
HTTPS는 웹에서 보안을 적용하기 위한 가장 기본 단계이기에, 이것 덕분에 보안이 완벽해진다고 할 수 없다.
웹 서버가 해커의 공격에 의해 루트 권한을 탈취당했다면, 웹 서버의 모든 기밀 데이터를 열람할 수 있는 권한이 넘어갈 수 있다.
또한 HTTPS는 전달 구간에 대한 보안 기술인데, 전달 구간 중간에 해커가 중간자 공격(Man in the middle attack)을 수행할 수 있는 취약점이 있다면 전달 내용이 고스란히 노출될 수 있다.