요약

  • RFC 2231의 연속 조각은 0부터 시작해 빠짐없이 번호가 매겨지며, 문자 집합과 언어의 선택적 선언은 인코딩된 첫 조각의 시작에만 나타난다. 조합을 결정하는 것은 번호 순서이지 헤더에서 매개변수의 위치가 아니다.
  • 형식이 올바른filename조차 Content-Disposition에서는 제안에 불과하다. RFC 2183은 수신 측에 경로 제거, 파일 덮어쓰기와 위험한 대상 방지, 그리고 사용자의 명시적 동작 없이는 콘텐츠 실행 금지를 요구한다.

번호가 곧 순서다

설명을 위한 가상의 예시로, 역사적 메시지에서 가져온 것이 아니라고 가정하고, 다음과 같은 헤더가 있다고 해 보자.

filename*0*=utf-8'en'Quarterly%20; filename*1*=review%20; filename*2=final.pdf

이것은 세 개의 이름이 아니다. 조각 0은 UTF-8과 선택적 언어를 선언하며 값을 시작하고, 조각 1은 퍼센트 표기로 표현된 바이트로 이어 받으며, 조각 2는 인코딩 표기 없이 값을 마무리한다. 문자열이 완전하고 모호하지 않다면 논리적 결과는Quarterly review final.pdf이다.

수신 측은 등장 순서에 의존해서는 안 된다. MIME 매개변수의 순서는 자체적으로 의미를 갖지 않으며,*2가*0보다 먼저 도착할 수 있다. 그래서 RFC 2231은 0부터 시작해 하나씩 증가하며, 누락된 번호나 앞에 붙은 0도 없어야 한다고 요구한다. 구현 측은 같은 기저 이름을 가진 조각을 모으고, 모호한 중복을 감지한 뒤, 숫자 접미사에 따라 정렬해야 한다.

그리고 연결하기 전에 각 조각을 독립적으로 디코딩하는 것도 또 하나의 오류이다. 문자 집합과 언어는 시작에서 단 한 번 선언된다. 조각 경계는 전송 경계일 뿐, 반드시 문자 경계는 아니다. UTF-8 문자의 바이트가 두 조각에 걸쳐 나뉠 수 있으며, 이 경우 별도 디코딩은 대체 문자를 만들어 내거나 두 프로그램이 같은 메시지에 대해 서로 다른 이름을 표시하게 만든다.

안전한 작업 순서는 질문을 분리한다. 매개변수 이름 해석, 단일 연속 문자열 확인, 번호에 따른 페이로드 조합, 퍼센트 인코딩의 바이트 변환, 한 번 선언된 문자 집합 해석, 그리고 그 결과 텍스트를 콘텐츠 취급과 분리된 정책에 전달하는 것. RFC 2231의 보안 절은 간결하지만, 서두의 문법 규칙과 단일 선언 규칙이 이 실용적 경계를 강제한다.

복원은 저장 권한을 부여하지 않는다

RFC 2231은 값의 표현 방식을 확장했을 뿐, 원격 발신자에게 파일 시스템에 대한 명령권을 부여하지 않았다. Content-Disposition을 정의한 RFC 2183은 명확했다.filename은 메시지 본문의 개별 부분을 저장하기 위한 제안된 이름이다.

메일 클라이언트가 이를 함부로 사용해서는 안 된다. 디렉터리 정보는 무시되고 마지막 구성 요소만 후보로 남는다. 기존 파일 덮어쓰기, 시스템 위치나 부팅 위치 접근, 특수 파일이나 파이프 이름 사용, 실행 파일을 검색 경로에 두는 일에 경계해야 한다. 단순 저장만으로 사용자의 명시적 개입 없이 실행이 이루어져서도 안 된다.

형식이 올바른 UTF-8 값은../, 절대 경로, 제어 문자, 양방향 표시 문자, 예약된 이름, 기만적인 확장자를 담을 수 있다. 퍼센트 디코딩은 살균이 아니다. 문자 집합이 유효하다고 발신자의 신원이 증명되지 않는다. 이름이 Content-Type과 일치한다고 바이트의 무결성이 증명되지 않는다. 어느 것도 대체, 열기, 실행 또는 콘텐츠의 귀속을 허가하지 않는다.

그래서 게이트는 독립적으로 유지된다. MIME 파서는 조각 구조의 완결성을 결정한다. 디코더는 바이트가 나타내는 텍스트를 결정한다. 로컬 정책은 안전한 이름을 만든다. 저장 계층은 한정된 대상을 선택하고 충돌을 처리한다. 사용자 또는 별도로 권한을 위임받은 정책이 열기나 실행을 결정한다. 한 게이트의 성공이 다음 게이트의 승인을 대신하지 않는다.

저작 경계는 추측으로 합쳐지지 않는다

RFC 2231에는 Ned Freed와 Keith Moore의 이름이 있다. 그리고 그 전신인 RFC 2184에도 같은 두 사람의 이름이 있다. 이것이 이 메커니즘의 공동 저작 경계이다.

Patrik Fältström은 인터넷 국제화 역사에서 중요한 역할을 했지만, RFC 2231이나 RFC 2184의 저자가 아니다. 한편 레거시 IDNA 형식을 다룬 RFC 3490은 Fältström을 Paul Hoffman, Adam Costello와 함께 저자로 명시한다. 인접한 작업들을 하나의 저작 관계로 묶으면 출처가 훼손된다. 주제는 가까울 수 있지만 문서, 저자, 합의의 범위는 별개로 남는다.

IETF Datatracker는 Freed의 메일과 미디어 타입에 걸친 광범위한 경력을 기록하고 있다. Nathaniel Borenstein은 추모 글에서 Freed가 더 풍부한 메일에 대한 열망이 어떻게 견고성과 상호 운용성에 대한 그의 집중과 만났는지를 이야기한다. RFC 2045는 MIME 본문을 규정하고, RFC 2047은 헤더의 비 ASCII 텍스트를 다루며, RFC 2231은 매개변수 값이라는 더 좁은 문제를 해결한다.

이러한 좁힘은 결함이 아니라 보호 장치이다. 필드 이름에 별표가 있다고 해서 자동으로 RFC 2231 의미가 부여되는 것은 아니다. 해당 사양이 명시적으로 그 규칙을 채택해야 한다. 마찬가지로 국제 이름의 전송은 그것을 신원 주장으로 바꾸지 않는다.

HTTP는 인코딩은 가져가고 연속은 남겼다

RFC 8187은 HTTP에서 인코딩된 매개변수와 유사한 형식을 사용하고 UTF-8 지원을 강제했지만, HTTP가 필요로 하지 않았기 때문에 연속 조각은 제외했다. 기술적 계보는 남았고, 계약은 의도적으로 축소되었다.

RFC 6266은 HTTP의 Content-Disposition에서 같은 경계를 반복한다. 파일 이름은 참고용이다. 수신 측은 경로 구성 요소를 제거하고, 디렉터리를 통제하고, 위험한 확장자와 제어 문자, 특수 이름을 처리한다. 서버는 이름을 제안할 수 있지만 클라이언트의 파일에 대한 권한을 얻을 수는 없다.

RFC 2231의 유산은 이중의 정밀함이다. 상호 운용성에는 연속된 번호 매기기, 단일 초기 선언, 결정적 조합과 디코딩 순서가 필요하다. 그리고 보안에는 결과가 증명하지 않는 것을 동일하게 정확히 식별하는 정밀함이 필요하다. 문자열은 완전하게 복원될 수 있으며, 그럼에도 여전히 신뢰할 수 없다.

출처