
CVE-2026-49268 — Analyse und Behebung einer LDAP-Injection-Authentifizierungsumgehungs-Schwachstelle
| Branch | 1.13-CVE-2026-49268 |
| Autor | Jinwoo Hwang (https://JinwooHwang.com) |
Dieser Branch (1.13-CVE-2026-49268) enthält eine umfassende Sicherheitsbehebung einer LDAP-Injection-Authentifizierungsumgehung in der Apache Shiro 1.13-Version.
Offizielle NVD-Beschreibung
Ein entfernter Angreifer kann LDAP-Sonderzeichen in die Konstruktion des Distinguished Name (DN) in der Klasse DefaultLdapRealm einschleusen. Vom Benutzer bereitgestellte Benutzernamen-Eingaben werden direkt in die LDAP-DN- Vorlage eingefügt, ohne dass RFC 2253-Sonderzeichen maskiert werden. Dies ermöglicht es einem Angreifer, die DN-Struktur zu manipulieren, die für die LDAP-Bind-Authentifizierung verwendet wird, wodurch möglicherweise die Authentifizierung umgangen oder die Identität anderer Benutzer angenommen werden kann. Dieses Problem betrifft alle Apache Shiro-Versionen bis 2.2.0 und 3.0.0-alpha-1, wenn DefaultLdapRealm verwendet wird.
| Feld | Wert |
|---|---|
| CVE | CVE-2026-49268 — Apache Shiro: LDAP-DN-Injection in DefaultLdapRealm |
| CWE-ID | CWE-90 — Unsachgemäße Neutralisierung von Sonderelementen in einer LDAP-Abfrage ('LDAP-Injection') |
| CVSS v4.0 | 8.8 HOCH — CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:H/VA:N/SC:N/SI:N/SA:N/S:P/AU:Y/R:A/RE:L/U:Red |
| CVSS v3.1 | 9.1 KRITISCH — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N |
| Betroffene Versionen | org.apache.shiro:shiro-core 0 bis einschließlich 2.2.0; 3.0.0-alpha-0 bis einschließlich 3.0.0-alpha-1 |
| Upstream behoben in | 2.2.1 und 3.0.0-alpha-2 |
| Referenz | https://lists.apache.org/thread/svszql3od8td7hn6conyj2oq70v53b5s |
Apache Shiro kann Benutzer gegenüber einem LDAP-Verzeichnis authentifizieren. Dazu wandelt es einen
übermittelten Benutzernamen in einen Distinguished Name um — die Adresse des Verzeichnisses für den Eintrag
dieses Benutzers —, indem der Benutzername in eine konfigurierte Vorlage eingesetzt wird, zum Beispiel
uid={0},ou=users,dc=mycompany,dc=com.
In den betroffenen Versionen wird der Benutzername als reiner Text in diese Vorlage eingefügt. Eine Handvoll Satzzeichen — allen voran das Komma — sind für einen Verzeichnisserver keine gewöhnlichen Textzeichen; sie sind die Syntax, die einen Teil einer Adresse vom nächsten trennt. Ein Benutzername, der diese Zeichen enthält, verhält sich daher nicht mehr wie ein Wert innerhalb der Adresse, sondern beginnt, sich wie ein Teil der Adresse selbst zu verhalten.
Die praktische Konsequenz ist, dass eine sich anmeldende Person beeinflussen kann, gegen welchen Verzeichniseintrag Shiro zu authentifizieren versucht, anstatt nur ihren eigenen Namen anzugeben. Statt in dem Container nachgeschlagen zu werden, den die Bereitstellung vorgesehen hat, kann die Suche an eine andere Stelle im Verzeichnis umgeleitet werden. Je nachdem, wie das Verzeichnis aufgebaut ist und was es zulässt, kann dies dazu führen, dass man sich als die falsche Identität authentifiziert oder dass die Authentifizierung erfolgreich ist, obwohl sie es nicht sein sollte.
Risikoprofil. Was das Risiko erhöht: Es sind keine vorherigen Zugriffsrechte oder Anmeldedaten erforderlich — die
Eingabe erreicht die Anmeldegrenze, die für jeden erreichbar ist, der die
Anwendung erreichen kann; und die betroffene Klasse ist die standardmäßige, dokumentierte Art, Shiro mit LDAP zu verbinden,
sodass dies keine exotische Konfiguration ist. Was es verringert: Die Bereitstellung muss tatsächlich
DefaultLdapRealm (oder JndiLdapRealm) mit einer konfigurierten DN-Vorlage verwenden; Bereitstellungen, die
sich auf andere Weise authentifizieren oder die einen vollständigen DN oder eine nicht-textuelle Anmeldeinformation wie ein
Zertifikat übergeben, sind nicht betroffen. Ob eine umgeleitete Suche eine nutzbare Authentifizierung ergibt,
hängt auch vom eigenen Aufbau und den Zugriffsregeln des Zielverzeichnisses ab, die von Standort zu Standort variieren.
Eine zweite, nicht sicherheitsrelevante Konsequenz ist für die Release-Planung erwähnenswert: Benutzer, deren
legitime Benutzernamen einen Backslash enthalten oder mit # beginnen, können sich derzeit überhaupt nicht anmelden,
weil die für sie erstellte Adresse kein wohlgeformter Name ist und
rundheraus abgelehnt wird. Andere Satzzeichen führen nicht zu einem direkten Fehlschlag — sie ändern stillschweigend, auf welchen Eintrag die
Adresse verweist, was das obige Sicherheitsproblem ist. Dieselbe Korrektur behebt beides.
core/src/main/java/org/apache/shiro/realm/ldap/DefaultLdapRealm.java, getUserDn(String),
Zeilen 227–250 auf der ungepatchten Basisversion:```java
protected String getUserDn(String principal) throws IllegalArgumentException, IllegalStateException {
if (!StringUtils.hasText(principal)) {
throw new IllegalArgumentException("User principal cannot be null or empty for User DN construction.");
}
String prefix = getUserDnPrefix();
String suffix = getUserDnSuffix();
if (prefix == null && suffix == null) {
log.debug("userDnTemplate property has not been configured, indicating the submitted "
+ "AuthenticationToken's principal is the same as the User DN. Returning the method argument "
+ "as is.");
return principal;
}
int prefixLength = prefix != null ? prefix.length() : 0;
int suffixLength = suffix != null ? suffix.length() : 0;
StringBuilder sb = new StringBuilder(prefixLength + principal.length() + suffixLength);
if (prefixLength > 0) {
sb.append(prefix);
}
sb.append(principal); // <-- inserted verbatim
if (suffixLength > 0) {
sb.append(suffix);
}
return sb.toString();
}
Das Template wird zur Konfigurationszeit einmal um das `{0}`-Token herum aufgeteilt
(`setUserDnTemplate`, Zeilen 181–200), in ein `prefix` und ein `suffix`. Zum Authentifizierungszeitpunkt
wird der Principal dazwischen konkateniert. **Zu keinem Zeitpunkt wird eine Kodierung angewendet.** Es gibt
keinen Escaping-Helfer irgendwo in `org/apache/shiro/realm/ldap/`.
### 3.2 Die Invariante, die angenommen, aber nie durchgesetzt wurde
Der umgebende Code behandelt das Ergebnis von `getUserDn` als wohlgeformten Distinguished Name —
er wird direkt an `LdapContextFactory.getLdapContext(...)` und von dort an JNDI als
Bind-DN übergeben. Das ist nur dann korrekt, wenn der substituierte Principal ein *einzelner Attributwert* ist.
String-Konkatenation kann das nicht durchsetzen. RFC 2253 (und RFC 4514) reservieren
`,` `+` `"` `\` `<` `>` `;` `=`, ein führendes `#` sowie führenden/nachfolgenden Leerraum als strukturelle
Syntax innerhalb eines DN. Wenn eines davon im Principal auftritt, wird es vom Parser als
Struktur gelesen, nicht als Inhalt. Die Invariante — *„der Principal belegt genau einen RDN-Wert"* —
wurde von jedem nachgelagerten Konsumenten angenommen und von keinem durchgesetzt.