SSL/TLS 에 대해서

Photo by Halil Ibrahim Cetinkaya on Unsplash

들어가며

이 블로그 포스트는 실제로 SSL/TLS 코드를 보기 전에 작성하였다. 그런데 SSL/TLS 구현체를 살펴보았을 때 정말 많은 기능들이 여기에 언급된 것들보다 많다는 것을 깨닫고 이 글을 어디까지 정리해야하는가에 대해서 고민이 생겼다.

SSL/TLS 확장 기능들인 여러 extentions들에 대해서는 나중에 필요할 때마다 정리해보기로 마음먹고 이 글의 범위를 SSL/TLS 기본 원리에 대해서 집중하기로 했다.

이 글은 어떤 것을 다루나요?

이번 포스팅에서는 SSL/TLS 프로토콜이 어떤 방식으로 동작하며 왜 이런 프로토콜이 등장하였는지 그 배경에 대해서 살펴본다.

그런데 SSL/TLS 프로토콜을 이해하기 위해서는 몇 가지 배경 지식이 필요하다. 그래서 글 앞 부분에서는 SSL/TLS를 이해하기 위한 배경 지식에 대해서 살펴보고 그 이후에 SSL/TLS 프로토콜이 왜 등장하였는지 어떻게 동작하는지에 대해서 살펴본다.

글 마무리에는 실제로 SSL/TLS 그리고 이것을 사용하여 만들어진 HTTPS 프로토콜이 코드 레벨에서 어떻게 동작하는지 테스트해볼 수 있는 github 링크도 첨부하였다.

배경 지식

Message Authentication Code (MAC)

메세지의 무결성을 보장할 수 있는 방법 중에는 Message Authentication Code (MAC) 방식이 존재하는데 이것이 어떻게 무결성을 보장하게해주는지 살펴보자. 다음과 같은 시나리오로 상대방에게 메세지를 보낸다고 생각해보자.

  1. Alice가 메세지 m을 해싱하여 해시값 H(m)을 만든다.
  2. 그리고 Alice는 H(m)를 메세지 m에 이어서 (m, H(m)) 값을 만들고 이것을 Bob에게 보낸다.
  3. Bob은 (m, h)을 전달받고 m을 이용해 H(m)을 계산한 다음 이것이 h와 일치한다면 Bob은 안전하게 데이터를 받았다고 생각한다.

위와 같은 방식에는 허점이 있는데 바로 중간자 Trudy가 Alice의 메세지를 가로챈다음 가짜 메세지 m’로 원본 데이터를 바꾸고 m’을 이용하여 H(m’)을 계산한 뒤 Bob에게 (m’, H(m’)) 을 보낸다면 Bob이 보았을 때는 아무 문제가 없다고 생각할 것이다.

이런 문제점을 해결하기 위해서 Alice와 Bob은 서로만 아는 공유된 시크릿인 s가 필요하다. s는 임의의 데이터이고 이것을 인증키라고 부른다. 이 인증키를 이용하여 무결성을 다음과 같이 보장할 수 있다.

  1. Alice는 메세지 ms와 이어붙여 m+s를 만든다. 그리고 m+s의 해시값인 H(m+s)를 만든다. H(m+s) 값을 message authentication code (MAC)이라고 부른다.
  2. Alice는 MAC에 m을 다시 이어붙여 (m, H(m+s))를 만들고 이것을 Bob에게 전송한다.
  3. Bob은 인터넷으로부터 (m, h)을 전달받고 이제는 Alice와 Bob만이 알고있는 s가 있기 때문에 이것과 m을 이용해 H(m+s)을 계산한 다음 이것이 h와 일치한다면 Bob은 안전하게 데이터를 받았다고 생각한다.

위의 방식을 살펴보면 알겠지만 MAC의 장점 중 하나는 비용이 큰 암호화 알고리즘이 필요하지 않다는 것이다. MAC 방식 중 이제 표준이 된 방식은 바로 HMAC 방식이다. HMAC에서는 MD5나 SHA-1을 이용해 ms를 해싱한다.

그런데 MAC 방식이 동작하기 위해서는 한 가지 전제가 필요하다. 송수신에 참여하는 시스템이 인증키를 공유해야한다는 것이다. 이 때 한 시스템이 다른 시스템에 어떻게 자신의 인증키를 상대방에게 건네줄지에 대한 고려가 필요하다.

MAC을 생성하는 방법
Fig. 1. the way to generate MAC
MAC 검증하는 방법
Fig. 2. the way to validate MAC

Digital Signature

일반적으로 문서에 서명을 한다고하면 해당 문서를 읽어보았고 동의한다는 뜻으로 서명을 하게 된다. 디지털 세계에서는 서명은 해당 데이터가 자신의 소유 혹은 자신이 보낸 데이터라는 것을 증명하기 위해서 사용된다. 이를 우리는 전자 서명이라고 부른다.

전자 서명을 한 데이터는 다음과 같은 특성을 지녀야 한다.

  • 전자 서명이 된 데이터는 소유주가 자신이 서명을 했다는 것을 증명할 수 있어야 한다.
  • 오직 소유주만이 전자 서명을 한 데이터를 만들 수 있어야 한다.

다음의 예시를 살펴보면서 전자 서명에 대해서 더욱 자세히 알아보자. Bob이 m이라는 데이터에 전자 서명을 하려고 한다. 이 데이터는 어떤 파일이 될 수도 있고 메세지가 될 수도 있다. 그리고 해당 데이터를 Bob은 다른 누군가에게 전송할 것이다. Bob은 전자 서명을 하기 위해서 자신의 비공개키, KB를 이용하여 KB(m)을 만든다. ‘만든다’라는 과정이 추상적으로 보일 수 있다. 이 과정은 단순히 비공개키를 이용하여 원본 데이터를 암호화를 하는 과정이고 이것은 따져보면 수학적 연산에 지나지 않는다. 우리가 잘 알고 있는 RSA 알고리즘을 암호화를 하는데 사용할 수 있고 우리는 이러한 과정을 서명을 한다고 한다. 다시 한번 짚고 넘어가면 이렇게 알 수 없는 값으로 원본 데이터를 변형시키는 것은 원본 데이터를 알 수 없게 만드는 것에 목적이 있는 것이 아니라 해당 데이터를 Bob이 보냈다는 것을 증명하고자하기 위함이다.

전자 서명을 하는 방식
Fig. 3. the way to create digital signature for the message

데이터 수신자 Alice는 정말 자신이 받은 데이터가 Bob으로부터 온 데이터인지 확인하고 싶다. 이런 경우 Alice는 Bob의 공개키, KB+를 가지고 전자 서명된 데이터 KB(m)에 복호화를 시도해볼 수 있다. 복호화 결과가 원본 데이터와 동일하다면 이 데이터는 Bob이 보냈다는 것을 확신할 수 있게 된다. 그 근거는 다음과 같다.

  • Alice가 받은 데이터는 비공개키 KB를 통해서 암호화가된 데이터이다. 왜냐하면 공개키 KB+를 이용하여 복호화를 하였을 때 원본 데이터가 나왔기 때문이다.
  • 비밀키 KB를 가진 사람은 Bob뿐이다. (이 가정은 Bob이 자신의 비밀키를 다른 누구에게도 탈취당하지 않았다는 가정이 있다.)

그리고 위 과정 중 하나 짚고 넘어갈 중요한 점이 있다. 전자 서명과 함께 원본 데이터를 전송할 때 원본 데이터인 m이 다른 데이터 m’ 으로 바뀌었다면 전사 서명을 확인하는 과정에서 데이터가 변조되었는지를 확인할 수 있다. 그렇기 때문에 우리는 전자 서명을 통해서 데이터 무결성을 보장한다고 볼 수 있다.

그런데 위의 과정 중에 데이터에 전자 서명을 하는 과정 그리고 해독하는 과정에 사용되는 암호화, 복호화 과정이 컴퓨팅 리소스적으로 비싸다는 단점이 있다. 그렇기 때문에 전송하고자하는 데이터 전체에 서명을 하는 것은 너무 비효율적이다. 이러한 문제를 개선할 수 있는 방식 중 하나가 전자 서명에 해시 함수를 사용하는 것이다. 해시 함수는 간단히 말하면 어떤 함수인데 입력값으로 어떤 메세지 m을 받는다. 그리고 결과 값으로는 고정된 길이의 어떤 값 H(m)을 얻을 수 있다.

이제 Bob은 전체 메세지에 대해 서명을 하는 것이 아니라 전체 메세지를 해싱한 결과 값에 대해서 서명을 하게 된다. KB-(H(m)). 이전 방식과 비교해보면 H(m)은 m보다 길이가 훨씬 짧기 때문에 컴퓨팅 리소스가 적게 든다.

해시값을 통해서 전자 서명하는 과정을 이제 Bob이 Alice에게 메세지를 보내는 과정을 놓고 생각해보자. Bob은 먼저 원본 데이터를 해시 함수에 넣어 해시값을 만든 뒤 그 값에 자신의 비밀키를 이용해 서명을 한다. 그리고 Alice에게 원본 데이터와 전자 서명 값을 보낸다.

두 값을 받은 Alice는 Bob의 공개키를 이용하여 전자 서명에 들어있는 해시값을 얻어내고, 또한 원본 메세지를 해시값으로 만들어 두 값을 비교한다. 만약 두 값이 일치한다면 Bob이 메세지를 보냈다는 것을 알 수 있을뿐만 아니라 데이터가 중간에 변조되지 않았다는 것을 알 수 있다.

Public Key Certification

전자 서명을 활용한 것이 바로 public key certification이다. public key certification은 공개키가 누구의 소유인지를 증명해주는 것을 말한다. Public key certificationd은 보안을 위한 네트워크 프로토콜에 다양하게 응용된다. 대표적인 예가 IPsec과 아래에서 살펴볼 SSL이 있다.

Public key certification이 등장한 배경을 이해하기 위해서 다음과 같은 상황을 상상해보자.

Alice가 피자 배송 서비스를 운영하고 웹사이트에서 주문을 받는다. Bob은 Alice가 운영하는 피자 가게에서 평문으로 Bob의 집 주소와 주문할 피자 종류를 Alice에게 보낸다. 또한 Bob은 이 주문을 넣은 사람이 자신임을 증명할 전자 서명을 같이 보내게된다. 주문을 받은 Alice는 Bob의 공개키를 이용하여 전자 서명이 Bob의 것이 맞다는 것을 확인한다.

그런데 여기서도 문제가 존재한다. Alice는 사실 자신이 받은 전자 서명이 누구의 것인지 알지 못한다. 악의적인 의도를 가진 Trudy가 Bob의 배송지와 피자 종류를 메세지에 적고 Trudy의 전자 서명과 공개키를 전달하면 어떻게 될까? Alice는 전자 서명이 ‘누군가’의 것이 맞다는 것만 알 뿐 메세지를 보낸 사람이 누구인지는 알지 못한다.

위와 같은 문제를 해결하기 위해서는 전자 서명과 같이 전송된 공개키가 누구의 것인지를 알 방법이 필요하다. 이와 같이 공개키와 해당 공개키가 누구의 소유인지를 확인시켜주는 일을 Certification Authority (CA)가 하게 된다. CA는 다음과 같은 역할을 가진다:

  • CA는 자신에게 등록한 주체가 누구인지 적법한 절차를 통해 알아내는 책임을 가진다.
  • CA 해당 주체에게 인증서(certificate)를 발급해주고 해당 인증서와 주체가 등록한 공개키를 바인딩시킨다. 인증서에는 공개키 정보와 해당 주체가 누구인지를 알려주는 정보가 들어가있다. CA가 발급한 인증서는 CA가 전자 서명을 한 형태로 제공된다.
CA가 인증서를 검증하는 방법
Fig. 4. How CA generate entity’s certificate

CA에게 인증서를 발급받기 위해서는 인증서 서명 요청 (Certificate Signing Request, CSR)을 작성해서 보내야한다. CSR에는 일반적으로 다음과 같은 정보가 포함된다.

  • 인증서에 포함할 공개키
  • 인증서가 적용되는 도메인
  • 인증서가 대표하는 주체에 대한 정보

현재는 X.509가 인증서의 표준으로 사용되고 있다. 그리고 X.509 인증서를 받기 위해서는 CA에게 CSR을 작성해서 보내야 발급받을 수 있다. 아래는 인증서의 여러 필드 중 중요한 필드에 대해 정리하였다. RFC5280 를 살펴보면 더욱 자세한 스펙에 대해서 알 수 있다.

  • Version: X.509 버전
  • Serial number: CA가 발급한 인증서 고유 번호
  • Signature: CA가 이 인증서를 발급할 때 사용한 암호화 알고리즘
  • Issuer name: 이 인증서를 발급한 CA의 고유 이름
  • Validity period: 이 인증서가 유효한 기간
  • Subject: 이 인증서가 증명하고 있는 주체의 이름
  • Subject public key: 이 인증서가 증명하고 있는 주체의 공개키

이제 CA가 발급해준 인증서가 이전에 설명한 피자 배송 서비스에 어떻게 적용될 수 있는지 살펴보자.

Bob은 피자 주문할 때 CA가 서명한 인증서를 그의 주문과 함께 보내게 된다. Alice는 CA의 공개키를 이용하여 인증서가 CA에 의해 서명된 것을 확인하고 인증서로부터 Bob의 공개키를 추출하고 Bob의 전자 서명이 맞는지를 확인한다. 이제 이전과 달리 자신이 전달받은 공개키가 누구의 것인지를 확실히 알 수 있다.

SSL의 필요성

SSL은 왜 등장하였을까? 그 필요성에 대해 이해하기 위해 다음과 같은 상황을 상상해보자.

Bob이 Alice가 운영하는 웹서비스에서 어떤 제품을 주문하기 위해 카드 정보와 주문 목록을 Alice에게 전송하였다. 그런데 다음과 같은 사항들이 지켜지지 않으면 문제가 생길 수 있다.

  • 만약 Bob의 주문 정보가 기밀성이 지켜지지 않은채 채 Alice의 서버로 전송이 된다면 중간자가 Bob의 주문 정보를 가로채서 Bob 카드 정보를 확인할 수 있게 된다.
  • 만약 Bob과 Alice 사이에서 데이터 무결성이 보장되지 않는다면 중간자가 Bob의 주문을 바꿔도 Alice나 시스템이 알아차릴 수 없다.
  • 서버 인증 방식이 제공되지 않는다면 Bob은 자신이 이용하고 있는 웹서비스가 Alice가 운영하고 있는 서비스인지 보장할 수 없다.

SSL은 위와 같은 문제들을 해결해준다. TCP 통신 과정에서 데이터 기밀성을 지켜주고 데이터 무결성을 보장하며 서버/클라이언트를 인증할 수 있는 수단을 제공해준다. SSL은 TCP 위에서 동작하고 TCP에서 제공해주는 소켓 API와 유사한 API를 제공해주기 때문에 TCP 위에서 동작하는 어플리케이션 레이어를 위해 사용될 수도 있다. 가장 대표적인 것이 HTTPS 프로토콜이다.

SSL/TLS 레이어 정리
Fig. 5. TCP API layer vs TCP with SSL API layer

SSL의 동작 원리

기본적으로 SSL은 세 가지 단계를 거쳐서 진행된다: handshake, key derivation 그리고 data transfer. 그리고 각각의 단계를 클라이언트(Bob)와 서버 (Alice)가 통신 과정을 통해서 살펴보자. 서버는 자신의 공개키와 비밀키를 가지고 있고 공개키는 CA에 의해 해당 공개키가 Alice의 것임을 보증하고 있다.

Handshake

먼저 high-level에서 handshake가 어떻게 일어나는지 정리하면 첫 번째로 클라이언트가 서버에게 TCP 연결을 맺는다. 두 번째로 클라이언트는 자신이 연결을 맺은 대상이 정말로 Alice가 맞는지를 확인한다. 그리고 이 과정에서 클라이언트는 서버에게 pre-master secret key를 보낸다. 서버와 클라이언트는 이를 이용하여 둘만이 공유하는 대칭키 master key를 만드는데 이를 이용하여 둘간이 전송하는 데이터를 암호화하는데 사용한다.

정리하면 상대가 정말 내가 통신하고자하는 시스템이 맞는지를 먼저 검증을하고 둘만이 아는 키를 공유하는 것이 handshake의 핵심이다. 그 외의 과정들은 악의적인 누군가가 데이터를 변조하지 않았는지 안전한 키를 안전하게 생성할 수 있는지 등에 대한 것들을 위한 것이다.

이제 조금 더 구체적인 handshake 과정을 정리하면 다음과 같다.

  1. 클라이언트는 자신이 사용할 수 있는 암호화 알고리즘 리스트를 nonce와 함께 서버로 보낸다.
  2. 서버는 리스트 중에서 대칭키 알고리즘, 공개키 알고리즘, MAC 알고리즘을 선택한다 (CipherSuite). 또한 SSL/TLS Version 중 가장 적합한 버전을 선택한다. 그리고 자신이 선택한 암호화 알고리즘. 버전, CA의 인증서 그리고 서버측에서 생성한 nonce를 함께 클라이언트에게 전송한다…
  3. 클라이언트는 인증서를 통해 서버를 검증하고 서버측 공개키를 얻는다. 그리고 pre-master secret (PMS)을 생성하는데 서버측 공개키를 통해 암호화한 뒤 서버로 보낸다.
  4. 서버와 클라이언트는 각각 key derivation function (KDF)를 통해 PMS와 nonce로부터 MS를 생성하게 된다. 그리고 MS는 4개의 키로 분리된다. 또한 만약 선택된 대칭키 알고리즘이 CBC라면 두 개의 initialization vectors (IVs)는 MS로부터 얻어진다.
  5. 클라이언트는 세션 암호화 키를 이용하여 모든 handshake 메세지의 MAC을 전송한다.
  6. 서버는 세션 암호화 키를 이용하여 모든 handshake 메세지의 MAC을 전송한다.

위의 설명이 아래 다이어그램에 정리되어있다. 클라이언트와 서버간에 TCP 연결이 맺어지면 클라이언트는 서버에게 hello message를 보낸다. 서버는 클라이언트 hello message를 받으면 서버는 자신의 공개키와 CA의 인증서를 클라이언트에게 보내서 자신이 Alice임을 증명한다. 클라이언트는 서버 인증이 이루어진 후에 pre-master secret (PMS)을 생성하고 이를 다시 서버의 공개키로 암호화하여 encrypted pre-master secret (EPMS)를 만들어서 서버에게 전송한다. 서버는 자신의 비밀키를 이용하여 클라이언트가 보낸 pre-master key 얻어내고 이를 이용하여 master key를 생성하게된다. 이 과정을 통해 둘만이 아는 master secret을 공유하게된다.

SSL에서는 서버와 클라이언트가 특정 대칭키 알고리즘, 공개키 알고리즘 혹은 특정 MAC을 사용하라고 강제하지 않는다. 대신에 handshake 과정에서 둘 사이에 어떤 암호화 알고리즘을 사용할지 합의를 하게되고 이 암호화 알고리즘의 세트를 cipher suite라고 부른다. Cipher suite는 여러가지 있다. 그중에서 client가 지원하면서 취약하지 않은 cipher suite의 리스트를 서버에게 알려주면, 서버는 그중에 지원하는 cipher suite를 선택해서 보내 합의한다.

5번 6번 과정은 handshake에서 일어나는 데이터들의 무결성을 보장하기 위한 과정이다. 만약에 1, 2번 과정에서 중간자가 의도적으로 강력한 암호화 알고리즘을 삭제시키고 상대방에게 전달할 경우 5번, 6번 과정에서 자신이 보낸 메세지와 다르다는 것을 확인할 수 있게 된다. 그리고 만약 다르다면 연결은 종료된다.

1번 2번 과정에서의 nonce는 어떤 역할을 할까? 다음과 같은 상황을 생각해보자. nonce의 개념이 없을 때 중간자가 서버와 클라이언트 사이의 handshake 메세지들을 모두 보고있었다. 그리고 다음날 중간자는 자신이 본 handshake 메세지를 통해 서버측에 handshake을 요청하면 서버는 이것이 클라이언트로부터 온 것인지 중간자로부터 온 공격인지 분간할 수 없다. 또한 handshake 메세지 전체를 그대로 보냈기 때문에 각 record에 담긴 MAC의 무결성 검증도 통과할 것이다.

이렇게 TCP 연결 replay attack을 방지하기 위해서 nonce를 사용한다. 매 TCP 연결마다 서버와 클라이언트는 다른 nonce를 사용하기 때문에 매 세션마다 다른 키들이 생성될 것이고 중간자가 복제한 handshake 메세지는 따라서 실패할 것이다.

SSL/TLS handshake 방식 정리
Fig. 6. How SSL handshake proceed

Key Derivation

이론적으로는 둘간에 공유된 master secret을 통해 전송할 데이터를 암호화할 수도있고 무결성을 검증하는데 사용할 수도 있다. 하지만 보안을 위해 두 개의 다른 키를 통해 하나는 데이터를 암호화하는데 사용하고 다른 키를 통해 무결성 검증을 한다. 그렇기 때문에 서버와 클라이언트는 MS를 통해 다음 네 개의 키를 생성하게 된다:

  • EB = 클라이언트가 서버에 데이터를 보낼 때 사용할 세션 암호화 키
  • MB = 클라이언트가 서버에 데이터를 보낼 때 사용할 세션 MAC 키
  • EA = 서버가 클라이언트에 데이터를 보낼 때 사용할 세션 암호화 키
  • MA = 서버가 클라이언트에 데이터를 보낼 때 사용할 세션 MAC 키

Key derivation 단계가 끝나면 서버와 클라이언트는 각각 MS를 통해 네 개의 키를 가지게 된다. 두 개의 암호화 키를 이용하여 자신이 보낼, 그리고 받을 데이터를 암/복호화하는데 사용하고 두 개 MAC 키를 이용하여 데이터의 무결성 검증을 한다.

Data Transfer

이제 서버와 클라이언트는 서로 데이터를 암호화하기 위한 키 준비가 모두 끝났다. 그래서 TCP connection으로 전송하는 byte stream들을 서로가 공유한 키를 통해 암호화를 하고 상대방에게 전송핳면 된다. 그런데 데이터 무결성 검증을 위한 MAC은 언제 어디에 넣어야할까?

세션동안 데이터를 상대방에게 모두 보낸 뒤에 무결성 검증을 한다면 중간자가 이미 데이터를 모두 확인한 상태이거나 혹은 시간적으로 너무 늦게 확인하는 것이 된다. 이러한 문제를 해결하기 위해 SSL에서는 상대방에게 보내려는 데이터를 record로 나누고 각 record에 MAC을 붙여서 데이터 수신측에서는 record 단위로 데이터 무결성 검증을 한다.

MAC을 생성하는 방식은 이제 record 단위로 무결성 검증을 진행하기 때문에 record의 데이터와 key derivation 단계에서 만든 MB을 이용하여 해시값을 만들게 된다. 그리고 해당 record의 값을 숨기기 위해 EB를 이용하여 다시 한 번 암호화한다. 그리고 이 암호화된 데이터를 TCP 레이어에 전달하게 된다.

그렇지만 record만을 이용한다고 해서 데이터 무결성이 완전히 보장되는 것은 아니다. 왜냐하면 각 record의 데이터는 무결성이 보장되지만 전체 데이터의 무결성은 아직 보장되지 않기 때문이다. 좀 더 구체적으로 예를 들면 중간자가 송신측에서 보낸 record들을 받아서 그 순서를 바꾼 뒤에 수신측에 전달한다고 하자. 그렇다면 수신측에서는 각 record들은 서로간에 공유된 키를 이용하여 무결성 검증을 할 수 있지만 받은 데이터를 합치면 순서가 엉망인 결과물이 된다.

이러한 문제를 해결하기 위해 sequence number를 사용한다. sequence number를 사용하여 데이터 무결성을 보장하는 방법은 다음과 같다. 데이터 송신측에서는 record를 보낼 때마다 sequence number를 증가시켜 보낸다. 이 때 sequence number가 record에 포함되는 것은 아니지만 MAC을 계산할 때 이전에는 데이터와 MB을 통해 계산했다면 이제는 sequence number를 포함하여 MAC을 얻어낸다.

SSL Record

Fig. 7은 SSL record에 포함되는 정보들을 보여주고 있다. data와 MAC은 data transfer 단계에서 살펴보았듯이 EB를 통하여 암호화되고 type, version, length 필드 값은 암호화되지 않는다. type 필드를 통해서 서버 클라이언트는 해당 메세지가 handshake를 위한 메세지인지 어플리케이션 데이터를 담고있는지를 알 수 있다. 이는 또한 SSL 연결을 종료할 때도 사용할 수 있다. length 필드를 통해서는 데이터를 복호화하는 쪽에서 TCP를 통해 넘어온 데이터 부분을 추출할 수 있다.

SSL/TLS record 구조 설명
Fig. 7. SSL record structure

Connection Closure

마지막으로 서버와 클라이언트가 SSL 세션을 종료하는 과정에 대해서 살펴보자. 한 가지 방법은 클라이언트가 TCP FIN 요청을 서버로 보내는 것이다. 그런데 단순히 TCP FIN 요청을 보내는 것만으로 세션을 종료하게 된다면 한 가지 문제가 생길 수도 있다. 아직 서버에서 클라이언트로 데이터를 보내는 도중에 만약 중간자가 클라이언트처럼 행세하여 TCP FIN 요청을 보낸다면 서버는 클라이언트가 모든 데이터를 받은 것으로 생각하여 중간에 연결을 끊어버리게 된다. 이와 같은 공격을 truncation attack이라고 한다.

이러한 문제를 해결하기 위해서 이전에 살펴보았던 record의 type 필드에 명시적으로 클라이언트가 세션을 종료할 것인지를 나타내는 값을 넣어서 서버로 보내게된다. type 필드 값은 평문으로 전송되지만 같은 record에 MAC이 포함되기 때문에 해당 record가 변조되었는지는 서버측에서 검증할 수 있다. 서버는 MAC 검증 후에 type 값을 확인하여 세션을 종료하게 된다.

Code, code, code

위에서 이야기한 것들을 모두 확인해볼 수 있는 코드를 github에 정리하였다. 코드는 golang v1.7에서 fork를 하여 필요한 부분만 추려내어 작성하였다. tiny-https이며 위에서 언급된 것과 같은 정말 기본적인 기능들에 대해서 코드가 정리되었다. 필요한 분들은 fork하여 개인적으로 실험을 해보아도 좋을 것 같다.

https://github.com/zeroFruit/thttps

답글 남기기

이메일 주소는 공개되지 않습니다.