요약

  • RFC 3078의 coherency count는 MPPE 패킷의 유실이나 순서 뒤바뀜을 드러낼 수 있었다. 그러나 잃어버린 암호문을 복구하거나, 다음 패킷이 복호화 가능함을 증명하거나, 도달하지 못한 응용 데이터를 되찾아 줄 수는 없었다.
  • Stateless 모드는 카운트 공백을 넘어 키 상태를 전진시킬 수 있었다. Stateful 모드는 대신 수신자가 트래픽을 폐기하고 CCP Reset-Request를 보낸 뒤 송신자의 FLUSHED 패킷을 기다려야만 암호 테이블이 다시 동기화된 것으로 취급하도록 요구했다.

공백을 드러낸 패킷 자체도 쓸 수 없었다

이전 패킷이 사라진 뒤 수신되는 첫 MPPE 패킷을 생각해 보자. 그 패킷의 헤더에는 수신자의 기대값과 맞지 않는 coherency count가 실려 있다. 이 카운트가 유용한 이유는 바로 결핍을 보이게 만들기 때문이다. 그러나 RFC 3078의 stateful 모드에서는, 새로 도착한 패킷이 수신자가 한 번도 보지 못한 키 변경 경계를 지난 뒤 암호화되었을 수 있다. 수신자는 시퀀스가 끊어졌다는 사실은 알지만, 방금 도착한 패킷을 읽는 데 필요한 암호 상태는 더 이상 갖고 있지 않을 수 있다.

프로토콜의 답은 추측이 아니었다. 수신자는 그 패킷을 폐기하고, 데이터 없는 Compression Control Protocol Reset-Request를 보내며, 송신자가 FLUSHED 비트가 설정된 패킷을 보낼 때까지 이후 패킷들을 조용히 버려야 했다. 송신자는 요청을 받은 뒤 RC4 테이블을 재초기화하고 다음 패킷에 표시를 하여 수신자가 같은 작업을 할 수 있게 했다. Reset-Ack은 요구되지 않았다. 표시된 데이터 패킷 자체가 실질적인 경계였다.

이 작은 상태 기계에는 더 큰 역사적 교훈이 담겨 있다. 어떤 필드는 전환을 되돌리지 않고도 끊어진 전환을 진단할 수 있다. 리셋은 잃어버린 것을 회복하지 않으면서 계속할 수 있는 능력을 되찾아 줄 수 있다. 새로 동기화된 상태가 실재하는 동안, 중단된 응용은 이미 되돌릴 수 없는 공백을 겪었을 수 있다.

암호화는 여러 다른 결정들 이후에 시작되었다

RFC 3078은 2001년 3월에 Informational RFC로 발표되었다. 이 문서는 PPP 캡슐화 트래픽을 위한 Microsoft Point-to-Point Encryption을 기술하고, RFC 2118의 Microsoft Point-to-Point Compression과 공유하는 옵션 공간을 갱신하였다. 인터넷 표준(Internet Standard)이 되지는 못했다.

MPPE는 PPP의 Compression Control Protocol 옵션 18을 통해 협상되었다. 개시자는 자신이 지원하는 옵션들을 제시하는 것이 기대되었다. 응답자는 그 옵션 집합을 거부하면서 단 하나의 선호 암호화 선택을 제시할 수 있었는데, 보통은 양측이 제시한 가장 강한 선택, 즉 128, 56 또는 40비트였다. 별도의 비트는 stateless 동작을 요청했다. MPPE 협상이 시도되지 않았다면 기본값은 암호화 없음이었다. 시도되었으나 실패했다면, RFC 3078에 따르면 링크를 종료해야 했다.

이 구분들은 운영상으로 중요하다. 인증 성공은 암호화가 아니었다. 세션 키를 보유한 것은 열린 CCP 상태가 아니었다. 128비트 옵션이 제시되었다고 해서 128비트 모드가 선택된 것은 아니었다. 암호화를 요구하는 정책은 사용자 패킷이 협상이 끝나기를 기다렸다는 증거가 아니었다. RFC 3078은 어떤 MPPE 패킷도 전송되기 전에 PPP가 Network-Layer Protocol 단계에 도달하고 CCP가 Opened 상태에 이르도록 요구했다.

주변 문서들은 의도적으로 이 연쇄를 나누었다. RFC 2548은 RADIUS가 MPPE의 송신 키와 수신 키를 각각 전달할 수 있는 방법을 기술했다. RFC 3079는 인증 자료로부터 MPPE 키를 도출하는 방법을 기술했다. RFC 1962는 CCP 협상과 리셋 기능을 제공했다. RFC 1661은 PPP의 링크 단계를 제공했다. RFC 3078은 실시간 암호화 패킷 상태를 담당했다. 어느 한 계층의 단일 기록으로 다른 계층을 증명할 수는 없었다.

12비트는 페이로드가 아니라 위치를 기억했다

모든 MPPE 패킷은 12비트 coherency count를 실었다. 송신자는 패킷마다 이 값을 증가시키고 4095에서 0으로 되돌아가게 했다. 수신자는 관찰된 값과 자신이 보존해 온 상태를 비교했다. 이 필드는 순서와 유실 조건을 탐지하고 키 상태가 얼마나 전진해야 하는지를 판단하기 위한 간결한 수단을 제공했다.

그러나 카운터에는 사라진 패킷이 담겨 있지 않았다. 카운트가 변한 이유를 인증하지도 않았다. 패킷이 링크에서 사라졌는지, 큐에서 버려졌는지, 필터링되었는지, 순서가 바뀌어 도착했는지, 공격자가 변조했는지를 알려 주지도 않았다. 연속된 카운트를 가진 패킷들이 응용에 도달했음을 증명하지도 않았다. 이는 프로토콜 상태에 대한 관찰이었지, 종단 간 전달 수령증이 아니었다.

RFC 3078은 MPPE가 신뢰성 있는 링크를 요구하지 않으며, 단지 동기화를 위해 RFC 1663의 신뢰성 전송 메커니즘을 추가하는 것은 보통 이득이 되지 않는다고 말했다. 이 문장은 잘못 읽힐 수 있다. “신뢰성 있는 링크를 요구하지 않는다”는 것은 패킷 유실이 무해해지거나 사라진 데이터가 다시 나타난다는 뜻이 아니었다. 암호화 상태 기계가 유실에 대해 정의된 반응을 갖고 있다는 뜻이었다. 없는 데이터의 결과는 여전히 응용과 상위 계층 프로토콜이 감당했다.

MPPE를 통과하는 PPP 프로토콜은 특정 범위에 한정되었다. 다른 PPP 패킷은 원래 프로토콜 번호를 유지했다. encrypted-data 비트는 MPPE 페이로드가 암호화되어 있는지를 식별했지만, 그 비트는 암호학적 증명이 아니었다. 패킷 헤더 자체는 수신자 상태가 의존하는 제어 표면의 일부로 남아 있었다.

Stateless 모드는 되돌아오는 리셋을 피하기 위해 계산을 치렀다

Stateless 모드에서는 coherency count가 바뀔 때마다—보통 패킷마다—세션 키가 바뀌었다. 송신자는 암호화 전에 키를 전진시켰다. 수신자는 새 카운트를 관찰한 뒤, 복호화 전에 키를 전진시켰다. FLUSHED 비트는 모든 암호화 패킷에 설정되었다.

수신자가 마지막으로 카운트 2를 보고 다음에 카운트 5를 받았다면, 새 패킷을 복호화하려고 시도하기 전에 키 변경을 세 번 수행했다. 카운트 공백은 송신자의 키 진화가 얼마나 전진했는지를 알려 주었다. 모든 stateless 패킷이 재초기화 표시를 실고 있었기 때문에, 수신자가 단지 재동기화를 위해 CCP Reset-Request를 보낼 필요는 없었다.

이 메커니즘은 건너뛴 암호문 이후의 계속을 가능하게 했다. 그러나 카운트 3과 4를 복구해 주지는 않았다. 반복된 키 전진이 통상적인 유실 때문인지 조작된 헤더 때문인지를 증명하지도 않았다. 수신자는 손에 쥔 패킷에 대한 올바른 키를 되찾으면서도, 사라진 응용 콘텐츠에 대한 어떤 증거도 갖지 못할 수 있었다.

따라서 statelessness는 상태의 부재가 아니었다. 양쪽 피어 모두 여전히 시작 키, 카운트 이력, 결정적 키 변경 함수, 모드에 대한 합의를 필요로 했다. “stateless”는 복구를 수신하는 각 패킷 안으로 국소화했을 뿐, 공유된 계약을 폐지하지 않았다.

Stateful 모드는 역방향 경로를 복호화의 일부로 만들었다

Stateful 모드는 키를 덜 자주 바꾸었다. 송신자는 하위 카운트 옥텟이0xFF인 패킷 앞에서 키를 바꾸었고, 수신자는 같은 플래그 패킷을 받은 뒤, 복호화 전에 키를 바꾸었다. 그 특정 패킷이 유실되면, 송신자는 전진했지만 수신자는 그러지 못했다.

이후의 카운트가 불연속을 드러낼 수 있었다. 수신자는 기대된 키 변경을 수행했을 수 있지만, RFC 3078은 stateful 유실 이후에도 리셋 교환을 요구했다. 수신자는 그 공백을 드러낸 패킷을 폐기하고, Reset-Request를 보내며, FLUSHED가 도착할 때까지 트래픽을 버렸다. 송신자의 응답은 확인 개체가 아니었다. 행동의 변화, 즉 재초기화와 다음 패킷의 표시였다.

그리하여 역방향 제어 경로는 순방향 데이터 경로의 회복의 일부가 되었다. 송신자에서 수신자로 가는 암호화 패킷만 관찰한 감시자는 공백과 어쩌면 이후의 FLUSHED 표시를 탐지할 수 있지만, 수신자가 요청을 보냈는지, 송신자가 그 특정 요청에 따라 행동했는지를 증명할 수는 없었다. Reset-Request만 관찰한 감시자는 사용 가능한 표시된 패킷이 돌아왔음을 증명할 수 없었다. 양방향, 그 시점, 리셋 이후 처음으로 성공적으로 복호화된 페이로드가 모두 수령증에 들어가야 했다.

RFC 3078은 또한 stateful 재초기화가 두 패킷이 같은 키를 사용하게 만들 수 있다고 경고했다. 따라서 인터넷 위의 계층 2 터널과 같은 유실 환경에서는 stateful 모드를 피하라고 권했다. 이 경고는 모든 stateful 세션이 실패했다거나 stateless 모드가 RC4를 현대적으로 만들었다는 뜻이 아니었다. 유실, 리셋 동작, 키 재사용 사이의 특정 상호작용을 지목한 것이었다.

협상은 첫 보호된 바이트 이전에 변경될 수 있었다

보안 섹션은 또 하나의 경계를 상류에 놓았다. MPPE 협상은 무결성 보호를 받지 않았다. 능동적 공격자는 Supported Bits 필드를 수정하여 겉보기 강도를 바꿀 수 있었다. 구성이 그 영향을 제한할 수 있었다—예를 들어 받아들일 수 없는 모드를 거부하는 식으로—그러나 프로토콜 교환 자체가 자신의 선택을 인증하지는 않았다.

공격자는 coherency count를 바꾸어 피어들이 동기화를 잃게 만들거나, encrypted-data 비트를 반전시켜 서비스 거부 공격을 수행할 수도 있었다. 이 경고들은 헤더 관찰을 신뢰할 수 있는 감사 주장으로 격상시키는 것이 안전하지 않음을 보여 준다. 증거 연쇄에는 와이어에 무엇이 나타났는지와 구성된 각 피어가 무엇을 받아들였는지가 모두 필요하다.

역사적 정확성은 또한 사후적 승인을 경계할 것을 요구한다. RFC 3078은 RC4를 사용했고 40, 56, 128비트 변형을 기술했다. RFC 4345는 나중에 SSH를 위한 개선된 RC4 모드를 제안했는데, 이는 다른 프로토콜이자 다른 구성이다. 그 후속 작업은 “128비트”가 완전한 보안 평가가 아니라는 점을 상기시키는 데는 유용하다. 그러나 MPPE가 이전했거나, 계속 배포되었거나, 이후 메커니즘의 성질을 획득했다는 증거는 아니다.

바람직한 수령증은 전환의 연쇄이다

stateful MPPE 세션의 경우, 비밀을 노출하지 않으면서 인증 결과와 초기 키 자료의 출처를 보존하라. 방향별 키 식별, PPP 세션과 피어 식별, 모든 CCP 요청·거부·확인, 선택된 키 길이와 모드, CCP가 Opened에 이른 시점을 보존하라.

각 암호화 방향에 대해 구성 에포크, 기대·관찰된 coherency count, 랩 이벤트, FLUSHED 및 encrypted-data 비트, 카운트 공백, 플래그 패킷 경계, 폐기된 암호문, Reset-Request의 송신과 수신, 대기 중 폐기된 패킷, 테이블 재초기화, 회복 이후 처음으로 성공적으로 복호화된 패킷을 보존하라. 암호 너머로 계속하라: 상위 계층 프로토콜, 응용 시퀀스 또는 확인, 그리고 서비스가 실제로 약속한 결과를 기록하라.

이것은 Lu Heng의 현실 계층 훈련을 하나의 간결한 암호화 프로토콜에 적용한 것이다. 자격 증명 수용, 키 도출, 키 전달, 옵션 협상, 패킷 수신, 유실 관찰, 동기화된 암호 상태, 평문 회복, 응용 전달은 동의어가 아니다. 실행 중인 코드는 그 전환이 실제로 일어나고 증거를 남길 때에만 이들을 연결한다.

coherency count는 정직한 역할을 했다. 그것은 불연속의 이름을 붙였다. 그 역사적 중요성은 작은 필드에 할 수 있는 것 이상을 부탁하기를 거부한 데 있다.

출처