요약

  • DNS는 ASCII 문자를 대소문자 구분 없이 비교하지만, 구현체는 수신한 대소문자 그대로 질의를 반환하는 경우가 많다. 2008년 DNS-0x20 제안은 이 정확한 에코를 일시적 트랜잭션 식별자로 활용하려 했다.
  • 대상 문자가 하나 늘어날 때마다 추측 비트를 하나씩 더할 수 있었지만, 보호 효과는 문자 수, 서버와 미들박스를 거치는 동안의 무변형 통과, 신중한 캐시 처리, 다운그레이드에 강한 폴백에 달려 있었다. DNS 데이터를 인증하지는 않았고 최종 RFC가 되지도 못했다.

하나의 이름, 두 가지 시험

리졸버가 문자들이 예측 불가능하게 대문자와 소문자를 오가는 이름을 전송한다고 상상해 보자. 권한 서버는 그 패턴을 이해할 필요가 없다. 조회 목적에서 대소문자가 섞인 질의와 모두 소문자인 질의는 같은 지점을 가리킨다. 그러나 응답이 돌아올 때 리졸버는 두 번째 시험을 부과할 수 있다. 질의 섹션이 자신이 보낸 패턴 그대로 돌아왔는가?

이는 모순된 규칙이 아니다. 서버는 데이터를 찾기 위해 의미적 동등성을 적용한다. 리졸버는 하나의 응답을 하나의 미결 요청에 대응시키기 위해 바이트 수준의 기억을 적용한다. 눈먼 위조자는 질의되는 이름을 알고 있어도, 그 질의가 이루어지기 전에는 존재하지 않았던 표현상의 선택을 여전히 추측해야 한다.

그 구분이 DNS-0x20이라 불린 제안의 핵심이다. 이 제안은 새로운 DNS 필드를 추가하지 않았다. 원래 프로토콜이 이미 이름 식별과 무관하다고 선언한 정보를 일시적으로 활용하려 했다.

오래된 사양은 좁은 틈을 남겼다

1987년에 발표된RFC 1035는 DNS 프로토콜의 비교가 대소문자를 구분하지 않는다고 명시한다. 대문자로 쓴 이름과 그렇게 쓰지 않은 같은 이름은 DNS 목적상 동일하다. 그러나 이 문서는 또한 가능한 한 원래 대소문자를 보존해야 하며, 대소문자 구분 데이터의 손실을 최소화해야 한다고 말한다.

이는 실용적 타협이었다. 대소문자는 네임스페이스를 병렬 객체로 안전하게 나눌 수 없었다. 사용자와 소프트웨어에는 하나의 안정된 이름이 필요했다. 동시에 운영자나 요청자가 제공한 철자를 보존하는 것은 유용한 표현상의 동작이었다. 식별성은 접혔지만 표현이 항상 지워진 것은 아니다.

RFC 4343은 이후 이 규칙을 좁혔다. 동등성은 ASCII A-Z와 a-z에 관한 것이며, 임의의 언어별 대소문자 변환을 적용하거나 DNS 와이어 비교를 IDNA 처리와 혼동할 수 있는 허가가 아니다. 이 해명은 또한 응답에서 반환되는 대소문자가 보장되지 않는다고 경고한다. 공유 저장소는 하나의 렌더링만 유지할 수 있고, 이름 압축은 출력 레이블이 메시지 다른 곳에서 표현을 빌려오게 만들 수 있다.

따라서 이 틈은 실재했지만 조건부였다. 대소문자는 RRset을 선택하지 않았고, 대소문자는 때때로 여정에서 살아남았다.

질의는 그 틈을 한 번만 쓸 수 있었다

2008년 3월 인터넷 드래프트Use of Bit 0x20 in DNS Labels는 질의 이름의 각 ASCII 문자에 대해 대소문자 비트를 무작위화할 것을 제안했다. 숫자 이름 0x20은 대문자와 소문자 ASCII 문자를 구분하는 비트에서 나온다. 응답자에게는 그 결과 나타난 모든 패턴이 동일한 DNS 이름이었다. 요청자에게는 각 패턴이 해당 질의가 유효한 동안 서로 다른 과제가 될 수 있었다.

이 제안은 흔한 응답 동작에 의존했다. 권한 서버는 일반적으로 질의 섹션을 요청에서 응답으로 그대로 복사했다. 드래프트 저자들은 그들이 시험한 구현체들이 이를 정확히 수행했다고 보고했지만, 당시 DNS 사양이 정확한 대소문자 복사를 요구하지는 않았다. 리졸버는 원래의 대소문자 혼합 질의를 기억하고, 반환된 질의와 비교하며, 트랜잭션 ID와 다른 필드가 맞아 보이더라도 대소문자 비트가 다른 응답을 폐기할 수 있었다.

이는 리졸버의 응답 매칭 상태에 또 하나의 좌표를 추가했다.RFC 5452는 위조 응답 방어를 미결 질의 튜플 전체로 설명한다. 질의, 식별자, 주소와 포트, 클래스와 타입이 모두 대응해야 한다. 완전히 무작위인 16비트 트랜잭션 ID조차 눈먼 추측에 유한한 목표를 제공하며, 예측 불가능한 출발 포트는 그 목표를 키울 수 있다. DNS-0x20은 이미 QNAME 안에 실려 있는 비트를 사용해 이를 다시 키우려 했다.

이는 대체가 아니라 추가였다. 대소문자를 무작위화하면서도 예측 가능한 식별자와 포트를 쓰는 리졸버는 진정성을 얻지 못했다. 단지 경쟁의 산수를 바꾸었을 뿐이다.

모든 이름이 같은 예산을 지닌 것은 아니었다

추가 과제 공간은 대상 문자의 수에 비례했다. 각 ASCII 문자는 최대 한 개의 무작위 대소문자 비트를 나를 수 있었다. 숫자와 하이픈은 아무것도 제공하지 않았다. 여섯 문자로 된 짧은 이름은 여섯 개의 선택만 노출할 수 있었고, 문자가 많은 긴 이름은 더 많이 노출할 수 있었다.

이 비대칭이 중요한 이유는 이 메커니즘의 보안 주장이 의례적이지 않고 구체적이기 때문이다. 균일한 “0x20 활성화” 강도란 없다. 실효 기여도는 질의된 이름, 대소문자 선택이 실제로 예측 불가능한지, 응답 경로가 이를 보존하는지에 달려 있다. 살아남은 비트를 세지 않고 구성된 지원만 세는 것은 기능 플래그를 통제 수단으로 착각하는 일이다.

비ASCII 레이블이 예산을 단순히 배로 늘려 주지도 않는다. RFC 4343은 DNS의 ASCII 비교 규칙을 국제화 이름 변환과 구분해 둔다. 대문자와 소문자에 대한 로캘의 관념을 와이어 이름에 적용하면 이 메커니즘을 확장하는 것이 아니라 문제 자체를 바꾸게 된다.

정확한 에코는 우연한 의존이었다

만료된 드래프트는 2008년 시험에서 정확한 질의 복사가 거의 보편적이라고 서술했지만, 질의를 소문자로 정규화하는 구현체도 발견했다. 포워더, 검사 장비 또는 다른 중개자도 같은 일을 할 수 있다. 그런 구성 요소는 조회의 의미를 완벽히 보존하면서 질의별 과제는 파괴할 수 있다.

이는 시사하는 바가 큰 호환성 문제를 만든다. 의미적 계약은 그 응답이 여전히 올바른 이름에 관한 것일 수 있다고 말한다. 방어적 계약은 기억된 패턴이 사라졌으므로 그 응답을 쓸 수 없다고 말한다. 리졸버는 두 시험이 같은 의미라고 가정해서 이 충돌을 해결할 수 없다.

불일치는 또한 모호한 증거다. 눈먼 위조일 수도 있다. 대소문자를 접는 서버나 미들박스일 수도 있다. 소프트웨어 결함일 수도 있다. 제안은 불일치를 기록하고 다른 권한 주소를 시도할 것을 권고했다. 바뀐 대문자를 공격의 증거로 바꾸지는 않았다.

과제는 캐시에 닿기 전에 사라져야 했다

DNS-0x20에서 가장 교훈적인 부분은 무작위화가 아니라 정리 작업이다.

DNS 메시지는 압축 포인터를 사용한다. 응답, 권한, 추가 섹션의 이름들은 같은 레이블을 반복하는 대신 질의 섹션을 가리킬 수 있다. 리졸버가 무작위화된 질의를 검증한 뒤 메시지의 나머지를 압축 해제하거나 캐시할 때 그대로 두면, 임시 대소문자 패턴이 저장 데이터와 이후 응답으로 옮겨갈 수 있었다.

따라서 드래프트는 요청자에게 원래 질의를 기억하고, 검증 후 다른 섹션을 압축 해제하기 전에 복원하라고 지시했다. 일시적 트랜잭션 식별성은 지속 상태의 경계에서 제거되어야 했다. 그렇지 않으면 한 번의 교환을 위한 방어가 이후 여러 교환의 표현을 오염시키고 다른 검사까지 방해할 수 있었다.

이 요구 사항은 일반적인 시스템 규칙을 드러낸다. 표현상의 여유가 논스가 될 때, 시스템은 그것이 언제 논스이기를 멈추는지 정확히 말해야 한다. 삭제 없는 생성은 완전한 설계가 아니다.

폴백이 바로 그 이점을 지울 수 있었다

엄격한 검사는 과제를 보호하지만 대소문자를 접는 권한 서버가 도달 불가능해 보이게 만들 수 있다. 즉각적인 관대한 폴백은 가용성을 보호하지만 공격자에게 다운그레이드 가능성을 준다. 충분한 불일치를 일으켜 리졸버가 비트 검사를 멈추도록 유도하는 것이다.

드래프트는 더 비용이 큰 추론을 제안했다. 영역의 다른 권한 서버들을 시도한다. 모두 실패하면, 새 식별자와 다른 무작위 요소를 사용해, 가능하면 다른 서버 순서로, 그 순서를 반복한다. 반복된 응답이 다른 예측 불가능한 필드는 올바르게 에코하면서 대소문자는 일관되게 바꿀 때에야 대소문자 채널을 비호환으로 취급하는 것이 합리적일 것이다.

이는 공짜 해법이 아니었다. 재시도는 시간과 질의를 소모하며, 대소문자를 제거하는 서버는 몇 배의 트래픽을 받을 수 있었다. 무작위 생성은 또한 분석에 더 많은 출력을 노출한다. 따라서 이 통제는 위조 비용을 지연, 부하, 공격자 영향 하의 폴백 위험과 맞바꾸었다.

DNSSEC는 의도적으로 대소문자를 다른 방식으로 쓴다

DNSSEC는 그 경계를 가장 분명히 표시한다.RFC 4034는 서명과 검증을 위한 정규 RR 형식을 정의한다. 압축된 이름을 확장하고 관련 대문자 ASCII 문자를 소문자로 변환한다. 서명은 모든 검증자가 동일한 옥텟 시퀀스를 구성할 것을 요구하지, 요청자의 일시적 타이포그래피를 보존할 것을 요구하지 않는다.

따라서 DNS-0x20과 DNSSEC는 정반대 이유로 같은 문자를 건드릴 수 있다. 전자는 무작위 표현 패턴이 한 번의 왕복에서 살아남는 데 의존한다. 후자는 정규 데이터를 인증하기 위해 표현 차이를 제거한다. 추측 저항성은 출처 인증이 아니며, 올바른 에코는 RRset이 그 영역에 의해 승인되었음을 증명하지 않는다.

버려진 구분의 가치에 관한 제안

DNS-0x20 문서는 2008년 9월에 만료되었다. 이를 최종 DNS 표준으로 인용하거나 오늘날의 모든 경로가 이 기법을 지원한다는 증거로 인용해서는 안 된다. 그 역사적 가치는 다른 곳에 있다.

이 제안은 프로토콜이 무시하는 구분이 항상 비어 있지는 않다는 것을 보여주었다. 어떤 구분은 프로토콜의 동등성 규칙과 무관하면서도 일시적 로컬 상태로 유용할 수 있다. 그러나 그 가치를 뽑아내는 일은 의무를 만든다. 비트가 몇 개 존재하는지 측정하고, 모든 의존성을 검증하고, 캐시 전에 상태를 제거하고, 불일치와 공격을 구분하고, 호환성 폴백이 원격 스위치가 되는 것을 막아야 한다.

대문자가 권위가 된 것은 아니다. 한 번의 질의에서, 조건이 맞으면, 대문자는 보이지 않는 응답이 답해야 하는 질문이 되었다.

출처와 한계

이 글은RFC 1035,RFC 4343,RFC 5452,RFC 4034및 2008년 3월의DNS-0x20 인터넷 드래프트에 의존한다. 드래프트의 구현 관찰은 당시 저자들의 시험을 서술한 것이며, 이 출처들은 현재의 배포 비중, 제품 기본값 또는 보편적 호환성 비율을 확립하지 않는다.