요약
- RFC 3112는 비밀번호에서 파생된 값을 스킴(scheme), 스킴 정보, 인증 값으로 인코딩했습니다. 그 일치 규칙은
TRUE,FALSE,Undefined를 답할 수 있었지만, 이 답은 비교 결과를 설명했을 뿐 인증된 LDAP 연관을 뜻하지 않았습니다. - RFC는 인증에는 Bind를 사용할 것을 명시적으로 요구했습니다. 또한 여러 저장 값을 허용했기 때문에, 수용 가능한 비밀 하나를 추가한 작성자가 사용자의 기존 비밀번호를 비활성화하지 않고도 두 번째 접근 경로를 만들 수 있었습니다.
잘못된 상태 머신 안의 참(true) 답
LDAP 클라이언트가 일치 규칙에 비밀번호를 제출합니다. 서버는 저장된 값을 선택하고 그 스킴과 솔트를 읽어 기대되는 결과를 도출한 뒤TRUE를 반환합니다. 비밀은 일치했습니다. 그러나 클라이언트는 아직 인증되지 않았습니다.
이 겉보기 모순이 RFC 3112에서 가장 중요한 문장입니다. 2001년 5월 Informational 문서로 공개된 LDAP Authentication Password 는 당시 LDAP 명세들이 전제하던userPassword형식에 실제 비밀번호를 그대로 두는 대신, 구조화된 대안을 만들었습니다. 이 문서는 저장 값, 일치 규칙, 기능 속성, 보조 객체 클래스를 정의했습니다. 그리고 나서 비밀번호 검증을 편리하게 만든 뒤, Compare든 Search든 성공한 검증을 접근 획득의 충분 조건으로 다루지 말라고 클라이언트에 지시했습니다. Bind 연산은 여전히 사용되어야 했습니다.
두 프로토콜 머신이 서로 다른 두 질문에 답했던 것입니다. 일치 규칙은 선언된 스킴 아래에서 하나의 주장된 문자열이 최소 하나의 저장된 인증 값과 일치하는지를 답했습니다. Bind는 서버가 이 LDAP 연관에 대한 인증 교환을 수용하는지를 답했습니다. 이후의 접근 제어는 그 결과로 나온 권한 부여 신원이 무엇을 할 수 있는지를 답했습니다. 디렉터리 너머의 애플리케이션은 여전히 요청된 업무 동작의 성공 여부를 스스로 판단해야 했습니다.
이 전환들을 하나의 "로그인 성공" 이벤트로 압축하면 근거는 사용할 수 없게 됩니다. Bind 없이도 일치가 기록될 수 있습니다. Bind가 성공하면서 하나의 연산은 여전히 금지될 수 있습니다. 디렉터리 읽기가 허용된 뒤 애플리케이션 트랜잭션이 실패할 수 있습니다. RFC 3112가 중요한 이유는 이 봉합선들을 가시적으로 남겨 두었기 때문입니다.
저장된 값은 자신의 방식을 담고 있었다
이 스키마는 각 값을 달러 기호로 구분된 세 개의 대소문자 구분 구성 요소, 즉scheme,authInfo,authValue로 표현했습니다. 스킴은 방식의 이름이었습니다. 정보 필드에는 보통 base64로 인코딩된 솔트가 들어갔습니다. 마지막 필드에는 보통 비밀번호에서 파생되어 base64로 인코딩된 자료가 들어갔습니다.
이 자기 서술은 실제 운영 문제를 다루었습니다. 디렉터리에는 서로 다른 메커니즘이 만든 값들이 담길 수 있었고, 서버는 자신이 이해하는 메커니즘을 말할 수 있었습니다. RFC 3112는MD5와SHA1을 정의했고, 비공개 또는 구현 고유 메커니즘은X-접두사나 할당된 객체 식별자를 사용하도록 했습니다. 루트 DSE는supportedAuthPasswordSchemes를 노출할 수 있어, 클라이언트나 운영자가 서버가 지원한다고 주장하는 스킴 이름을 알아볼 수 있었습니다.
그러나 표현이 명시적이었다고 해서 곧바로 정책이 되는 것은 아니었습니다. 루트 DSE 광고는 인증 절차가 어느 스킴을 선택했는지, 어느 항목에 어느 값이 들어 있는지, 솔트가 고유한지, 그 값이 권한 있는 주체가 기록한 것인지, 연산이 보호된 채널로 감싸져 있는지를 증명하지 않았습니다. 지원은 기능에 대한 증거이지 실행 흔적이 아니었습니다.
이 구분은 뒤돌아보면 더 선명합니다. RFC 3112의 MD5와 SHA-1 스킴은 비밀번호와 솔트를 이어 붙여 다이제스트했습니다. 솔트는 최소 64비트여야 했고, 구현은 최대 128비트 솔트를 수용해야 했습니다. 이것은 그 문서의 역사적 정의였습니다. 이것은 오늘날의 비밀번호 저장 권고가 아닙니다. 이후의 작업은 반복 횟수와 파생 비용을 명시적으로 다루었고, RFC 9106은 메모리 하드 Argon2 함수를 규정하며 비밀번호 해싱과 비밀번호 기반 키 파생에는 Argon2id를 우선했습니다. 이후 표준들이 2001년 기록을 다시 쓰는 것은 아닙니다. 스킴 이름과 그 매개변수를 "안전하게 해시됨"이라는 어법으로 바꿔 말하지 않고 그대로 보존해야 하는 이유를 보여줄 뿐입니다.
동등성, 비밀번호 검증, 인증은 별개였다
RFC 3112는 이름이 비슷해 서로 다른 증거적 역할을 감추는 두 가지 일치 규칙을 정의했습니다.authPasswordExactMatch는 인코딩된 세 구성 요소를 비교했습니다. 저장된 값 하나가 주장된 구조화된 값과 동일한 스킴, 정보, 인증 값을 갖고 있으면 참을 반환했습니다. 이것은 표현 사이의 동등성이었습니다.
authPasswordMatch는 확장 일치 필터를 통해 주장된 비밀번호를 받았습니다. 서버는 각 저장 값의 스킴을 적용해 하나 이상의 값이 일치하면 참, 테스트된 모든 값이 실패하면 거짓, 비교를 완료할 수 없으면 미정(undefined)을 반환했습니다. 이것은 저장된 지침 아래에서 주장된 비밀을 검증하는 것이었습니다.
어느 답도 키보드 앞의 사람의 신원을 설명하지 않았습니다. 참 결과는 채널을 누가 통제하는지, 요청자가 그 값을 검증할 자격이 있는지를 보여주지 않았습니다. 거짓은 항목이 의도된 사람을 가리키는지, 올바른 스킴이 선택되었는지, 다른 인증 저장소가 존재하는지를 말하지 않았습니다. 미정은 전혀 잘못된 비밀번호의 증거가 아니었습니다. 미정은 부정적 비교와 판단 불능 사이의 구분을 보존한 것입니다.
프로토콜이 Bind를 고집한 덕분에 이런 불확실성이 조용히 더 큰 권위를 얻는 일은 막혔습니다. LDAP Bind는 연관에 대한 상태 전이를 제공합니다. RFC 4511은 이후 성공한 Bind 응답을 인증 결과로 기술했고, RFC 4513은 다음 구분을 명시했습니다. 접근 결정에 사용되는 권한 부여 신원은 인증 신원에서 도출될 수도 있고, 적절한 메커니즘을 통해 서버가 클라이언트가 채택하도록 허용하는 별도로 주장된 신원일 수도 있습니다.
따라서 Bind 성공조차 보편적 허가는 아니었습니다. 인증은 이 연관에 대해 서버가 누구를 수용했는지를 답했습니다. 권한 부여는 그 신원이 이 연산을 통해 이 객체에 무엇을 할 수 있는지를 답했습니다. LDAP을 사용하는 업무 서비스는 여전히 자기 동작을 소유했습니다. 비밀번호 일치는 그 사슬의 시작에 있었지 끝에 있지 않았습니다.
여러 값은 여러 가능한 문을 의미했다
authPassword는 여러 값을 가질 수 있었습니다. 선택된 스킴 또는 스킴 집합에 대해 RFC 3112는 서버가 관련된 모든 값을 사용하고 하나라도 일치하면 주장된 비밀번호를 유효한 것으로 간주하도록 권고했습니다. 이것은 저장 방식 간 전환, 겹치는 자격 증명, 관리 정책을 지원할 수 있었습니다. 동시에 기록 이력을 보안상 핵심적인 것으로 만들었습니다.
RFC는 이 공격을 정면으로 명명했습니다. 쓰기 권한을 얻은 누군가는 사용자의 진짜 비밀번호를 비활성화하지 않고도 추가 값을 저장할 수 있었습니다. 피해자는 평소처럼 로그인할 수 있었습니다. 단순한 가용성 점검은 잠김도 재설정도 보여주지 않았습니다. 추가 자격 증명은 조용한 두 번째 문으로 남을 수 있었습니다.
최종 항목 스냅숏은 그 사건을 재구성할 수 없습니다. 두 값이 존재한다는 것은 보여주지만, 누가 각 값을 추가했는지, 어느 정책이 승인했는지, 비밀번호 변경 연산이 그 값을 만들어냈는지, 어떤 값이 교체되었는지, 서버가 언제부터 그 값을 수용했는지는 보여주지 않습니다. 따라서 근거는 변경 이력을 따라가야 합니다. 추가, 교체, 삭제, 작성자 신원, 권한 부여 결과, 값 지문, 스킴, 매개변수 출처, 복제, 폐기.
RFC 3062는 이미 LDAP Password Modify 확장 연산을 정의하고 있었습니다. 이 연산은 서버가 통제된 규칙 아래 대상을 식별하고, 새 비밀번호를 수용하거나 생성하며, 일반적인 가시 속성 쓰기를 비밀번호 수명 주기 전체로 취급하지 않고 저장 메커니즘을 선택하도록 허용했습니다. RFC 3112는 그런 메커니즘과 함께 사용될 수 있었지만, 저장 필드를 완전한 계정 통제 시스템으로 바꾸지는 않았습니다.
서버는authPassword를userPassword나 외부 비밀번호 저장소와 결합할 수도 있었습니다. 따라서 하나의 속성을 관찰하는 것으로 전체 결정 집합이 확립되지 않았습니다. 하나의 일치 값이 선택된 경로에는 충분할 수 있습니다. 그 부재가 실패를 설명하기에 충분하지 않을 수 있습니다. 그 제거가 다른 모든 경로를 철회하지 않을 수 있습니다.
파생된 비밀도 여전히 비밀처럼 행동했다
RFC 3112는 일방향 파생이 디렉터리 값을 공개해도 안전하게 만든다는 안심되는 생각을 거부했습니다. 파생 값을 평문 비밀번호처럼 보호하라고 권고했습니다. 알고리즘 결함, 구현 오류, 오프라인 공격은 노출을 접근으로 바꿀 수 있었습니다. 기밀 전송을 보장하는 수단이 없다면 값의 전송은 강하게 만류되었습니다.
같은 경고는authPasswordMatch를 통해 전송되는 주장된 비밀번호에도 적용되었습니다. 일치 규칙은 온라인 추측을 서버까지 실어 날랐습니다. 보호되지 않은 채널로 노출하면 비밀번호가 유출될 수 있었습니다. 연산을 너무 자유롭게 노출하면 비밀번호 오라클이 만들어질 수 있었습니다. RFC는 서버에 그런 공격에 대한 대책을 지시했습니다.
연산 비용은 두 번째 통제 문제를 더했습니다. 일부 스킴은 상당한 CPU를 소모할 수 있습니다. 그 비용은 추측을 더 비싸게 만들 수 있지만, 신뢰할 수 없는 클라이언트가 서버의 자원을 소모하게 할 수도 있습니다. 속도 제한, 동시성 예산, 타임아웃, 비교에 대한 인증된 접근은 그 메커니즘의 운영적 의미에 속합니다. 암호학적으로 더 강한 스킴도 가용성 실패와 함께 배포될 수 있습니다.
이것이supportedAuthPasswordSchemes가 그토록 좁은 증거로 남은 이유입니다. 서버는 비싸거나 현대적인 스킴을 광고하면서도 어느 항목에는 다른 것을 선택하고, 겹치는 오래된 값을 수용하고, 비교를 너무 넓게 노출하거나 채널을 보호하지 못할 수 있습니다. 증명에 필요한 것은 정확한 요청, 선택된 값, 서버 결정, 채널 상태, 그 결과로 나온 Bind였지 기능 라벨이 아니었습니다.
오래된userPassword이야기도 변했다
RFC 3112는userPassword가 단순 Bind용으로 쓰이고 실제 비밀번호가 담기리 기대되던 1997년 LDAP 모델과 비교하며authPassword를 제시했습니다. 이 역사적 대조를 시대를 초월한 규칙으로 평탄화해서는 안 됩니다. RFC 4519는 이후 사용자 애플리케이션 스키마를 개정하며userPassword값이 반드시 평문이거나 Bind에서 사용 가능할 필요는 없다고 말했습니다. 구현과 배포는 저마다의 태그 형식과 저장 동작을 발전시켰습니다.
이 변화가 RFC 3112를 무의미하게 만드는 것은 아닙니다. 오히려 이 에피소드를 더 정밀하게 만듭니다. 이 문서는 표현, 인증, 디렉터리 스키마가 아직 분리되고 있던 시점에 비밀번호 파생 데이터에 명시적 문법과 LDAP 일치 의미론을 부여하려는 시도 중 하나였습니다. 그 지속적인 기여는 MD5나 SHA-1 구성이 아닙니다. 저장 형식, 일치 기능, 세션 인증이 하나의 주장으로 무너지도록 두지 않겠다는 거부입니다.
상태도 중요합니다. RFC 3112는 Informational이었습니다. RFC Editor 기록과 IETF Datatracker는 그 공개와 이력을 확립하지, 보편적인 구현을 확립하지 않습니다. RFC 2251, RFC 2252, RFC 2256은 그것이 다룬 프로토콜과 스키마의 맥락을 확립합니다. RFC 2829와 RFC 4513은 비밀번호 인증을 더 넓은 보안 모델 안에 위치시킵니다. RFC 4511, RFC 4517, RFC 4519는 이후의 프로토콜, 일치, 스키마 계보를 보여줍니다. 그 어느 기록도 특정 디렉터리가 이 스키마를 실제로 활성화했다는 것을 증명하지 않습니다.
신뢰할 수 있는 기록이 분리해 두어야 할 것들
어떤 사고 보고서가 이렇게 말한다고 가정해 봅시다. "비밀번호 해시가 일치했으므로 사용자가 로그인했다." RFC 3112는 이 문장을 해체하기 위한 점검 목록을 제공합니다.
먼저 디렉터리 항목을 식별하고 스킴 이름, 솔트 및 기타 스킴 정보, 생성 이력을 포함한 정확한 저장 값을 보존합니다. 다음으로 Compare 또는 Search 요청, 주장된 값이 담긴 보호 채널의 상태, 검증을 허용한 접근 제어 결정,Undefined를 포함한 결과, 실제로 평가된 값과 스킴을 보존합니다. 그다음 Bind 요청과 응답, 선택된 인증 메커니즘, 그것이 발생한 연관, 결과로 나온 인증 신원과 권한 부여 신원을 보존합니다. 마지막으로 요청된 디렉터리 연산, 그 접근 제어 결과, 다운스트림 애플리케이션의 응답을 보존합니다.
각 기록에는 서로 다른 관리자가 있습니다. 스키마 작성자는 표현을 정의합니다. 서버 운영자는 지원되는 스킴과 선택된 스킴, 비교 노출, 자원 한도를 결정합니다. 권한 있는 디렉터리 작성자가 자격 증명 값을 만듭니다. 인증 메커니즘이 연관 상태를 확립합니다. 접근 제어 정책이 연산을 허가합니다. 애플리케이션이 업무 결과를 소유합니다. 어떤 단일 성공 비트도 이 사슬을 대신할 수 없습니다.
RFC 3112의 일치 규칙은 비밀이 저장된 값과 일치한다고 올바르게 답할 수 있었습니다. 그 역사적 정교함은 그 답이 어디서 멈춰야 하는지를 아는 것이었습니다. 비밀번호는 일치했습니다. 디렉터리가 그 연관을 인증했다고 말할 수 있는 것은 Bind뿐이었고, Bind조차 다음 정책이 처음부터 부여하지 않은 권위를 쓸 수 없었습니다.
출처
- https://www.rfc-editor.org/rfc/rfc3112.html
- https://www.rfc-editor.org/info/rfc3112
- https://datatracker.ietf.org/doc/rfc3112/
- https://www.rfc-editor.org/rfc/rfc2251.html
- https://www.rfc-editor.org/rfc/rfc2252.html
- https://www.rfc-editor.org/rfc/rfc2256.html
- https://www.rfc-editor.org/rfc/rfc2829.html
- https://www.rfc-editor.org/rfc/rfc3062.html
- https://www.rfc-editor.org/rfc/rfc4511.html
- https://www.rfc-editor.org/rfc/rfc4513.html
- https://www.rfc-editor.org/rfc/rfc4517.html
- https://www.rfc-editor.org/rfc/rfc4519.html
- https://www.rfc-editor.org/rfc/rfc8018.html
- https://www.rfc-editor.org/rfc/rfc9106.html
회원 브리핑
프로필 심층 컨텍스트
올바른 멤버십 등급으로 로그인하면 전체 브리핑과 출처 노트를 볼 수 있습니다.
Strategic Circle 전용
Strategic Circle
모든 독자에게 공개됩니다. 가입 후 로그인하면 프로필 브리핑를 열람할 수 있습니다.
Strategic Circle 가입하기Leadership Alliance 전용
Leadership Alliance
자격을 갖춘 IP 자산 소유자 및 운영진을 위한 콘텐츠입니다. 로그인하면 Leadership Alliance 브리핑을 열람할 수 있습니다.
Leadership Alliance 가입하기





