[OS] 44(Final). Distributed System

Park Yeongseo·2024년 4월 22일
0

OS

목록 보기
54/54
post-thumbnail

Operating Systems : Three Easy Pieces를 보고 번역 및 정리한 내용들입니다.

1. Introduction

OS는 자신이 설치된 컴퓨터의 자원들만 제어할 수 있다. 그렇기 때문에 OS를 통해 여러 기기들이 협업해야 하는 분산 시스템에서의 보안을 제공하는 일은 어렵다.

  • 분산 시스템 내의 다른 기계는 우리가 원하는 보안 정책을 제대로 구현하고 있지 않을 수 있다. 우리는 원격 시스템을 제어할 수 없지만, 그럼에도 불구하고 그들이 우리에게 주는 자격증명 및 자격이 유효하다고 믿을 수 있길 바란다.
  • 분산 시스템 내의 기계들은 네트워크를 통해 소통한다. 그런데 분산 시스템 내의 기계들 중 어느 것도 네트워크에 대한 완전한 제어를 가지고 있지 않다. 공격자들도 네트워크에 대한 동등한 접근 권한을 가지고 있고, 네트워크에서 흐르는 우리의 메시지를 복사, 재생, 수정, 삭제, 지연시킬 수 있다.

하나 이상의 기계들로 만들어진 시스템을 어떻게 보안적으로 안전하게 만들 수 있을까? 그런 시스템을 보호하는 데 도움이 되는 도구에는 어떤 것들이 있고, 이것들은 어떻게 쓸 수 있을까?

2. The Role of Authentication

분산 시스템 내의 다른 파트너가 우리의 보안 정책을 따르고 있다는 걸 어떻게 알 수 있을까? 대부분의 경우는 알 수 없고, 기껏해야 우리는 보안 정책에 대해 합의하고 모든 사람들이 그것에 따르기를 희망할 수 밖에 없다. 이 파트너들이 제대로 동작하고 있다는 양질의 증거를 얻을 수 있는 특이 케이스들도 있지만, 일반적으로는 그렇지 않다. 물론 그들은 자신이 보안 정책을 잘 따르고 있다고 말하겠지만, 어떻게 우리는 그 사실을 알 수 있을까?

일반적으로는 알 수 없다. 때문에 분산 시스템 환경에서는 (우리가 실제 생활에서도 그렇듯) 일단은 시스템에 참여한 구성원들이 보안 정책을 따르고 있다고 믿고, 그들이 해당 정책을 따르지 않았음을 감지하면 그에 대한 보상을 요구한다.

그러나 사이버 세계에서는 모든 것이 네트워크를 통해 움직이고, 우리가 볼 수 있는 것은 그 네트워크를 통해 오고 가는 비트들 밖에 없다. 따라서 위와 같은 신뢰-기반 해결법이 동작하려면, 우리와 우리의 파트너는 자신이 받은 비트가 정말로 상대편으로부터 온 것임을 검증할 수 있는 방법을 가지고 있어야 한다.

이는 인증의 역할이다. 이전 인증 장에서 다룬 것처럼, 네트워크 상에서 작업을 할 때에는 비트를 통한 인증 형식이 필요하다. 원격 OS에서 실행되고 있는 상대편만이 알 수 있는 정보에는 어떤 게 있을까? 패스워드는 어떨까? 개인 키는 어떨까?

대부분의 분산 시스템 인증은 이 둘 중 하나를 통해 이루어지며, 우리는 이 인증을 확인하기 위한 무언가를 알고 있어야 한다. 패스워드의 경우에는 패스워드, 혹은 패스워드의 해시값이 될 것이고, 개인 키의 경우에는 공개 키가 될 것이다.

각각에 대해, 더 적합한 경우는 언제일까? 요컨대 패스워드는 많은 수의 사람들이 한 곳에 인증을 해야하는 경우에 더 유용하고, 공개 키는 한 사람이 여러 곳에 인증해야하는 경우에 더 유용하다. 패스워드를 사용하는 경우, 패스워드에 대해 아는 사람은 패스워드 제공자와 이를 검증하는 쪽 밖에 없다. 공개 키를 사용하는 경우, 많은 이들이 키를 알 수는 있지만, 오직 그에 맞는 개인 키를 가지고 있는 쪽만 이를 인증에 사용할 수 있다.

예를 들어, 웹 사이트가 자신을 사용자에게 인증해야하는 경우는 공개 키 암호화를 이용한다. 웹사이트는 공개 키를 여러 사용자들에게 분배하고, 자신의 개인 키를 이용해 스스로를 인증한다. 이 웹 사이트는 굳이 자신을 각 사용자들에게 인증하기 위해 별개의 인증 정보를 가지고 있을 필요가 없다. 만약 사용자가 자신을 웹 사이트에 인증하고자 하는 경우에는 패스워드를 이용하면 된다. 각 사용자는 모두 웹 사이트에 개별적으로 인증되어야 하고, 이를 위해서는 해당 사용자 각각이 사용할 수 있는, 각 사용자를 식별하기 위한 고유 정보가 필요하기 때문이다.

그렇다면 이 인증 메커니즘들은 분산 시스템에서 어떻게 쓸 수 있을까? 만약 원격 파트너가 자신을 패스워드를 통해 인증하게 만들고 싶다면, 우리는 그가 우리에게 패스워드를 제공하도록 요구하고 이를 확인할 수 있다. 이때 패스워드는 암호화되어야 한다. 그렇지 않으면 누군가가 네트워크를 도청해 패스워드를 알아낼 수도 있기 때문이다. 패스워드를 암호화하는 경우, 우리는 사전에 대칭 키를 공유하거나, 상대방의 공개 키를 알아야 한다. 그렇다면 어떻게 우리가 그 공개 키를 얻을 수 있을 지에 대해 알아보자.

3. Public Key Authentication For Distributed Systems

공개 키는 비밀일 필요가 없다. 하지만 우리는 파트너가 실제로 이것을 알고 있음을 확신할 수 있어야 한다. 물론 직접 만나서 공개 키를 가지고 있는지 확인할 수 있다면 좋겠지만, 우리는 우리와 상호작용하는 파트너를 대면해서 만나지 않는다.

다행히도 단순히 공개 키를 포함하는 비트 패턴들을 만드는 데에는 비밀성이 필요하지 않다는 사실을 이용할 수 있다. 우리는 이 비트 패턴의 복사본을 가지고 있는 누구든, 공개 키를 가지고 있다고 생각할 수 있다. 그런데 이 경우, 해당 비트 패턴을 가진 이들은 어떻게 그것이 자신의 파트너의 공개 키라는 사실을 알 수 있을까? 파트너를 인증해야 하는모두에게 알려진, 신뢰할 수 있는 다른 이가 자신의 공개 키를 이용해 해당 비트 패턴을 암호화해 서명하고, 이를 통해 그것이 실제로 파트너에게 속한 것임을 증명한다면 어떨까? 만약 우리가 그 서명을 확인할 수 있으면, 우리는 그것이 정말로 파트너의 공개 키를 표현한 것임을 확신할 수 있게 된다. 적어도 서명을 한 서드 파티를 믿을 수 있는 정도로는 말이다.

이 테크닉은 우리가 실제로 웹 사이트에 인증을 하는 데 쓰이며, 우리는 웹을 탐색하거나 다른 웹-기반 활동들을 할 때 이 테크닉을 사용한다. 이렇게 서명된 비트 다발을 가리켜 인증서(certificate)라 부른다. 기본적으로 여기에는 공개 키를 소유하고 있는 자의 정보, 공개 키, 그리고 만료일 등의 다른 정보들이 들어있다. 이 모든 정보들은 암호학적 해시를 거치고, 그 결과는 신뢰할 수 있는 서드 파티의 개인 키로 암호화된다. 만약 이 인증서의 복사본을 얻고 그 서명을 확인할 수 있으면, 우리는 그와 직접 상호작용하지 않고도 그들의 공개 키에 대해 알 수 있다.

간단하게 예시를 통해 알아보자. Frobazz Inc. 라는 기업이 공개 키 KFKF를 위해 인증서를 얻고 싶다고 하자. Frobazz Inc.는 인증서를 판매하는, 믿을 수 있는 기업 Acmesign Co.에 인증서를 얻기 위한 비용을 지불하고 있다. 이렇게 인증서를 판매하는 기업을 가리켜 인증 기관(Certificate Authority, CA)라 부른다. Acmesign은 Frobazz Inc.를 확인해, 인증서 발급을 요청한 이가 Frobazz의 적법한 대표자인지를 확인하고, 자신이 인증서에 넣고자 하는 공개 키가 Frobazz에서 사용하고자 하는 것인지 확인한다. 만약 그렇다면 Acmesign은 암호학적 해싱 알고리즘을 Frobazz의 이름, 공개 키 KFKF, 또 다른 정보들에 적용해 해시 HFHF를 만들어낸다. 이후 이를 자신의 개인 키 PAPA로 암호화해 디지털 서명 SFSF를 만든다. 마지막으로 Acmesign은 HFHF를 만들기 위해 썼던 모든 정보들과 자기 자신의 신원, 그리고 서명 SFSF를 모아 서명 CFCF에 넣고 Frobazz에게 건넨다.

이제 Frobazz Inc.는 자기 자신을 인터넷 상의 고객에게 인증하려고 한다. 만약 고객이 이미 Frobazz의 공개 키를 가지고 있다면, 우리는 이 공개 키를 인증 메커니즘에 바로 사용할 수 있다. 반대로 만약 고객이 공개 키를 가지고 있지 않다면 Frobazz는 CFCF를 고객에게 보낸다. 고객은 Acmesign이 만든 이 인증서를 살펴보고, 이 인증서가 어떤 알고리즘으로 암호화됐는지를 확인하고, Acmesign이 해싱했던 것과 동일한 정보를 같은 알고리즘으로 해싱해 HFHF'를 만든다(이 정보들은 모두 SFSF에 포함되어 있다). 이후 고객은 Acmesign의 공개 키로 SFSF를 복호화해 HFHF를 얻는다. 만약 HFHFHFHF'가 같으면, 고객은 인증서에 포함된 공개 키가 Frobazz의 것임을 확신할 수 있게 되고, 이후의 인증 과정에서 이 공개 키를 사용할 수 있게 된다. 만약 두 해시값이 서로 다르다면, 고객은 이 인증서가 제대로 된 것이 아님을 알고 받아들이지 않게 될 것이다.

공개 키를 얻기 위해 이 방식을 사용함으로써 얻을 수 있는 여러 이점들이 있다.

  1. 서명 기관은 고객의 인증서 확인 과정에 참여할 필요가 없다. 고객은 어디에서든 인증서를 가져올 수 있고, 동등한 수준의 유효성을 보증받을 수 있다.
  2. 이 과정은 고객 당 한 번만 이뤄지면 된다. 인증서를 얻고 확인한 후, 고객은 공개 키를 저장하고 사용하기만 하면 된다. 만약 어떤 이유로 공개 키를 잃어버리게 되면, 저장된 인증서를 통해 다시 공개 키를 얻거나, 인증서 획득 과정을 다시 밟으면 된다.
  3. 고객은 자신이 Frobazz라고 주장하는 쪽의 신원이 인증서를 통해 확인되기 전까지는 믿을 필요가 없다.

그런데 문제가 있다. 위 과정은 Frobazz의 공개 키를 얻고 확인하기 위해 진행한 것인데, 인증서를 복호화하기 위해서는 Acmesign의 공개 키를 먼저 알아야 한다는 것이다. 이 키가 유효하다는 것은 어떻게 알 수 있을까? 또 믿을 수 있는 제 3자에게 기대는 방법도 가능하겠지만, 그 경우에도 마찬가지의 문제가 발생한다. 믿을 수 있는 최초의 공개 키는 어디서 얻을 수 있을까?

가장 흔하게, 이 공개 키는 우리가 설치한 소프트웨어에 있다. 예를 들어 브라우저에는 여러 믿을 수 있는 기관들의 공개 키가 들어 있다. 보안이 필요한 웹 사이트에 접속할 때, 이는 해당 사이트의 공개 키가 포함되고, 믿을 수 있는 기관 중 하나에 의해 서명된 인증서를 제공한다. 이렇게 사전에 설정된 기관의 공개 키를 이용해 인증서가 정말 제대로 된 것인지를 확인하면, 해당 웹 사이트의 공개 키를 알 수 있게 되고, 이후의 인증 과정에서는 그 웹 사이트의 공개 키를 사용한다.

그런데 인증서는 신뢰할 수 있는 CA 뿐만 아니라, 누구든 만들 수 있다. 그런데 인증될 쪽과 인증을 수행하는 쪽은 그 인증서가 누구로부터 만들어진 것이든 그 기관을 믿을 수 있어야 한다. 인증서 발급 기관을 믿을 수 없다면 인증서도 믿을 수 없기 때문이다.

만약 스스로 분산 시스템을 만든다면, 신뢰할 수 있는 한 컴퓨터에서 인증서를 만들고, 공개 키를 필요로 하는 곳에 이를 서명하는 인증서를 설치하면 된다. 인증서를 만들기 위한 소프트웨어 패키지는 많다. 직접 이를 구현하기 보다는 믿을 수 있는, 이미 있는 것들 중 하나를 선택해 사용하도록 하자.

어떻게든 원격 기기를 인증하는 데 필요한 공개 키를 얻었다고 해보자. 이젠 뭘 해야할까? 원격 기기가 인증을 위해 보낸 것들은 모두 그들 자신의 개인 키로 암호화되어 있고, 복호화는 그것에 대응하는 공개 키로만 가능하다. 따라서 어떤 정보가 공개 키로 복호화할 수 있다면, 이 정보는 그들로부터 온 것임을 알 수 있다.

문제는 공격자가 이 메시지를 가로채, 이 메시지가 정상적으로 발송되었을 때가 아닌, 그 이후에 보내는 경우도 있을 수 있다는 것이다. 이러한 공격을 가리켜 재생 공격(replay attack)이라 부르며, 이는 공격자를 승인된 사용자로 오인하게 만들 수 있다. 이 공격을 막는 방법으로는 각 암호화된 메시지에 다른 메시지에는 없는 고유 정보를 넣는 것이 있다. 이 기능은 표준 암호화 프로토콜들에 이미 만들어져 있으므로, 이것들을 사용하면 재생 공격에 대한 보호를 얻을 수 있다. 하지만 스스로 암호화 기법을 만든다면 더 많이 고심하고 공부해야 한다.

4. Password Authentication For Distributed Systems

분산 시스템에서 인증을 하기 위한 다른 옵션으로는 패스워드를 사용하는 것이 있다. 위에서 말했듯, 패스워드는 여러 사용자들이 한 곳에 인증을 하는 경우에 적합하고, 한 사람이 여러 곳에 인증해야하는 경우와는 잘 맞지 않는다. 후자의 경우는 공개 키 방식이 더 낫다.

패스워드 사용이 더 적합한 경우, 어떻게 네트워크 환경에서 패스워드 인증을 제대로 다룰 수 있을까? 패스워드는 보통 특정 사용자 ID와 연관되어 있고, 따라서 사용자는 ID와 패스워드를 인증이 필요한 사이트에 제출한다. 이때 네트워크 상에서 누군가가 전송되고 있는 패스워드를 가로챌 수도 있기 때문에, 패스워드는 네트워크를 통해 전송되기 전에 암호화되어야 한다.

그런데 패스워드를 암호화해야 한다면, 어떤 키를 써야할까? 만약 위에서 처럼 Frobazz가 공개 키로 자신을 사용자에게 인증했다면, 사용자는 자신의 ID와 패스워드를 Frobazz의 공개 키로 암호화할 수 있다. 공개 키에 맞는 개인 키를 가지고 있는 Frobazz만이 사용자가 보낸 메시지를 확인할 수 있다. 하지만 실제로는 이것만으론 부족하다. 위에서 언급한 재생 공격 등의 가능성이 있기 때문이다. 우리는 Frobazz의 개인 키를 사용자 패스워드 전송을 보호하는 데 사용할 수 있다. 이와 관련한 내용은 다음의 SSL/TLS 섹션에서 자세히 다룬다.

이전의 인증 장에서 패스워드 선택 및 관리에 대한 이야기들을 했었는데, 이것들은 모두 네트워킹 컨텍스트에도 적용된다. 더 생각해보아야 할 것은 원격 사이트가 패스워드를 검증한 후 알게 되는 것에는 무엇이 있는지 정도다. 패스워드를 검증함으로써 알 수 있는 것은, 해당 패스워드를 제출한 사용자, 혹은 사이트가 그것을 알고 있다는 것, 그러므로 이를 제출한 사람이 바로 그 사용자, 혹은 사이트라는 사실 뿐이다.

그렇다면 인증 후의 후속 메시지들의 경우는 어떨까? 이 메시지들도 진짜임을 표시하기 위해서는 여기에도 패스워드를 담아보내야 할 것 같은데, 이렇게 되면 모든 메시지들에 패스워드를 담아 보내야 한다. 하지만모든 메시지에 패스워드를 포함할 필요는 없다. 우리는 초기 인증을 설정하고, 이를 후속 상호 작용들에 연결할 수 있게 하는 인증 테크닉을 사용한다.

5. SSL/TLS

이전 장에서, 현대 시스템에서는 두 프로세스 사이의 소통을 위해서는 표준적으로 소켓을 이용한다고 얘기했다. 이는 프로세스들이 서로 다른 기기에 있을 때도 마찬가지다. 따라서 보호되지 않는 네트워크 통신에 암호화 보호를 추가하기 위해서는 소켓에 암호화 기능을 추가하는 것이 자연스럽고, 이것이 바로 SSL(Secure Socket Layer)이 만들어진 이유다. 하지만 SSL은 이 역할을 제대로 하지 못했고, 이를 개선해 만들어진 것이 TLS(Transport Layer Security)다. SSL은 안전하지 않으므로 쓰지 말아야 하고, TLS를 써야 한다. 유일한 예외는 장치가 오래돼서 TLS를 지원하지 않는 경우 뿐인데, 이 경우에는 아무 것도 쓰지 않는 것보다는 나으니 SSL을 써야 한다.

SSL의 컨셉은 간단하다. 암호화된 데이터를 일반 소켓을 통해 이동시키는 것이다. 소켓을 설정하고, 수행할 암호화를 위한 특수한 구조를 설정한 후, 해당 구조의 출력을 소켓의 입력과 연결시킨다. 반대쪽은 이와 반대로 설정한다. SSL의 장점은, 실행 단계에 큰 변화를 주지 않고 몇 가지 추가적인 단계를 더해 원하는 결과를 얻을 수 있다는 것이다. 또한 SSL은 일반성을 가져, 여러 암호화 작업 및 여러 종류의 암호화 알고리즘을 지원한다. 송수신자 간의 키 교환 및 인증 수행을 하기 위한 방식도 여러 가지 지원한다.

하지만 SSL을 프로그램에 추가하는 일은 복잡한데, 올바른 SSL 연결을 위해서는 특정 라이브러리 및 해당 라이브러리로의 콜 시퀀스를 사용해야 하기 때문이다. 이 작업의 대부분은 SSL의 일반성을 제공하기 위한 것들이다. 이 작업들에 대해 하나하나 알아보지는 않겠지만, 만약 SSL을 제대로 사용하려 한다면 제대로 공부해야 한다.

한 가지 자세히 알아볼 만한 것은, 설정하려 하는 연결에 사용할 암호화 키를 어떻게 안전하게 분배하느냐 하는 것이다. 가장 안전한 것은 연결을 만들 때마다 데이터를 암호화하기 위한 새로운 키를 사용하는 것이다. 이를 위해서는 인증을 위한 공개/비밀 키도 많이 써야 하고, 인증 이후 데이터를 암호화하기 위한 대칭 키도 사용해야 한다(공개 키의 경우 컴퓨팅이 많이 필요하기에, 모든 데이터를 공개 키 방식으로 암호화한다면 너무 비효율적이다). 만약 같은 파트너와 동시에 여러 SSL 연결을 맺는다면, 그 연결 각각에 서로 다른 대칭 키를 사용해야 한다.

새 SSL 연결을 맺을 때에는 뭘 해야할까? 우선 사용 가능한 대칭키가 없는 경우, 비대칭 암호화 방식에 기반해 안전한 연결을 맺어야 한다. 가장 첫 번째 단계는 클라이언트와 서버 사이의 협상 단계다. 이 각자는 자신이 설치한 SSL 버전, 그 설정, 그리고 SSL 연결을 맺는 프로그램이 작성된 방식에 따라 서로 다른 암호화 알고리즘, 해시, 키 분배 전략, 인증 방식 등을 가진다. 대부분의 경우 협상은 양측에서 동의할 수 있는, 보안-성능 간 밸런스를 만족하는 암호화 알고리즘 및 테크닉 집합을 찾으면서 끝이 난다.

예를 들면 비대칭 암호화를 위한 2048 비트 키의 RSA, 새 대칭 키를 분배하기 위한 디피-헬먼 키 교환 메커니즘, 무결성을 위한 SHA-3 해싱 알고리즘, 데이터 암호화를 위한 256 비트 키의 AES를 조합해 사용할 수 있다. 현대 SSL은 이러한 옵션들의 조합을 보통 50개 이상 제공한다. 어떤 경우에는 이 조합들 중 시스템에서 쓸 수 있는 것은 무엇이 있는지 알아야 할 수도 있지만, 대부분의 경우는 SSL이 각 연결에 어떤 것을 쓸지 맡겨놔도 괜찮다. 협상이 끝나면 SSL은 서버 인증(클라이언트 인증은 선택적), 대칭 키 생성 및 분배, 선택된 암호화 알고리즘 및 키를 이용한 통신 등, 자신이 할 일들을 계속 진행한다.

디피-헬먼 키 교환을 이용해 키를 생성할 수 있는데, 이 경우 우리는 이 키를 누구와 공유할 것인지를 분명히 할 필요가 있다. SSL은 이를 위해 쓸 수 있는 방식도 여럿 제공하는데, 가장 흔히 쓰이는 방식은 클라이언트가 서버의 공개 키를 가지고 있는 인증서를 얻게 하고, 해당 인증서에 있는 공개 키로 서버 메시지의 진위를 확인케 하는 것이다. 클라이언트는 인증서를 다른 방식으로도 얻을 수 있지만, 그런 경우는 흔치 않다. 다만 클라이언트가 다른 방식으로 얻었다고 해서, 서버로부터 인증서를 받았을 때보다 그 인증서를 믿을 수 없는 것은 아니다. 인증서의 보안은 이를 전송하는 방식에 달린 것이 아니라, 해당 인증서 내에 들어간 암호화 방식에 달려 있기 때문이다.

어떻게든 클라이언트가 해당 인증서를 받았다면, 디피-헬먼 키 교환을 인증된 방식으로 진행할 수 있게 된다. 서버는 자신의 디피-헬먼 메시지를 자신의 개인 키로 서명하고, 클라이언트는 이를 가지고 키 교환의 상대가 올바른 서버인지 확인한다. 보통 클라이언트는 자신의 인증서를 제공하지 않고, 자신의 디피-헬먼 메시지에도 서명하지 못한다. 이는 SSL의 디피-헬먼 키 교환이 완료됐을 때, 클라이언트는 서버가 누구인지 알지만 서버는 클라이언트가 누군지 모른다는 것을 함축한다. 물론 SSL에는 여러 옵션이 있어서 꼭 위와 같은 경우만 있으리라는 법은 없지만, 클라이언트도 인증서를 사용하는 방식은 흔치 않으며, 특히 보안 웹 브라우징에서는 잘 쓰이지 않는다.

하지만 서버가 클라이언트에 대해 알지 못한다는 게 그렇게 큰 문제가 되지는 않는다. 앞서 말헀듯 클라이언트는 보통 인증서에서 가져온 공개 키가 아니라, 패스워드를 통해 자신을 인증하기 원하기 때문이다. 만약 서버가 클라이언트로부터 패스워드를 얻고, 이를 확인하기 전까지는 인증이 필요한 어떤 서비스도 제공하지 않는다면, 서버는 클라이언트가 누구든 전혀 상관하지 않는다. 서버는 사용자 ID와 패스워드가 필요하게 되면, SSL 연결이 맺어진 이후 언제든 그것들을 사용자에게 물어볼 수 있다. SSL은 데이터 전송을 위해 대칭 키를 사용하므로, ID 및 패스워드의 교환은 해당 키들로 암호화해 보호될 수 있다.

SSL/TLS에 대해 마지막으로 할 말은, 이것들이 소프트웨어 패키지가 아니라 프로토콜이라는 점이다. 이 프로토콜을 구현하고 있는 소프트웨어 패키지에는 아주 많은 것들이 있다. 이상적으로는, 그것들이 모두 프로토콜을 제대로 구현하고 있다면 서로 올바로 상호작용할 것이다. 하지만 이들은 프로토콜 구현을 위해 서로 다른 코드를 사용하고 있다. 그 결과, 한 SSL/TLS 구현에서의 소프트웨어 결함은 다른 구현에서는 나타나지 않을 수도 있다. 예를 들어 Heartbleed 공격은 OpenSSL의 구현에 기반한 것이었고, 마이크로소프트 Windows에서는 나타나지 않았다.

또한 현재 SSL/TLS 프로토콜 정의는 모든 구현에서 결함을 일으킬 수 있는, 프로토콜 결함을 가지고 있을 수도 있다. 만약 나중에 SSL에 대한 보안 문제를 겪게 된다면, 우선 이것이 프로토콜 결함인지 구현 결함인지를 확인하고 이후의 행동을 정하도록 하자. 만약 그게 구현 결함이라면 다른 구현을 사용하기만 하면 될 것이다.

6. Other Authentication Approaches

패스워드와 공개 키가 가장 흔히 쓰이는 인증 방식이기는 하지만, 다른 옵션들도 있다. 그 중 하나는 항상 쓰이는 것이다. 앞서 말했듯 한 번 인증이 마친 후의 후속 메시지에 계속 인증 정보를 담아서 보내는 것은 비효율적이다. 따라서 서버는 한 번 인증이 마치면 해당 정보가 계속해서 유효하다고 가정한다. 따라서 인증이 마친 시점에서 세션이 암호화되고, 서버는 제대로 된 방식의 암호화를 인증 형식으로 생각하고 사용한다. 하지만 브라우저를 끄고, 다시 열고, 이전 페이지로 돌아갔을 때, 여전히 새로운 패스워드를 요청하지 않고 인증된 사용자로 취급될 수도 있다. 이 시점에서는 이전과 같은 암호화를 사용하지 않는다. 새로운 세션을 열고 새로운 암호화 키를 설정하기 때문이다. 그렇다면 서버는 어떻게 클라이언트가 새로운 키를 받았다는 것을 알 수 있을까?

이 경우, 우리가 작업하는 사이트는 보안적으로 타협을 한다. 이 사이트는 과거 어떤 시점에 패스워드를 이용해 사용자 신원을 검증하고, 미래에는 다른 방식을 이용해 사용자를 인증한다. 흔히 쓰이는 방법은 웹 쿠키를 사용하는 방법이다. 웹 쿠키는 웹 사이트에서 클라이언트로 보낼 수 있는 데이터로, 클라이언트가 해당 데이터를 저장해놓고 이후 서버와의 통신에 다시 보낼 수 있도록 하게 만드는 데 쓰인다. 웹 쿠키는 대부분의 브라우저에 있고, 사용자의 개입 없이, 보이지 않게 처리된다. 제대로 된 암호화를 사용하면 이전에 클라이언트의 패스워드를 검증했던 서버는 클라이언트의 신원을 안전하게 저장할 수 있는 웹 쿠키를 만들 수 있다. 클라이언트가 나중에 다시 서버와 통신하면, 웹 브라우저가 자동으로 쿠키를 요청에 넣고, 서버는 이를 통해 클라이언트에게 패스워드를 다시 묻지 않고 사용자 신원을 검증할 수 있게 된다.

하지만 이런 방식을 사용했을 때에는 몇 가지 보안 문제가 발생할 수 있다. 이 기술을 설계한 사람들은 네트워크를 통한 쿠키 전달 시의 도청 및 복제 문제와 같은 것들을 다뤄왔다. 하지만 쿠키를 사용했을 때에는 해결할 수 없고, 항상 사용자에게 패스워드를 요청해야만 풀리는 문제들도 있다. 따라서 시스템을 만들 때에는, 이런 종류의 보안 타협점들에 대해서 생각해봐야 한다.

또 다른 인증 옵션도 있다. 그 중 하나는 시도 응답 프로토콜(challenge/response protocol)이라 불리는 것이다. 여기에서 원격 기기는 보통 숫자 형식으로 된 시도(challenge)를 우리에게 보낸다. 우리가 스스로를 인증하려면, 우리는 이 시도에 응답을 만들기 위한 몇 가지 작업들을 해야 한다. 이 작업은 오직 승인된 사용자만이 수행할 수 있는 작업이어야 하기에, 보통은 승인된 사용자만이 알고 있는 비밀을 사용한다. 시도에 비밀을 적용해 응답을 만들고 서버로 보내면, 서버는 이것이 올바른 응답인지를 검증할 수 있어야 한다.

시도는 매번 다른 것이 보내지기 때문에, 공격자는 도중에 시도와 응답을 도청하더라도 그것을 사용할 수 없다. 그렇기 때문에 시도와 응답은 꼭 암호화될 필요가 없다. 시도 응답 시스템은 보통 어떤 종류의 암호화 작업을 수행해, 보통은 해싱 연산이다. 시도 응답 시스템에는 시도를 제시하는 기계와 스스로를 인증하는 기계 사이의 사전 협의가 필요하며, 이를 위해서는 시도가 만들어지기 전에 하드웨어 토큰이나 비밀 데이터가 만들어져 분배되어야 한다.

또 다른 인증 옵션으로는 인증 서버를 사용하는 것이 있다. 이 서버는 클라이언트가 신뢰하는 서버이고, 이 서버 또한 스스로도 클라이언트를 신뢰해야 한다. 우리가 인증을 하고자 하는 쪽도 서버를 신뢰해야 한다. 인증 서버는 우리의 신원을 안전한 형식으로 보증해주며, 우리가 인증을 하는 쪽은 이 정보를 통해 인증 서버가 우리의 신원을 보증해줌을 확인한다. 우리가 통신을 하고자 하는 쪽도 해당 인증 서버를 신뢰하므로, 이는 해당 서버에서 보증해주는 우리의 신원도 신뢰한다.

어떻게 말하면, 인증서와 CA는 이런 인증 서버의 오프라인 버전이라고도 할 수 있다. 온라인 버전은 CA와 같은 오프라인 버전들에 비해 보안 컨디션 변화에 더 잘 반응한다. 오래 되어 쓸 수 없는 인증서는 삭제하기 어렵지만, 온라인 인증 서버는 그런 인증 정보들을 즉시 무효화할 수 있고, 그 변경 내용도 빠르게 반영할 수 있다.

7. Some Higher Level Tools

조금 더 높은 수준에서의 보안 프로토콜 등에 대해 알아보도록 하자. HTTPS와 SSH가 그 예다.

HTTPS

HTTP는 그 자체로는 보안 관련 기능들을 가지고 있지 않다. 하지만 요즈음에는 더 민감하고 가치 있는 정보들이 웹 상에서 돌아다니고 있기에, 이렇게 보호되지 않은 데이터들을 전송하는 것은 좋은 생각이 아니다. HTTP를 위한 새로운 보안 구현을 만들기 보다, HTTPS는 이미 있는 HTTP 프로토콜 정의를 이용하고, 이를 SSL/TLS에 연결시킨다. 한 번 SSL 연결이 만들어지면, 이후의 모든 클라이언트-서버 상호작용은 안전한 커넥션을 통해 이루어진다.

HTTPS는 특히 인증에 많은 신경을 썼는데, 사용자가 악의적인 웹 사이트와 통신하지 않을 것은 분명하기 때문이다. HTTPS는 이를 위해 인증서를 사용한다. HTTPS가 원래 웹 브라우저에서 쓰일 것으로 만들어졌기에, 필요한 인증서들은 브라우저에 의해 모이고 관리된다. 현대 브라우저들은 많은 CA들이 제공하는 공개 키들이 설정된 상태로 제공되고, 웹 사이트에서 제공되는 인증서는 이 미리 설정된 공개 키를 통해 그 진위를 확인한다. 하지만 인증서가 확인됐다는 것은 CA가 어떤 시점에 누군가의 공개 키에 대한 보증을 설 만하다고 판단했다는 것을 말할 뿐, 그가 좋은지, 나쁜지, 그의 개인 키가 여전히 노출되지 않고 비밀로 남아있는지, 혹은 CA가 여전히 보안상 안전한지 등에 대해서는 말해주지 않는다. HTTPS는 그저 인증에 대한 보증만 제공할 뿐, HTTPS를 사용한 인증된 사이트는 여전히 클라이언트에 대한 공격을 할 수 있다.

모든 웹 브라우저가 항상 HTTPS를 지원하는 것도 아닌데, 보통은 해당 웹 브라우저가 SSL을 설치하지 않았거나 이에 대한 설정을 하지 않았기 때문이다. 이런 경우 HTTPS를 사용하는 웹 사이트는 클라이언트와 상호 작용할 수 없게 된다. 클라이언트가 SSL 소켓 설정을 마치지 않았기 때문이다. 클라이언트가 HTTPS를 사용할 수 없다고 했을 때의 웹 사이트가 취하는 표준적인 해결법은 HTTP를 대신 사용하는 것이었다. 하지만 이렇게 되면 서버가 HTTPS를 전혀 사용하지 않을 때처럼 아무 보안 효과도 적용되지 않는다.

브라우저와 클라이언트 기기가 HTTPS를 더 많이 지원하게 되면서, 서버는 HTTPS를 사용하게 하고 HTTPS를 사용할 수 없다고 하는 클라이언트와의 상호 작용은 거부하게 만드는 경우가 많아졌다. 이러한 방식을 HSTS(HTTP Strict Transport Security)라 부른다. HSTS는 웹 사이트가 선택할 수 있는 옵션이다. 만약 웹 사이트가 HSTS를 지원하기로 결정한다면, 이 웹 사이트와의 모든 상호 작용은 암호학적으로 안전해지게 된다. HTTPS를 사용할 수 없는 클라이언트는 해당 웹 사이트와의 상호 작용을 할 수 없게 된다. 구글과 같은 많은 웹 사이트들이 HSTS를 사용하고 있지만, 2020년을 기준으로, 보편적이지는 않다.

HTTPS는 원래 안전한 웹 브라우징을 돕기 위해 만들어졌지만, 이는 다른 종류의 통신 보안을 위해서도 쓰인다. 어떤 개발자은 HTTP를 표준 웹 브라우징이 아닌 다른 목적으로 사용하기도 했는데, 그들에게는 통신을 안전하게 만들기 위해 HTTPS를 사용하는 것이 자연스럽고, 비용적으로도 낫다. 하지만 시스템 보안을 위해 HTTPS를 쓰는 것은 HTTP를 애플리케이션 프로토콜로 사용하기로 정한 경우에만 가능하고, HTTP는 원래 사람에 의한 활동을 지원하기 위해 만들어졌다. HTTP 메시지는 보통 ASCII로 인코딩되고 웹 브라우징에서 필요한 것들을 지원하기 위해 설계된, 상당히 큰 헤더를 포함한다. 웹 브라우저가 아닌 애플리케이션 보안을 위해서는 HTTPS보다 SSL이나, 아래의 SSH를 쓰는 게 훨씬 더 효율적일 수 있다.

SSH

SSH는 Secure Shell의 준말이다. 이는 Linux나 다른 Unix 시스템들, 그리고 Windows 시스템에서도 어느 정도 사용할 수 있다. SSH는 원래 안전한 원격 쉘을 목적으로 만들어졌지만, 이제는 컴퓨터들 간의 안전한 상호작용을 적용하기 위한, 더 일반적인 툴이 됐다. 이는 CLI에서 가장 흔히 쓰이지만, 여러 다른 안전한 원격 상호작용도 지원할 수 있다. 일반적으로 TCP 포트가 SSH를 통해 전달될 수 있고, 이는 원격 시스템 간 상호 작용을 보호하기 위한 강력한 방법을 제공한다.

SSH는 SSL에서와 같은 문제들을 많이 다루는데, 그 방식도 대부분 비슷하다. 원격 사용자는 인증되어야 하고, 공유 암호화 키 설정도 해야하며, 무결성 체크도 해야하는 등의 문제들이다. SSH는 보통 공개 키 암호화와 인증서를 통해 원격 서버를 인증한다. 클라이언트는 사용자 ID와 패스워드를 쓸 수 있는 경우, 보통 자기 자신의 인증서, 개인 키는 가지지 않는다. SSH는 인증서나 패스워드를 사용하지 않는 인증 방식, 예를 들면 인증 서버를 활용하는 방식도 제공한다. 많은 암호화 알고리즘들이 지원되며, 이렇게 지원되는 많은 것들 사이에 무엇을 쓸지를 결정하기 위해서는 클라이언트와 서버 사이의 협상도 있어야 한다.

SSH는 특히 중간자 공격(main in the middle, MITM)과 같은 네트워크 보안 취약점에 유용하다. 이러한 종류의 공격은 두 당사자가 서로 직접 통신하고 있다고 생각하지만, 사실은 아무도 모르는 악의적인 제 3자를 통해 통신을 하고 있는 경우에 발생한다. 이 제 3자는 모든 둘 사이에 전달되는 모든 메시지를 보거나 바꿀 수 있고, 새로운 메시지를 주입할 수도 있다.

잘 설계된 네트워크 보안 툴들은 많은 종류의 MITM 공격을 방지할 수 있지만, SSH와 같은 좋은 툴도 어떨 때는 그 공격을 당하기도 한다. 처음 SSH를 이용해, 이전에는 로그인해본 적 없는 원격 기기에 로그인 할 때, 우리는 해당 기기와 관련된 공개 키를 가지고 있지 않다. 그렇다면 이 키는 어떻게 얻을 수 있을까? 보통은 인증서 등을 통해서가 아니라, 원격 사이트에 직접 해당 공개 키를 보내달라고 요청해서 얻는다. 하지만 원격 기기에 처음으로 로그인하려 할 때, 이미 중간자가 기다리고 있다면 어떨까? 이 경우 중간자는 원격 사이트에서 보내주는 공개 키를 가로채고, 사용자에게는 자신의 공개 키를 건네줄 수 있다. 사용자는 이 공개 키가 원격 사이트의 키라고 생각하고 사용하겠지만, 이 키는 사실 공격자의 키이고, 공격자는 마치 자신이 원격 사이트인 양 행세할 수 있게 된다. SSH 설계자들도 이 취약점을 잘 알았기 때문에, SSH를 이렇게 사용하는 경우, 보안상 리스크가 있음에도 계속 사용할 것인지를 묻는 메시지가 나타나도록 했다.

profile
박가 영서라 합니다

1개의 댓글

comment-user-thumbnail
2024년 4월 22일

헉 OS 완주 축하드립니다 👏 이제 다음 시리즈 써주세요

답글 달기