HTTPS에 대한 기초 이해

Posted by Yun on 2018-11-25

HTTP의 약점

  • 평문(암호화하지 않은) 통신이기 때문에 도청 가능
  • 통신 상대를 확인하지 않기 때문에 위장 가능
  • 완전성을 증명할 수 없기 때문에 변조 가능

평문이기 때문에 도청 가능

  • HTTP를 사용한 리퀘스트나 리스폰스 통신 내용은 HTTP 자신을 암호화하는 기능은 없기 때문에 통신 전체가 암호화되지 않습니다.
  • TCP/IP는 도청 가능한 네트워크
    • TCP/IP의 구조의 통신 내용은 전부 통신 경로의 도중에 엿볼 수 있습니다. 서버와 클라이언트가 통신할 때 통신 경로 상에 있는 네트워크 기기나 케이블이나 컴퓨터 등을 전부 자기 자신이 소유하고 할 수 없기 때문에 그 경로를 누구나 엿볼
      수 있습니다.
    • 네트워크 상을 흐르고 있는 패킷을 수집하는 것만으로 도청할 수 있게 됩니다.
    • HTTP에는 암호화 구조는 없지만 SSL이나 TLS를 프로토콜을 조합해서 HTTP 통신 내용을 암호화할 수 있습니다.
    • 통신 암호화 : SSL 등을 이용해서 안전한 통신로를 확립하고 나서 그 통신로를 사용해 HTTP 통신을 합니다.
    • 콘텐츠 암호화 : 통신하고 있는 콘텐츠의 내용 자체를 암호화해버리는 방법입니다. HTTP에 암호화를 하는 기능은 없기 때문에 HTTP를 사용해서 운반하는 내용을 암호화하는 것입니다. 즉 HTTP 메시지에 포함되는 콘텐츠만 암호화하는 것입니다.

통신 상대를 확인하지 않기 때문에 위장 가능

  • HTTP를 사용한 리퀘스트나 리스폰스에서는 통신 상대를 확인하지 않습니다. 리퀘스트를 보낸 서버가 정말로 URI에 지정된 호스트인지 아닌지, 리스폰스를 반환한 클라이언트가 정말로 리퀘스트를 출력한 클라이언트인지 아닌지 모릅니다.
  • 누구나 리퀘스트 가능 : HTTP에 의한 통신에는 상대가 누구인지 확인하는 처리는 없기 때문에 누구든지 리퀘스트를 보낼 수 있습니다.
    • 리퀘스트를 보낸 곳의 웹서버가 원래 의도한 리스폰스를 보내야 하는 웹서버인지 아닌지를 확인할 수 가없어 위장 우려가 있습니다.
    • 리스폰스를 반환한 곳의 클라이언트가 원래 의도한 리퀘스트를 보낸 클라이언트인지 아닌지 확인할 수 없어 위장한 클라이언트일 우려가 있습니다.
    • 통신하고 있는 상대가 접근이 허가된 상대인지 아닌지 확인할 수 없어 중요한 정보를 가진 웹서버에서는 특정한 상대만 통신을 허가하고 싶을 때가 있습니다.

HTTPS는 SSL의 껍질을 덮어쓴 HTTP

HTTPS는 새로운 애플리케이션 계층의 프로토콜이 아닙니다. HTTP 통신을 하는 소켓 부분을 SSL이나 TSL이라는 프로토콜로 대체하고 있을 뿐입니다.

보통 HTTP는 직접 TCP와 통신하지만 SSL을 사용하는 경우에는 HTTP는 SSL와 통신하고 SSL이 TCP와 통신하게 됩니다. 즉 SSL이라는 껍질을 덮어쓴 HTTP가 HTTPS인 것입니다.

용어 정리

  • 디지털 인증서 : SSL 인증서는 클라이언트와 서버 간 통신을 제3자가 보증해 주는 전자화된 문서다. 클라이언트가 서버에 접속한 직후 서버는 클라이언트에게 이 인증서 정보를 전달한다. 클라이언트는 이 인증서 정보가 신뢰할 수 있는 것인지 검증한 한 후에 다음 절차를 수행하게 된다.
    • 통신 내용이 공격자에게 노출(암호화하여) 되는 것을 막을 수 있다.
    • 클라이언트가 접속하려는 서버가 신뢰할 수 있는 서버인지를 판단할 수 있다.
    • 통신 내용의 악의적인 변경을 방지할 수 있다.
    • 대칭키 : 대칭키는 동일한 키로 암호화와 복호화를 같이 할 수 있는 암호화 기법을 의미한다. 즉 1234 key로 암호화 했으면 복호화 할 때도 1234 key 값으로 해야 한다.
  • 공개키 : 공개키 방식은 두 개의 키를 갖는다. A키로 암호화를 하면 B키로 복호화 할 수 있고, B키로 암호화했다면 A키로 복호화 할 수 있다. 두 개의 키 중 하나를 비공개 키(개인키, 비밀키)라 하고 나머지를 공개키라고 한다. 비공개 키는 자신만이 가지고 있고, 공개키를 타인에게 제공한다. 공개키를 제공받은 타인은 공개키를 이용해서 정보를 암호화한다. 암호화 정보를 비공개 키를 가지고 있는 사람에게 전송한다. 비공개 키의 소유자는 이 키를 이용해서 암호화된 정보를 복호화 한다. 이 과정에서 공개 키가 유출된다고 하더라도 비공개 키를 모르면 정보를 생성 수 없기 때문에 안전하다.
  • 비공개 키의 소유자는 비공개 키를 이용해서 정보를 암호화 후에 공개키와 함께 암호화된 정보를 전송한다. 정보와 공개키를 획득한 사람은 공개키를 이용해서 암호화된 정보를 복호화 한다. 암호화된 데이터를 공개키를 가지고 복호화 할 수 있다는 것은 그 데이터가 공개키와 쌍을 이루는 비공개 키에 의해서 암호화되었다는 것을 의미한다. 즉 공개키가 데이터를 제공한 사람의 신원을 보장해 주게 되는 것이다.
  • CA : 인증서의 역할은 클라이언트가 접속한 서버가 클라이언트가 의도한 서버가 맞는지 보장하는 역할을 한다. 이 역할을 하는 민간기업들이 있는데 이런 기업들은 CA 혹은 Root Certificate라고 부른다.
    • CA를 브라우저는 알고 있다. 인증서를 이해하는데 꼭 알고 있어야 하는 것이 CA 리스트이다. 이 리스트는 브라우저에서 자체적으로 가지고 있다.

SSL 인증서

  1. 클라이언트가 접속한 서버가 신뢰할 수 있는 서버임을 보장한다.
  2. SSL 통신에 사용할 공개키를 클라이언트에게 제공한다.

SSL 인증서의 내용

  • 서비스의 정보 (인증서를 발급한 CA, 서비스의 도메인 등등)
  • 서버 측 공개키 (공개키의 내용, 공개키의 암화 방법)

SSL 인증서가 서비스를 보증하는 방법

  • 웹 브라우저가 서버에 접속할 때 서버는 제일 먼저 인증서를 제공한다.
  • 브라우저는 이 인증서를 발급한 CA가 자신이 내장한 CA의 리스트에 있는지 확인한다.
  • 확인 결과 서버를 통해서 다운로드한 인증서가 내장된 CA 리스트에 포함되어 있다면 해당 CA의 공개키를 이용해서 인증서를 복호화 한다.
    • 비밀키로 암호화한 정보를 공개키로 복호화 할 수 있다는 것은 그 정보가 틀림없이 쌍으로 존재하는 것이다. 즉 정보의 출처(접속한 사이트)를 신뢰할 수 있다.

SSL의 동작방법

SSL은 암호화된 데이터를 전송하기 위해서 공개키와 대칭키를 혼합해서 사용한다. 클라이언트와 서버가 주고받는 실제 정보는 대칭키 방식으로 암호화하고, 대칭키 방식으로 암호화된 실제 정보를 복호화 할 때 사용할 대칭 키는 공개키 방식으로 암호화해서 클라이언트와 서버가 주고받는다.

공개키 방식은 컴퓨터의 성능을 많이 들기 때문에 두 가지 방식을 혼합해서 사용한다.

  • 실제 데이터: 대칭키
  • 대칭키의 키: 공개키

HTTPS 흐름

  1. 클라이언트가 Client Hello 메시지를 송신하면서 SSL 통신을 시작합니다. 메시지에는 클라이언트가 제공하는 SSL 버전을 지정하고, 암호 스위트(Cipher Suite)로 불리는 리스트(사용하는 암호화 알고리즘이나 키 사이즈 등)이 포함되어 있습니다.
  2. 서버가 SSL 통신이 가능한 경우에는 Server Hello 메시지로 응답합니다. 클라이언트와 같이 SSL 버전과 암호 스위트를 포함합니다. 서버의 암호 스위스트 내용은 클라이언트에서 받은 암호 스위트의 내용에서 선택된 것입니다.
  3. 서버가 Ceriticate 메시지를 송신합니다. 메시지에는 공개키 증명서가 포함되어 있습니다.
  4. 서버가 Server Hello Done 메시지를 송신하여 최초의 SSL 네고시에이션 부분이 끝났음을 통지합니다.
  5. SSL의 최초 네고시에이션이 종료되면 클라이언트가 Client Key Exchange 메시지로 응답합니다. 메시지에는 통신을 암호화하는데 사용하는 PreMaster secret이 포함되어 있습니다. 이 메시지는 (3)의 공개키 증명서에서 꺼낸 공개키로 암호화되었습니다.
  6. 클라이언트는 Change Cipher Spec 메시지를 송신합니다. 이 메시지는 이 메시지 이후의 통신은 암호 키를 생성해서 진행한다는 것을 나타내고 있습니다.
  7. 클라이언트의 Finished 메시지를 송신합니다. 이 메시지는 접속 전체의 체크 값을 포함하고 있습니다. 네고시에이션이 성공했는지 어떤지는 서버가 이 메시지를 올바르게 복호화를 할 수 있는지 아닌지가 결정합니다.
  8. 서버도 마찬가지로 Change Cipher Spec 메시지를 송신합니다.
  9. 서버에도 마찬가지로 Finished 메시지를 송신합니다.
  10. 서버와 클라이언트의 Finished 메시지 교환이 완료되면 SSL에 의해 접속은 확립됩니다. 이제부터 애플리케이션 계층의 프로토콜에 의해 통신입니다. 즉 HTTP 리퀘스트를 송신합니다.
  11. 애플리케이션 계층의 프로토콜에 의한 통신입니다. 즉 HTTP 리스폰스를 송신합니다.
  12. 마지막에 클라이언트가 접속을 끊습니다. 접속을 끊을 경우 close_notify메시지를 송신합니다. 그림에서는 생략되었지만 그 후에는 TCP FIN 메시지를 보내 TCP 송신을 종료합니다.

간략한 흐름

  1. 클라이언트가 서버에 접속한다. 이 단계를 Client Hello라고 한다. 이 단계에서는 주고받는 정보는 아래와 같다
  • 클라이언트 측에서 생성한 랜덤 데이터: 아래 3번 과정 참조
  • 클라이언트가 지원하는 암호화 방식들 : 클라이언트와 서버가 지원하는 암호화 방식이 서로 다를 수 있기 때문에 상호 간에 어떤 암호화 방식을 사용할 것인지에 대한 협상을 해야 한다. 이 협상을 위해서 클라이언트 측에서는 자신이 사용할 수 있는 암호화 방식을 전송한다.
  • 세션 아이디 : 이미 SSL 핸드셰이킹을 했다면 비용과 시간을 절약하기 위해서 기존 세션을 재활용하게 되는데 이때 사용할 연결에 대한 식별자를 서버 측에 전송한다.
  1. 서버는 Client Hello에 대한 응답으로 Server Hello를 하게 된다. 이 단계에서 주로 받는 정보는 아래와 같다.
  • 서버 측에서 생성한 랜덤 데이터 : 아래 3번 과정 참조
  • 서버가 선택한 클라이언트 암호화 방식 : 클라이언트가 전달한 암호화 방식 중에 서버 쪽에서도 사용할 수 있는 암호화 방식을 선택해서 클라이언트에게 전달한다. 이로써 암호화 방식에 대한 협상이 종료되고 서버와 클라이언트는 암호화 방식을 이용해서 정보를 교환한다.
  1. 클라이언트는 서버의 인증서가 CA에 의해 발급된 것인지 확인하기 위해서 클라이언트 (브라우저)에 내장된 CA 리스트를 확인한다. CA 리스트에 인증서가 없다면 사용자에게 경고 메시지를 출력한다. 인증서가 CA에 의해서 발급된 것인지를 확인하기 위해서 클라이언트에 내장된 CA의 공개키를 이용해서 복호화 한다. 복호화에 성공했다면 인증서는 CA 개인키로 암호화된 문서임을 암시적으로 보장된 것이다. 인증서를 전송한 서버를 믿을 수 있게 된 것이다.
  • 클라이언트는 상기 2번을 통해서 받은 서버의 랜덤 데이터와 클라이언트가 생성한 랜덤 데이터를 조합해서 PreMaster secret이라는 키를 생성한다. 이 키는 뒤에서 살펴볼 세션 단계에서 데이터를 주로 받을 때 암호화하기 위해서 사용할 것이다. 이때 사용할 암호화 기법은 대칭키이기 때문에 PreMaster secret 값은 제3자에게 절대로 노출되어서는 안 된다.
  • PreMaster secret 값을 서버로 전송할 때 공개키 방식으로 전달한다. 서버의 공개키로 PreMaster secret 값을 암호화해서 서버로 전송하면 서버는 자신이 비공개 키로 안전하게 복호화 할 수 있다. 이때 서버의 공개키는 서버로 받은 인증서 안에 들어 있다. 이 서버의 공개키를 이용해서 PreMaster secret 값을 암호화한 후에 서버로 전송하면 안전하게 전송될 수 있다.
  1. 서버는 클라이언트가 전송한 PreMaster secret 값을 자신의 비공개 키로 복호화 한다. 이로써 서버와 클라이언트가 모두 PreMaster secret 값을 공유하게 되었다. 그리고 서버와 클라이언트 모두 일련의 과정을 거쳐 PreMaster secret 값을 Master secret 값으로 만든다. 이 값은 session key를 생성하는데 이 값을 이용해서 서버와 클라이언트는 데이터 대칭키 방식으로 암호화한 후에 주고받는다 이렇게 해서 세션 키를 클라이언트와 서버가 모두 공유하게 되었다.
  2. 클라이언트와 서버는 핸드셰이킹 단계를 서로에게 알린다.

출저