개요
최근 사내망에서의 SSL Certification 오류가 발생하거나, SSL 인증서를 갱신하는 작업을 하면서 SSL 인증서가 도대체 어떤 녀석이길래 '신뢰할 수 있는 사이트'라는 타이틀을 쥐어주는지, 암호화는 어떻게 가능한지에 대한 의구심이 들었다. SSL 인증서의 메커니즘을 알아보기 전 HTTPS와 암호화 방식에 대해 알아보고, 왜 굳이 CA 기관을 통해 SSL 인증서를 발급받아야하는지도 분석해보았다.
HTTPS 란?
HTTP는 Hypertext Transfer Protocol의 약자로 웹서비스에 데이터를 전송하는 통신 규약을 말한다.
HTTPS는 HTTP에 보안을 더한 프로토콜로 암호화 기반의 프로토콜인 SSL(Secure Socket Layer) 이 적용된 프로토콜을 말한다. 즉, HTTPS는 HTTP에 대한 암호화 기반의 데이터 통신규약을 말한다.
암호화? 우리가 아는 암호화??
맞다. 네트웤 구간에 떠다닐 우리의 요청, 응답 데이터들을 공격자가 알아볼 수 없는 형태로 암호화하는 것이다. 그럼 잠깐 암호화에 대해 알아보자.
대칭키?! 비대칭키?! 공개키?! 개인키??!! 😱
암호화는 데이터를 특정한 키 기준으로 연산하는 것을 말한다. 또 키를 이용해 복호화한다. 동일한 키로 암호화와 복호화를 둘다 할 수 있는 방식을키가 대칭된다 하여 대칭키 방식이라한다. 반대로 암호화하는 키와 복호화하는 키가 다른 방식을 비대칭키 방식이라 한다.
암호화 키와 복호화 키 중 어느 키가 더 중요할까?
당연히 복호화 키가 더 중요하다! 암호화 키가 유출되어 모든 사람들이 갖게된다고 하여도, 복호화 키가 없다면 그 누구도 암호화된 데이터를 볼 수 없기 때문이다.
대칭키는 암호화 키와 복호화 키가 똑같으니 모두 공개되어서는 안된다. 그럼 비대칭키는 어떨까? 공개되어도 되는 암호화 키와, 공개되어선 안되는 복호화키로 구성된다고 했다. 여기서 공개되어도 되는 키를 '공개키', 공개되어선 안되는 키를 '개인키'라고 한다. 그럼 HTTPS에 사용되는 암호화 방식은 대칭키일까? 비대칭키일까?
HTTPS에 사용되는 암호화 키 방식은 대칭키 인가요...? 🧐
대칭키 방식이라고 가정하고 생각해보자. 요청을 하는 클라이언트에서는 요청 데이터를 암호화해야한다. 즉, 키가 필요하다. 이 키는 서버로부터 전달받아야 한다. 그럼 최초 통신(핸드 쉐이크) 단계에서 서버가 클라이언트에게 키를 전달해야한다.
그런데 만약 이 과정에서 공격자가 요청을 가로챈다면, 그리고 이 대칭키를 탈취한다면 어떨까? 클라이언트와 서버간 대칭키 암호화를 통해 데이터를 주고 받더라도 공격자는 탈취한 키를 이용해 복호화를 할 것이고, 데이터를 감청할 수 있게 된다. 즉, 단순 비대칭키 방식을 사용하는 것은 네트웤 통신 관점에서는 매우 위험한 방식이다.
아! 그럼 비대칭키 방식이군요?! 😏
비대칭키를 사용하면 클라이언트로 전달되는 키, 즉 공개키가 공격자에게 탈취당해도 괜찮다. 복호화를 하지 못하기 때문이다. 하지만 여기서도 큰 문제가 있다. 바로 데이터를 응답할때 암호화가 불가능한 점이다. 예를들어 로그인에 성공 시 클라이언트에게 액세스 토큰을 전달하는 상황을 가정해보자. 액세스 토큰도 마찬가지로 암호화를 해야하는데, 현재 서버는 복호화를 할수있는 개인키밖에 없는 상황이다. 암호화를 위한 키가 없는 상황인 것이다.
서버도 자신이 사용할 공개키를 발급한 후 암호화하면 되잖아? 😏
그럼 서버의 응답 데이터는 암호화 되겠지만 클라이언트는 서버에서 준 데이터를 복호화 하지 못한다. 클라이언트는 복호화를 할 수 있는 개인키가 없기 때문이다
클라이언트에게 개인키를 주면 되잖아? 😏
그럼 대칭키를 사용했을 때의 문제 상황과 마찬가지로 공격자가 개인키를 가로챌 수 있는 상황에 처한다. 또한 비대칭키 방식은 대칭키보다 암/복호화 복잡도가 높고 속도도 수 천배 느리다. 즉, 속도와 시스템 자원 낭비 문제를 안게 된다.
키를 대체할 수 있는 값을 활용하면 되지 않아? 😏
클라이언트에서 키를 대체할 수 있는 랜덤 값을 생성하고, 이 값을 서버의 공개키로 암호화하는것이다. 그럼 서버에서 개인키로 이를 복호화하여 랜덤 값을 얻고, 서버와 클라이언트가 이 값을 대칭키로 삼아 암/복호화 하는것이다. 대칭키 방식이니 클라이언트, 서버 모두 암/복호화 할 수 있고, 키가 되는 랜덤 값을 전달할 때에는 서버의 공개키로 암호화해서 전달할 것이기 때문에 공격자에게 탈취되도 문제되지 않는다.
위에서 말한대로 위 구조에서는 공격자는 클라이언트에서 생성한 대칭키(랜덤 값)를 획득하지 못한다. 서버의 공개키로 암호화됐기에 서버의 개인키로만 복호화되기 때문이다.
이제 문제가 없어보일 수 있으나, 이 구조에서도 보안 이슈가 존재한다. 바로 서버가 클라이언트에게 전달하는 공개키를 공격자의 공개키로 바꿔치는 것이다. 이를 중간자 공격이라 한다.
중간자 공격 (Man-in-the-middel attack)
공격자가 공개키를 가로채어 변경하고 상대방에게 전달하여 신뢰를 잃게 만드는 방식.
서버가 공개키를 전달할 때를 캐치하여 서버의 공개키 대신 공격자의 공개키를 주면, 클라이언트는 공격자의 공개키로 생성한 대칭키를 암호화할것이다.
그 후 클라이언트가 전달한 암호화된 대칭키를 공격자가 가로채 공격자의 개인키로 복호화한다. 대칭키를 탈취한 것이다. 탈취한 대칭키를 서버가 사용하도록 만들어야하므로 4번과정에서 획득한 서버의 공개기로 대칭키를 암호화 한 후 서버로 전달한다. 서버는 아무것도 모르고 이를 복호화할것이고 대칭키로 사용할 것이다. 이제 데이터가 암호화되더라도 공격자가 복호화할 수 있게 되었다.
신뢰할 수 있는 기관을 끼자! 🏢
위처럼 중간에 공개키가 위변조되는 것을 막는 방법은 위변조를 못하도록 보안을 강화하면 된다. 보안을 위한 여러 프로세스들과 보안 장비를 붙이고, 취약점이 발생할때마다 수시로 업데이트해주며, 모니터링도 철저히 하는 것이다.
그렇다... 배보다 배꼽이 더 커진다.
서비스 운용 비용보다 보안을 위한 비용과 기술력이 훨씬 많이 필요할것이다. 그럼 서비스 운용자가 아닌, 믿을 수 있는, 매우 높은 보안성을 갖는 기관에게 서버의 공개키를 전달받으면 어떨까?
브라우저가 신뢰하는 기관, 신뢰할 수 있는 공개키를 제공하는 기관, 이 기관이 바로 CA이다.
CA (Certificate Authority)
인증기관이라 부르며, 다른 곳에서 사용하기 위한 디지털 인증서를 발급하는 곳.
CA도 털린적...이 있답니다 :)
실제로 2011년 DigiNotar 이라는 CA 가 해킹당해 Google과 Facebook 등 수많은 사이트가 피해를 입었다. 때문에 브라우저가 신뢰할 수 있는 CA 는 매우 깐깐한 조건으로 선별된다고 한다.
이제 본론으로 들어가 실제 CA와 서버, 클라이언트(브라우저)가 어떻게 상호작용하며 데이터를 암/복호화하는지 알아보자.
SSL 인증서 발급부터 통신까지의 과정을 알아보자! ✏️
1. SSL 인증서 발급 요청
SSL 프로토콜을 적용하고 싶다면 먼저 CA 에게 SSL 인증서 발급을 요청해야한다. 중요한 점은 서버의 공개키를 함께 전달하는 것이다.
2. 발급된 SSL 인증서 전달 및 SSL 프로토콜 적용
CA 로부터 SSL 인증서를 전달받으면 사용하는 웹 서비스(웹서버 또는 AWS ALB 등) 에 맞게 SSL 인증서를 적용시킨다.
3. Client Hello (Handshake-1)
클라이언트로부터 요청이 들어온다면 바로 요청/응답 데이터를 주고받지 않는다. 핸드쉐이크 과정을 거치는데, 첫번째 과정을 Client Hello 라고 하며, 클라이언트는 서버에게 '클라이언트 랜덤 값(편의를 위해 C Random이라 칭함)'과 클라이언트가 지원 가능한 암호화 메서드 리스트 등을 전달한다.
* 암호화 메서드 리스트들은 왜 전달하나요? 🤔
핸드쉐이크 과정에서 주고받는 데이터들에 대한 암호화 방식을 설정하기 위함이다. 핸드쉐이크 과정에서도 키 교환, 대칭키 암호화, PRF 알고리즘 적용과 같은 프로세스가 발생하는데, 이 때 서버와 클라이언트 모두 지원하는 암호화 방식을 사용해야하기 때문이다.
4. Server Hello (Handshake-1)
두번째 과정을 Server Hello 라 하며, '서버 랜덤 값(편의를 위해 S Random이라 칭함)'과 클라이언트에서 전달한 암호화 메서드 리스트 중 채택한 암호화 메서드, SSL 인증서를 전달한다.
5-6-7. SSL 인증서 확인 및 서버 공개키 획득
클라이언트는 SSL 인증서를 전달받으면 인증서를 발급한 CA 기관을 확인한다. 그리고 이 기관이 브라우저에 저장되어 있는지를 확인한다. 저장되어 있지 않다면 '신뢰할 수 없는 인증서'라는 경고가 발생할것이고, 저장되어 있다면 함께 저장된 해당 CA 의 공개키를 가져온다.
공개키를 통해 복호화(SSL 인증서 전자서명 검증)에 성공한다면 공인하는 CA로부터 발급된 위변조 없는 SSL 인증서라는 것을 알게 된다.
그리고 SSL 인증서에 포함되어있던 서버의 공개키를 획득한다.
브라우저에 저장된 CA는 브라우저가 신뢰하는 CA
위에서 말했듯이 CA 는 매우 깐깐한 기준으로 선별된다. 브라우저 내에 저장되어 관리되며, CA 리스트와 CA 공개키를 함께 관리한다.
만약 CA 리스트에 대한 업데이트가 발생한다면, 브라우저 업데이트를 통해 진행된다.
8. C + S 값 생성
C Random 값과 S Random 값을 조합한 C + S 값(제가 편의를 위해 칭한 이름입니다.) 을 생성한다.
9-10. Pre Master Secret 생성 및 전달
C + S 값을 서버에게 전달하기 위해 서버의 공개키로 암호화한다. 암호화된 C + S 값을 Pre Master Secret 이라한다.
이 값을 서버로 전달한다.
11. 서버측 C + S 값 획득
Pre Master Secret은 서버의 공개키로 암호화됐기에 서버는 자신의 개인키로 복호화하여 내장된 C + S 값을 획득한다.
12. 서버측 Master Secret 생성
획득한 C + S 값과 Pre Master Secret, PRF 알고리즘을 조합하여 Master Secret 을 생성한다.
PRF(Pesudo-Random Function)
특정 입력에 대해 항상 동일한 출력을 주는 랜덤 함수.
13. 대칭키 발급
Master Secret 을 기반으로 데이터를 암/복호화 하기 위한 대칭키를 발급한다. 여러 대칭키를 발급하는데, 실제 암/복호화에 사용하는 대표적인 키는 Session Key와 Mac Key이다.
Session Key
실 데이터를 암/복호화할때 사용하는 키.
Mac Key
데이터에 대한 HMAC 값을 구할 때 사용하는 키.
송신자 측에서 Mac Key를 사용해 데이터의 HMAC 값을 계산하여 암호화된 데이터와 함께 전달하면, 수신자측에서는 데이터를 전달받아 Session Key로 복호화한 후, Mac Key를 통해 데이터의 HMAC 값을 구한다. 송신자가 전달한 HMAC 값과 수신자가 연산한 HMAC 값이 동일하면 메시지가 변조되지 않았다는 것을 검증하게 되는 것이다.
HMAC
해시 함수와 공유 비밀 키를 사용하여 해시화하여 메시지의 무결성을 확인하는 메시지 인증 코드(MAC)의 한 종류.
14. 클라이언트측 Master Secret 생성
클라이언트에서도 12 번 단계에서 사용했던 것과 동일한 C+S 값과 Pre Master Secret, PRF 값을 조합하여 Master Secret을 생성한다. 여기서 중요한 점은 위 세개 값들을 서버로부터 다시 전달받는게 아닌, 자신이 이미 갖고 있던 값들을 사용한다는 것이다.
15. 대칭키 발급
13번 과정과 마찬가지로 Master Secret 을 기반으로하여 데이터를 암/복호화 하기 위한 대칭키를 발급한다. 서버와 마찬가지로 Session Key, Mac Key 등을 생성한다.
16. 대칭키 암호화 기반 통신 시작!
이 후 서버와 클라이언트간 통신 시 각자 갖고있는 Session Key와 Mac Key를 사용해 데이터를 암/복호화하여 통신한다!
서버와 클라이언트가 갖고있는 Session Key와 Mac Key 동일하므로 대칭키 암호화 기반으로 통신이 된다!
회고
이 글을 보는 독자들이 SSL 프로토콜의 내부 동작과 CA 의 SSL 인증서를 연결시켜 이해할 수 있길 바란다. 이 글에 적진 않았지만, 중간자 공격의 메커니즘을 이해한다면 사내망에서 SSL Certification 이슈가 발생하는 이유와 조치 방안도 이해할 수 있을 것이다!
'CS' 카테고리의 다른 글
[CS] 프로세스와 스레드 / 프로세스 구조 및 상태 / 싱글 스레드와 멀티 스레드 (0) | 2023.12.06 |
---|---|
[CS] 웹 프락시 / Proxy (0) | 2023.09.20 |
[CS] HTTP 메시지 (0) | 2023.08.30 |
[CS] URL이란? (0) | 2023.08.30 |
[CS] Web Cache / 웹 캐시란? (0) | 2023.08.23 |