요약

  • RFC 1446은 공유 키 기반 MD5 다이제스트로 SNMPv2 메시지를 인증한 뒤, 별도의 수명(lifetime) 검사를 통해 인증된 메시지가 계속 수용할 만큼 최근 것인지를 판단했습니다. 올바른 다이제스트는 필요조건이었지만 충분조건은 아니었습니다.
  • 파티 인증 시계는 동일한 개인 키가 사용되는 동안 감소하지 않아야 했습니다. 키를 바꾸지 않은 채 시계를 되돌리면 타임스탬프 구간이 다시 열리고, 캡처된 트래픽이 다시 수용 가능해질 수 있었습니다.
  • 따라서 복구는 에포크(epoch) 문제였습니다. 장애 전후로 정체성, 시계, 비밀을 유지하거나, 아니면 폐쇄적으로 실패하고 새로운 상태를 수립해야 합니다. RFC 3414는 이후 권위 엔진 ID, 부팅 카운터, 부팅별 타이머로 에포크를 표현하면서도 암호학적 유효성과 시의성의 구분은 그대로 유지했습니다.

다이제스트는 맞을 수 있지만 판단은 틀릴 수 있다

발신 파티의 인증 시계가 50,000을 가리킬 때 보낸 메시지를 생각해 봅시다. 수신자는 그 파티의 개인 인증 키를 알고 있고, 수명을 300초로 허용합니다. 수신자가 로컬에 기록한 발신 시계 기록이 50,300을 넘어서면, 캡처된 메시지의 재전송은 너무 오래된 것이 됩니다. 바이트는 여전히 기대한 다이제스트와 정확히 일치할 수 있습니다. 거부의 근거는 시간이지, 깨진 서명 검사가 아닙니다.

이제 수신자가 전원을 잃고, 동일한 키를 유지한 채 로컬 파티 시계를 49,900으로 복원했다고 상상해 봅시다. 50,000이라는 오래된 타임스탬프는 더 이상 창 밖에 있지 않습니다. 메시지가 새로워진 것도, 발신자가 다시 보낸 것도 아닙니다. 수신자가 그 메시지를 둘러싼 경계를 움직인 것입니다.

이것이 RFC 1446 안에 담긴 유난히 구체적인 교훈입니다. 암호학은 메시지를 비밀에 결합하고 변조를 드러낼 수 있지만, 재전송 저항은 수신자가 역사상 어디에 있는지를 말해주는 상태에도 의존합니다. 비밀이 연속적인 채로 그 상태가 되돌아가면, 공격자의 녹음 자료는 두 번째 유효 수명을 얻게 됩니다.

RFC는 시계를 완벽하다고 선언함으로써 이 문제를 해결하지 않았습니다. 대신 불변식을 규정했습니다. 파티의 인증 시계는 특정 개인 인증 키와 연관된 동안 감소해서는 안 된다는 것입니다. 관리자가 시계를 되돌린다면, 키도 동시에 바꿔야 합니다. 따라서 진짜 보안 객체는 타임스탬프나 비밀 그 자체가 아니라, 파티 정체성·키 세대·단조 시간으로 이루어진 에포크였습니다.

인증에는 두 개의 관문이 있었다

1993년 4월에 발표되고 현재는 Historic으로 분류된 RFC 1446은 SNMPv2의 인증 및 프라이버시 프로토콜을 정의했습니다. 다이제스트 프로파일은v2md5AuthProtocol을 사용하는 파티를 위해 16옥텟의 개인 인증 재료와 함께 MD5를 사용했습니다. 발신자는 비밀을 일시적으로 메시지의 다이제스트 필드에 놓고, 그 인증된 형태를 직렬화·해시한 뒤, 결과로 나온 128비트 값을 비밀 대신 전송했습니다.

수신자는 단순히 도착한 내용을 해시하지 않았습니다. 전송된 다이제스트를 제거하고, 로컬에 보유한 개인 키 사본으로 인증된 형태를 재구성한 뒤, 다이제스트를 계산해 두 값을 비교했습니다. 불일치는snmpStatsWrongDigestValues로 집계되었고, 프로토콜상 메시지는 인증되지 않은 것으로 처리되었습니다.

그러나 수신자는 또한 발신 파티의 인증 시계와 구성된 수명을 조회했습니다. 메시지가 실어 온 타임스탬프를 로컬 시계 기록과 비교한 것입니다. 요약하면 거부 조건은 다음과 같습니다.

authSrcTimestamp + lifetime < local authentication clock

이 조건이 성립하면 메시지는 허용 수명 밖에 있는 것이고,snmpStatsNotInLifetimes가 증가하며 처리 과정은 메시지를 인증되지 않은 것으로 거부했습니다. 다이제스트가 일치한다고 이 실패가 지워지지는 않았습니다. 공유 비밀 아래의 무결성과 주장된 발신지는 하나의 질문에 답했고, 시간적 수용 가능성은 또 다른 질문에 답했습니다.

이 구분은 증거 측면에서 중요합니다. 보존된 다이제스트 비교는 특정 바이트가 알려진 키 구성 아래에서 수신자가 규정한 무결성·발신지 검사를 통과했다는 주장을 뒷받침할 수 있습니다. 보존된 시계 비교는 그 바이트가 수신자의 허용 창 안팎에 있었다는 주장을 뒷받침할 수 있습니다. 어느 기록 하나만으로 메시지가 승인되었거나, 실행되었거나, 영속되었거나, 프로토콜 처리 이상의 무언가를 바꾸었다는 사실까지 증명되지는 않습니다.

“최근”은 행정적 수량이었다

인증된 각 메시지는 1초 단위의 발신·수신 인증 타임스탬프를 실었습니다. 수명은 네트워크에서 발견된 법칙이 아니었습니다. 허용되는 전달 지연에 대한 행정적 상한이었습니다. RFC 1446은 시계 정확도, 왕복 지연, 검증 빈도가 허용하는 한 가장 작게 설정할 것을 권고했습니다. 관대한 설정은 드리프트와 지연에 대한 운영 여유를 넓혔지만, 기록된 메시지가 여전히 유효할 수 있는 구간도 함께 넓혔습니다.

이 상충 관계는 “시계 스큐 허용치” 같은 친절한 라벨에 가려지기 쉽습니다. 실제로 수명은 위험 결정을 암호화한 것이었습니다. 관리자는 수신자가 가용성을 위해 어느 정도의 시간적 불확실성을 수용할지를 선택한 것입니다. 창이 넓어진다고 인증이 개선되지는 않았습니다. 신선도의 정밀도가 약해졌을 뿐입니다.

수명 안에 있다는 것만으로 고유성이나 순서가 증명되지도 않았습니다. 동일한 두 사본이 모두 시의적절할 수 있습니다. 상태를 바꾸려는 메시지에 대해 RFC는 후속 발신 전에 긍정 응답을 기다리거나 해당 구간이 만료되기를 기다릴 것을 권고했습니다. 이 경고는 인증과 신선도가 있어도 데이터그램 교환이 트랜잭션 로그가 되지는 않는다는 점을 인식한 것입니다.

메시지가 수명 및 다이제스트 검사를 통과한 뒤에는 접근 정책이 참조되었습니다. 어떤 접근이 허용된 경우에만 인증된 타임스탬프가 로컬에 저장된 파티 시계 개념을 선별적으로 앞당길 수 있었습니다. 이 순서는 누가 수신자에게 시간을 가르칠 수 있는지를 제한했지만, 단계들을 하나로 합치지는 않았습니다. 다이제스트 유효성, 수명 수용, 접근 판단, 프로토콜 동작은 서로 구별되는 사실로 남았습니다.

롤백 규칙이 키 에포크를 만들었다

시계가 되돌아갈 때 왜 새 키를 고집하는가? 공격자가 49,900부터 50,200까지의 구간 트래픽을 모두 녹음했다고 가정해 봅시다. 수신자는 이후 그 구간을 지나쳐 진행하므로 그 메시지들은 시간이 지나며 만료됩니다. 만약 운영자가 키를 그대로 둔 채 시계를 49,900으로 복원하면, 수신자는 다시 이전 다이제스트와 이전 타임스탬프를 모두 인식합니다. 이전 구간이 동일한 자격 증명으로 다시 열린 것입니다.

키를 바꾸면 그 결합이 깨집니다. 이전 메시지들은 다시 수치상 수용 가능한 타임스탬프를 가질 수 있지만, 새 비밀 아래에서는 다이제스트가 더 이상 검증되지 않습니다. 롤백과 키 교체는 하나의 상태 전이여야 합니다. 어느 한쪽만 단독으로 수행되면 이전 수용 관계의 절반이 그대로 남기 때문입니다.

RFC 1447은 이 규칙을 파티 MIB에 노출했습니다. 그partyAuthClock정의는 개인 인증 키가 동시에 변경되지 않는 한 값을 감소시켜서는 안 된다는 점을 반복했습니다.partyAuthLifetime은 초 단위의 허용 수명을 기록했습니다. MIB는 따라서 단순한 타이머가 아니라 시간과 비밀 상태 사이의 운영상 약속을 보이게 만들었습니다.

이 약속은 키 갱신 요청이 완료의 약한 증거에 불과한 이유도 설명합니다. 관리 스테이션은 새 값을 작성해 보낼 수 있습니다. 메시지는 전달될 수 있습니다. 피어는 그것을 채택할 수 있습니다. 다른 책임 관리자들이 알게 될 수 있습니다. 이전 값은 결국 퇴역할 수 있습니다. 이들은 서로 별개의 사건입니다. 교체 기간 동안 책임 스테이션은 전달이 확인될 때까지 이전 비밀과 새 비밀을 모두 보관해야 할 수 있고, 자신의 재부팅을 넘어서도 보관해야 할 수 있습니다. 감사 로그의 요청은 요청이 존재했다는 것만 증명합니다.

동기화는 의도적으로 약한 관찰에서 시작되었다

RFC 1446은 대략 동기화된 시계와, 시계 값과 비밀 배포를 조율하는 최소 한 대의 책임 관리 스테이션을 가정했습니다. 비밀이 바뀌지 않는 동안 평범한 동기화는 느린 시간 개념을 빠른 쪽으로 앞당기는 것이었습니다. 빠른 시계를 되돌려 조용히 역사를 다시 여는 일은 아니었습니다.

특히 계몽적인 예외 절차가 하나 있습니다. 자신의 시계가 에이전트와 일치하는지 알지 못하는 관리자는 인증되지 않은 시계 값 조회로 시작할 수 있었습니다. 그 관찰을 동기화 후보로 사용할 수 있었지만, 이어서 인증된 조회를 수행해 채택한 값을 검증해야 했습니다. 첫 번째 답은 신뢰할 수는 없지만 유용했습니다. 두 번째 답은 다른 종류의 증거를 제공했습니다.

이 두 단계 절차는 증거 위생의 초기 교훈입니다. 발견(discovery)은 피어가 어떤 값을 제시하고 있는지 운영자에게 알려줄 수 있습니다. 인증은 이후 교환을 공유 비밀 상태에 결합할 수 있습니다. 어느 쪽도 상대를 소급적으로 강하게 만들지는 않습니다. 인증되지 않은 후보와 인증된 확인을 별개의 기록으로 유지하면 신뢰가 프로세스 어디에 들어왔는지 정확히 드러납니다.

책임 관리자가 둘 이상이 되면 조율은 더 어려워졌습니다. 각자 파티의 시계나 키 세대에 대해 서로 다른 관점을 가질 수 있습니다. 한쪽에서 성공한 갱신이 다른 관리자를 이전 에포크에 남겨둘 수 있습니다. 프로토콜 문서가 불변식을 정의할 수는 있었지만, 누가 공유 보안 상태를 움직일 수 있는지, 동시에 존재하는 관리자들이 그 상태를 어떻게 조정하는지는 여전히 운영자가 다스려야 했습니다.

재부팅은 위협 모델의 일부였다

프로세스가 살아 있는 동안에만 작동하는 재전송 보호는 어플라이언스를 위한 재전송 보호가 아닙니다. 그래서 RFC 1446은 파티 정체성, 인증 시계, 개인 인증 키, 개인 프라이버시 키의 비휘발성이고 오염되지 않는 표현을 요구했습니다. 가능한 한 수명 상태에도 유사한 보호를 권고했습니다.

시계는 전원 상실 전후로 사실상 단조를 유지해야 했습니다. 장치는 배터리 지원 시계를 쓸 수 있습니다. 비휘발성 저장소에 값을 체크포인트로 저장하고, 재부팅 후 마지막 체크포인트 이후의 구간을 덮도록 보수적으로 앞으로 점프할 수도 있습니다. 구현 기법은 달라질 수 있지만 불변식은 변할 수 없었습니다.

관리 대상 에이전트가 파티 시계가 최대치에 도달할 때까지 다운되어 있다면, 시계는 거기서 멈춥니다. 그 시점에 보내져야 하는 유일한 인증된 관리 요청은 최소한 시계와 개인 인증 키를 변경하는 요청입니다. 최종값은 함부로 리셋해도 되는 번거로움이 아니라 현재 에포크의 고갈을 표시하는 것으로 취급되었습니다.

보호된 매개변수의 상실에는 똑같이 엄격한 대응이 요구되었습니다. 파티 보안 상태가 파괴되면 RFC는 무작위 대체 값을 요구하고, 통신이 재개되기 전에 수동 재배포를 강제했습니다. 추측으로 조용히 재구성하는 방식은 연속성을 발명함으로써 가용성을 지킬 것이었습니다. 이 설계는 검증 불가능한 보안 과거보다 명시적 중단을 선호했습니다.

에이전트의 재부팅을 감지한 책임 관리 스테이션은 타이머 하나 설정 이상의 복구 작업을 맡았습니다. 에이전트가 보존하지 않는 수명을 포함한 다른 파티 속성들을 복원해야 할 수 있습니다. 복구 절차는 인증된 복원 메시지가 수용되도록 타임스탬프를 인위적으로 앞당길 수 있었습니다. 그럼에도 프로토콜은 재부팅이 정상 운영 밖의 사건이라고 가장하지 않았습니다. 복구는 그 자체의 증거 요건을 가진 통제된 전이였습니다.

SNMPv3은 표현을 바꿨지만 경계는 바꾸지 않았다

RFC 3414의 사용자 기반 보안 모델은 이후 시의성을 권위 SNMP 엔진을 중심으로 조직했습니다.snmpEngineID가 엔진을 식별하고,snmpEngineBoots는 재부팅 또는 재초기화 횟수를 세며,snmpEngineTime은 현재 부팅 에포크 내의 초를 셉니다. 엔진 ID와 부팅 횟수는 비휘발성 저장소에 남아야 했습니다. 부팅별 타이머는 부팅 카운터가 증가한 후 0으로 돌아갈 수 있었습니다.

이 표현은 하나의 계속 흐르는 파티 시계가 정전을 넘어 살아남아야 할 필요를 없앴습니다. 부팅 카운터가 새 에포크를 이전 것과 구별 가능하게 만들기 때문에 시간이 다시 시작될 수 있었습니다. 권위 수신자는 부팅 횟수가 틀리거나 규정된 150초 창 밖의 시간을 가진 메시지를 거부했습니다.

이후 설계도 다이제스트를 신선도 신탁(oracle)으로 만들지는 않았습니다. 인증 재료와 시의성은 여전히 별도로 검사되었습니다. 또한 심각한 실패 모드도 유지되었습니다. 현재 부팅 횟수를 판단할 수 없으면 엔진은 카운터를 최대치에 고정하고, 수동 개입이 새 엔진 정체성이나 새 사용자 비밀을 수립하기 전까지 인증된 통신은 시의성 검사에서 실패합니다.

RFC 3414가 RFC 1446을 직접 대체한 것은 아닙니다. 두 문서 사이의 표준 계보에는 중간 설계들이 있었습니다. 이 비교는 건축학적입니다. 둘 다 재전송 방어 에포크를 명시적으로 만듭니다. RFC 1446은 파티 시계 롤백을 키 교체에 결합했습니다. RFC 3414는 리셋 가능한 타이머를 내구성 있는 부팅 카운터와 엔진 정체성에 결합했습니다. 두 경우 모두, 암호학적으로 유효한 메시지를 수용하려면 그 메시지가 수신자의 현재 역사에 속한다는 증거가 필요했습니다.

수식어가 아니라 조인을 보존하라

“인증됨”이라고만 쓰여 있는 운영 기록은 그 메커니즘에서 가장 중요한 경계들을 버린 것입니다. 유용한 기록은 파티 또는 권위 엔진, 키 세대, 시계 또는 부팅 에포크, 수용된 수명, 정확한 메시지 바이트, 다이제스트 판단, 타임스탬프 판단을 식별합니다. 그다음 접근 제어 결과, 프로토콜 응답, 외부 상태에 대한 독립 관찰을 각각 별도로 기록합니다.

이 조인들이 주장의 팽창을 막습니다. 일치하는 다이제스트는 승인이 아닙니다. 시의적절한 메시지가 반드시 고유한 것은 아닙니다. 키 변경 요청이 모든 피어가 새 키를 채택했다는 증거는 아닙니다. 스키마의 비휘발성 필드가 물리적 장치가 장애를 넘어 그것을 보존했다는 증거는 아닙니다. 성공적인 응답이 재시작 후 구성이 지속되었다는 증거는 아닙니다.

RFC 1446의 역사적 성과는 MD5나 DES의 수명이 아니었습니다. 어느 쪽도 현재의 권고로 제시되어서는 안 됩니다. 그 밑에 있는 더 날카로운 명제였습니다. 수신자가 자신이 어느 보안 에포크에 사는지 증명할 수 있는 동안에만 과거는 배제된다. 시간을 거슬러 돌린다면, 키가 그 여정을 불연속으로 만들어야 한다.

출처