| <!-- |
| SPDX-License-Identifier: Apache-2.0 |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| https://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| --> |
| |
| # Threat Model — Apache Directory (umbrella) |
| |
| ## §1 Header |
| |
| - **Project:** Apache Directory — a family of identity-infrastructure components: an **LDAP v3 directory |
| server** (ApacheDS), the **LDAP API** client/codec library, a **Kerberos** implementation (Kerby, incl. |
| KDC + token/PKINIT preauth), the **Fortress** RBAC/ARBAC authorization system (core + REST endpoint + |
| web console + container realm), a **SCIM 2.0** provisioning implementation (SCIMple), an **MVCC B-tree** |
| storage engine (Mavibot), and the **Studio** desktop LDAP client *(documented — project; per-repo READMEs)*. |
| - **Scope of this umbrella:** the **shared trust model** across the server-side identity components, with |
| **per-domain addenda** where the surface diverges (LDAP bind/ACI, Kerberos KDC crypto, RBAC policy, SCIM |
| protocol, MVCC storage). The Studio desktop client is modelled lightly as a *client* (§3). |
| - **Repos covered (confirmed scope):** `directory-server`, `directory-ldap-api`, `directory-kerby`, |
| `directory-fortress-core`, `directory-fortress-enmasse`, `directory-fortress-commander`, |
| `directory-fortress-realm`, `directory-scimple`, `directory-mavibot`, `directory-studio`. |
| - **Modelled against:** each repo's default branch HEAD (2026-05-31). |
| - **Status:** **DRAFT — v0, not yet reviewed by the Directory PMC.** Produced by the ASF Security team via the |
| `threat-model-producer` rubric (<https://gist.github.com/potiuk/da14a826283038ddfe38cc9fe6310573>). |
| - **Reporting / version-binding / legend** as in the sibling models. **Draft confidence:** ~18 documented / |
| 0 maintainer / ~70 inferred. Each *(inferred)* routes to §14 (grouped by domain). |
| |
| These components share one shape: a **network service that authenticates a remote principal and then |
| authorizes its requests over a wire protocol** (LDAP, Kerberos, SCIM/HTTP, Fortress REST). The umbrella |
| captures that shared boundary; the addenda capture each protocol's specific attack surface. |
| |
| ## §2 Scope and intended use |
| |
| Caller roles (common across the stack): |
| |
| - **Unauthenticated network client** — a peer speaking LDAP/Kerberos/HTTP before authenticating; untrusted. |
| - **Authenticated principal** — bound LDAP user, Kerberos principal, or authenticated SCIM/REST caller; |
| trusted up to its directory/RBAC permissions. |
| - **Administrator** — a principal with directory-admin / Kerberos-admin / Fortress-superuser rights. |
| - **Operator / deployer** — controls server config, schema, ACIs, the Kerberos realm + keytabs, the RBAC |
| policy data, TLS material, and the backing store. **Trusted; out of model as adversary (§3).** |
| |
| **Component-family table (repo → domain → model placement):** |
| |
| | Repo | Domain / role | Trust surface | In runtime model? | |
| | --- | --- | --- | --- | |
| | `directory-server` (ApacheDS) | LDAP v3 server (bind, search, modify, ACI), embeds Kerberos/DNS | LDAP/Kerberos network protocol | **Yes — host of this umbrella** | |
| | `directory-ldap-api` | LDAP protocol API + ASN.1/BER codec (client & server) | parses untrusted LDAP PDUs | **Yes** | |
| | `directory-kerby` | Kerberos: KDC (AS/TGS), client, crypto, PKINIT/token preauth | Kerberos network protocol; crypto | **Yes (addendum K)** | |
| | `directory-fortress-core` | RBAC/ARBAC policy engine over LDAP | API + policy decisions | **Yes (addendum F)** | |
| | `directory-fortress-enmasse` | Fortress REST service (RBAC over HTTP) | HTTP/REST | **Yes (addendum F)** | |
| | `directory-fortress-commander` | Fortress web admin console | HTTP/web UI | **Yes (addendum F)** | |
| | `directory-fortress-realm` | Fortress container security realm (Tomcat/etc.) | servlet auth integration | **Yes (addendum F)** | |
| | `directory-scimple` | SCIM 2.0 provisioning protocol | HTTP/JSON | **Yes (addendum S)** | |
| | `directory-mavibot` | MVCC B-tree storage engine (a backend) | in-process; on-disk data | **Yes (addendum M)** | |
| | `directory-studio` | Eclipse-based LDAP **client** tool (desktop) | parses server responses; local | Light — client tool (§3) | |
| |
| ## §3 Out of scope (explicit non-goals) |
| |
| - **The operator/deployer as adversary**, and pure misconfiguration (weak ACIs, an open anonymous bind left |
| enabled, a Kerberos realm with weak crypto enabled, RBAC policy mistakes, TLS disabled). Each component |
| provides controls; configuring them is the operator's job (§10/§11) *(inferred)*. |
| - **The backing data stores and external systems** the components integrate with (an external LDAP, an |
| external KDC, the OS keytab/credential cache), except as these components consume them. |
| - **`directory-studio` as a server** — it is a desktop client; its in-model surface is *parsing untrusted |
| responses* from a directory it connects to, not serving requests. Findings requiring a malicious server |
| the user chose to connect to are low-priority client-side hardening, not server-side `VALID`. |
| - **Examples, samples, integration-test harnesses, and build tooling** across all repos *(inferred)*. |
| - **Cryptographic-primitive internals** (the JCE provider) except as the components select and use them. |
| |
| ## §4 Trust boundaries and data flow |
| |
| The shared boundary is **the wire-protocol request before authentication+authorization completes**. Per domain: |
| |
| - **LDAP (server, ldap-api):** the BER/ASN.1 decoder is the first thing untrusted bytes hit — a classic |
| parser/DoS surface. After a **bind** establishes identity (simple/SASL), **ACIs** authorize each |
| operation; anonymous/unauthenticated operations are a configurable surface *(inferred — addendum L)*. |
| - **Kerberos (kerby):** AS-REQ/TGS-REQ from any network peer reach the KDC; pre-authentication, ticket |
| issuance, encryption-type negotiation, and PKINIT/token preauth are the trust transitions; the KDC's |
| master key and per-principal keys are the crown jewels *(inferred — addendum K)*. |
| - **Fortress (core/enmasse/commander/realm):** RBAC/ARBAC **policy decisions** are the boundary — a request |
| is authorized only if the activated roles grant the permission; the REST/web tiers add HTTP auth, CSRF, |
| and injection surfaces *(inferred — addendum F)*. |
| - **SCIM (scimple):** HTTP/JSON provisioning requests (create/modify/delete users/groups) must be |
| authenticated and authorized; the filter/PATCH parsers are an injection/DoS surface *(inferred — addendum S)*. |
| - **Mavibot (storage):** consumes data from the server layer; its trust input is the on-disk B-tree and the |
| records the server hands it — corruption-resistance and bounds, not a network boundary *(inferred — addendum M)*. |
| |
| **Reachability precondition (shared):** a finding is in-model on a **server inbound** path if reachable from |
| an unauthenticated or under-privileged remote principal *before* the component's auth/authorization gate; |
| a finding that requires admin rights or a misconfiguration is `OUT-OF-MODEL` (§7/§5a). |
| |
| ## §5 Assumptions about the environment |
| |
| - JVM services; operator-managed config, schema, ACIs, Kerberos realm/keytabs, RBAC policy, and TLS material. |
| - Backing storage (Mavibot or another partition backend; LDAP for Fortress policy) is on trusted disk. |
| - Clocks are synchronized within the Kerberos skew window *(inferred — addendum K)*. |
| - TLS/StartTLS, SASL, and Kerberos crypto are available and operator-configured *(inferred)*. |
| - **What the stack does to its host (*(inferred)* — wave-2):** binds protocol ports; reads/writes its data |
| partitions and keytabs; performs crypto; the Fortress tiers open HTTP listeners and bind to a backing LDAP. |
| Not assumed to execute host commands. |
| |
| ## §5a Build-time and configuration variants |
| |
| | Knob (per domain; defaults *(inferred)*) | Effect | Ruling needed | |
| | --- | --- | --- | |
| | LDAP **anonymous bind / unauthenticated access** | Whether unauthenticated reads/ops are allowed | **Open (wave-1, L):** default on/off; supported posture? | |
| | LDAP **ACI default** & admin-limits | Default authorization posture | **Open (L)** | |
| | Kerberos **allowed enctypes** (incl. legacy RC4/DES) | Crypto strength of tickets | **Open (wave-1, K):** are weak enctypes disabled by default? | |
| | Kerberos **PKINIT / token-preauth** enabled | Adds preauth attack surface | Open (K) | |
| | Fortress **REST/console auth + TLS** | Whether RBAC management is authenticated/encrypted | **Open (wave-1, F)** | |
| | SCIM **auth + filter/PATCH limits** | Auth + injection/DoS posture | **Open (wave-1, S)** | |
| | TLS/StartTLS enforcement (all protocols) | Transport confidentiality/integrity | Operator (§10) | |
| |
| ## §6 Assumptions about inputs (shared trust table) |
| |
| | Entry point | Parameter | Attacker-controllable? | Caller/operator must enforce | |
| | --- | --- | --- | --- | |
| | LDAP listener | BER-encoded PDU (bind, search filter, DN, controls) | **yes** | codec bounds; filter complexity limits; ACI authz | |
| | Kerberos KDC | AS-REQ/TGS-REQ (princ names, enctypes, preauth, PA-DATA) | **yes** | enctype policy; preauth; replay window | |
| | SCIM endpoint | HTTP method, JSON body, SCIM filter, PATCH ops | **yes** | authn/authz; filter/PATCH bounds; JSON limits | |
| | Fortress REST/console | HTTP request, RBAC operands, form fields | **yes** | authn; RBAC decision; CSRF; injection guards | |
| | LDAP-API codec | server/client LDAP messages | **yes** (both directions) | robust decode; no OOB/DoS | |
| | Mavibot | record bytes from the server; on-disk pages | from a **trusted** server layer | bounds; corruption handling | |
| | config / schema / ACI / keytab / policy | all | **no — operator-trusted** | never sourced from a request | |
| |
| ## §7 Adversary model |
| |
| - **Primary adversary:** an untrusted network client of any listener (LDAP, Kerberos, SCIM, Fortress REST/UI) |
| — sending crafted PDUs, malformed/oversized requests, weak-enctype or replayed Kerberos requests, |
| injection payloads (LDAP filter, SCIM filter, SQL/LDAP injection via the management tiers), or |
| authentication-bypass attempts. |
| - **Secondary:** an **under-privileged authenticated principal** attempting to exceed its ACIs / RBAC roles |
| (privilege escalation); a malicious LDAP server vs. a Studio/ldap-api **client**. |
| - **Goals:** authenticate as another principal / bypass bind; read or modify directory entries, Kerberos |
| principals, or RBAC policy beyond authorization; forge or replay Kerberos tickets; crash/DoS a service; |
| corrupt stored data. |
| - **Out of model:** the operator; anyone holding the KDC master key, admin DN, Fortress superuser, keytabs, |
| or filesystem access; the JCE/OS internals. |
| |
| ## §8 Security properties the project provides (shared + per-domain) |
| |
| *(All *(inferred)* pending §14; symptom + severity per the rubric.)* |
| |
| 1. **Authentication integrity (shared).** Bind / Kerberos preauth / SCIM+REST auth verify the principal before |
| privileged operations *(inferred)*. *Symptom:* auth bypass. *Severity:* critical. |
| 2. **Authorization enforcement (shared).** LDAP **ACIs**, Fortress **RBAC/ARBAC**, and SCIM authz confine a |
| principal to permitted operations *(documented — Fortress is an RBAC engine; ACI in ApacheDS; specifics |
| inferred)*. *Symptom:* read/modify beyond authorization; role/permission escalation. *Severity:* critical. |
| 3. **Robust protocol parsing (shared).** The LDAP BER codec, Kerberos ASN.1, and SCIM JSON/filter parsers |
| reject malformed/oversized input cleanly rather than crashing or corrupting memory *(inferred)*. *Symptom:* |
| crash/hang/OOB/DoS from crafted input. *Severity:* high–critical. |
| 4. **(K) Kerberos ticket integrity & replay resistance.** Tickets are bound to the issuing key and protected |
| by timestamps/replay caches; weak enctypes are restrictable *(inferred)*. *Symptom:* forged/replayed |
| ticket; downgrade to weak crypto. *Severity:* critical. |
| 5. **(M) Storage integrity.** Mavibot's MVCC keeps readers consistent and resists corruption from concurrent |
| writes / crash *(inferred — MVCC design)*. *Symptom:* reader sees torn/inconsistent state; corruption. |
| *Severity:* high. |
| 6. **Transport security support.** TLS/StartTLS and SASL confidentiality/integrity when configured *(inferred)*. |
| *Symptom:* MITM/downgrade where protection was expected. *Severity:* high. |
| |
| ## §9 Security properties the project does NOT provide |
| |
| - **No security without configuration** — anonymous LDAP, weak Kerberos enctypes, or an unauthenticated |
| Fortress REST/console expose the service to the extent the operator left them open *(inferred)*. |
| - **No defence against the operator / key-holder** (KDC master key, admin DN, Fortress superuser) — §3. |
| - **No application-level authorization beyond the configured ACIs/RBAC policy.** |
| - **(client) ldap-api / Studio do not protect the user against a hostile server they chose to connect to** |
| beyond robust parsing. |
| |
| **False friends:** |
| |
| - *A successful **anonymous bind** looks like "it works" but is unauthenticated access* — many reports are |
| really an operator leaving anonymous access on. |
| - *Kerberos "encryption" of a ticket is integrity/authenticity, not a guarantee against a weak **enctype** |
| the realm still permits* — a permitted RC4/DES enctype is a downgrade surface. |
| - *An RBAC **role assignment** is not active permission until the session **activates** the role* (RBAC vs. |
| ARBAC, separation-of-duty constraints) — naive "user has role" checks miss SoD/DSD. |
| - *An LDAP **search filter** is a query language, not inert data* — filter injection via unsanitized input at |
| a downstream app is the LDAP analogue of SQL injection. |
| |
| **Well-known attack classes to keep in view:** LDAP/SCIM **filter injection**; **anonymous-bind** exposure; |
| Kerberos **enctype downgrade**, **replay**, **Kerberoasting** (weak service keys), **PKINIT** edge cases; |
| **ASN.1/BER parser DoS**; **XXE/JSON-bomb** in SCIM/REST; **CSRF/XSS** in the Fortress console; **SoD/DSD** |
| policy bypass in RBAC; **password-policy / lockout** bypass. |
| |
| ## §10 Downstream (operator) responsibilities |
| |
| - **LDAP:** disable anonymous/unauthenticated access unless intended; set restrictive ACIs and admin limits; |
| enforce TLS/StartTLS; bound search filter complexity and result sizes. |
| - **Kerberos:** disable weak enctypes (RC4/DES); require preauth; protect the KDC master key + keytabs; keep |
| clocks synced and the replay cache on. |
| - **Fortress:** authenticate and TLS-protect the REST endpoint and web console; protect the policy LDAP; |
| configure SoD/DSD constraints deliberately. |
| - **SCIM:** require authentication/authorization on every endpoint; bound filter/PATCH/JSON size. |
| - **Storage:** protect the data partitions/keytabs at the filesystem layer; back up. |
| - Track ASF advisories and stay on supported lines. |
| |
| ## §11 Known misuse patterns |
| |
| - Leaving anonymous LDAP bind/read enabled on an exposed server. |
| - Permitting legacy Kerberos enctypes for "compatibility". |
| - Exposing the Fortress REST endpoint or console without authentication/TLS. |
| - Building LDAP/SCIM filters by concatenating untrusted input in a downstream app (filter injection). |
| - Treating an RBAC role *assignment* as an active permission, ignoring activation/SoD. |
| |
| ## §11a Known non-findings (recurring false positives) |
| |
| *(v0 seed — the PMC (LDAP/Kerberos/RBAC experts) will own the authoritative list — §14.)* |
| |
| - **"Anonymous bind allowed" / "weak enctype available"** against a default/sample config — operator posture |
| (§5a/§10); `OUT-OF-MODEL: non-default-build` unless the *default* is the insecure one (then `VALID` — §14). |
| - **"Admin can do X"** — the admin/superuser is trusted (§7); an authorized admin action is not a finding. |
| - **LDAP/SCIM filter injection attributed to a downstream caller** concatenating input — not a server bug (§9). |
| - **Findings in examples / integration tests / build tooling** across repos — out of scope (§3). |
| - **Studio parsing a response from a server the user connected to** — client-side hardening, not server `VALID` (§3). |
| - **Mavibot internal invariants** not reachable from server-accepted input — out of the input surface (§6). |
| |
| ## §12 Conditions that would change this model |
| |
| - A change to a default auth/anonymous/enctype/anonymous-REST posture in any component. |
| - A new protocol surface, a new Kerberos preauth mechanism, or a new SCIM/REST endpoint enabled by default. |
| - A change to ACI/RBAC default semantics or to Mavibot's consistency guarantees. |
| - Promotion of `directory-studio` to a server role. |
| - Any report not cleanly routable to a §13 disposition. |
| |
| ## §13 Triage dispositions |
| |
| | Disposition | Meaning | Licensed by | |
| | --- | --- | --- | |
| | `VALID` | Violates a claimed property via an in-scope adversary/input in a default/secure config. | §8, §6, §7 | |
| | `VALID-HARDENING` | No §8 property broken, but a §11 misuse is easy enough to warrant a safer default/guard. | §11 | |
| | `OUT-OF-MODEL: trusted-input` | Requires control of config / schema / ACI / policy / keytab. | §6 | |
| | `OUT-OF-MODEL: adversary-not-in-scope` | Requires operator / admin / key-holder capability. | §7, §3 | |
| | `OUT-OF-MODEL: unsupported-component` | Lands in examples, tests, build tooling, or Studio-as-server. | §3 | |
| | `OUT-OF-MODEL: non-default-build` | Only when an insecure non-default option was enabled. | §5a | |
| | `BY-DESIGN: property-disclaimed` | Concerns a §9-disclaimed property (no security without config; client ≠ server). | §9 | |
| | `KNOWN-NON-FINDING` | Matches a §11a entry. | §11a | |
| | `MODEL-GAP` | Routes to none of the above → revise the model. | §12 | |
| |
| ## §14 Open questions for the maintainers (grouped by domain) |
| |
| **Wave 1 — insecure-default rulings across the stack (decide VALID-vs-misconfig):** |
| 1. **(LDAP)** Is **anonymous bind / unauthenticated access** off by default, and is leaving it on an operator |
| choice (→ misconfig) rather than a default we ship? *Proposed:* off by default; on = operator choice. |
| 2. **(Kerberos)** Are **weak enctypes (RC4/DES)** disabled by default and is **preauth required** by default? |
| *Proposed:* weak enctypes off; preauth required. |
| 3. **(Fortress/SCIM)** Do the **REST endpoint, web console, and SCIM endpoints require authentication (+ TLS)** |
| by default? *Proposed:* yes; unauthenticated exposure is operator misconfig. |
| |
| **Wave 2 — authorization & protocol parsing (§8):** |
| 4. **(LDAP)** What enforces **ACI** authorization and are there bounds on **search-filter complexity / result |
| size** to prevent DoS? *Proposed:* ACI subsystem enforces; admin limits bound cost. |
| 5. **(RBAC)** Does Fortress enforce **role activation + SoD/DSD** (not just assignment) on every decision? |
| *Proposed:* yes; activation + SoD enforced. |
| 6. **(codec)** Are the **LDAP BER and Kerberos ASN.1 decoders** hardened against malformed/oversized PDUs |
| (depth/length caps)? *Proposed:* yes, bounded. |
| |
| **Wave 3 — crypto, storage, §11a (§8/§9/§11a):** |
| 7. **(Kerberos)** Replay protection + master-key handling assumptions; any known PKINIT/token-preauth caveats? |
| 8. **(Mavibot)** What consistency/corruption guarantees does the MVCC engine make under crash/concurrent write? |
| 9. **(all)** From the long advisory history, what do scanners most often (re)report that the PMC considers a |
| **non-finding** today? (Seeds §11a per domain.) |
| |
| **Meta:** |
| 10. Confirm the umbrella shape: this document in `apache/directory-server`, the other nine repos carrying an |
| `AGENTS.md`→`SECURITY.md`→(this umbrella) discoverability pointer, with the per-domain addenda above |
| expanded as the PMC answers. Should **Kerby / Fortress / SCIMple** instead each carry their *own* full |
| model (they are semi-independent products)? *Proposed:* umbrella + pointers now; split out later if the |
| PMC prefers. |
| |
| ## §15 Machine-readable companion |
| |
| Deferred for v0; a `threat-model.yaml` per domain can later encode the §6 trust tables, §2/§3 scoping, §8 |
| property rows, §9 false friends, §11a non-findings, and §13 dispositions. |