Java: model LDAP bind-DN sinks for java/ldap-injection#22002
Open
tonghuaroot wants to merge 1 commit into
Open
Java: model LDAP bind-DN sinks for java/ldap-injection#22002tonghuaroot wants to merge 1 commit into
tonghuaroot wants to merge 1 commit into
Conversation
The java/ldap-injection query modelled LDAP search sinks (the filter and base of a directory search) but not the bind-DN path, where DN injection (CWE-90, RFC 2253) actually lands. Add bind-DN sinks: - javax.naming.Context / javax.naming.directory.DirContext bind, rebind, lookup, lookupLink and createSubcontext (the String name argument); - the java.naming.security.principal JNDI environment value, modelled as a hand-written sink because it depends on the put key, not the signature; - Apache Shiro LdapContextFactory.getLdapContext (the principal argument). new javax.naming.ldap.LdapName(String) is deliberately left unmodelled: it commonly parses an existing certificate or principal DN rather than building one for a bind, so modelling it as a sink would over-fire. Extend the CWE-090 test with bind-DN true positives and Rdn.escapeValue true negatives.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
java/ldap-injectionmodels LDAP search sinks (the filter and base of a directorysearch) but not the bind-DN path, where LDAP distinguished-name injection
(CWE-90, RFC 2253) actually lands. This PR adds the bind-DN sinks:
ldap-injection):javax.naming.Contextbind/rebind/createSubcontext/lookup/lookupLink— theString nameargument (javax.naming.model.yml).javax.naming.directory.DirContextbind/rebind/createSubcontext— theString nameargument (javax.naming.directory.model.yml).org.apache.shiro.realm.ldap.LdapContextFactory.getLdapContext— theprincipalargument (new
org.apache.shiro.realm.ldap.model.yml). This is the exact sink inApache Shiro CVE-2026-49268.
LdapInjectionSinkfor thejava.naming.security.principalJNDIenvironment value (
env.put(Context.SECURITY_PRINCIPAL, dn)and the literal-keyform). This cannot be a MaD sink because it keys off the
putkey argument, notthe method signature.
When given a
String, all of these positions interpret the argument as a(distinguished) name; an unescaped, attacker-controlled value lets the caller
manipulate the DN structure used to authenticate, which can bypass authentication or
impersonate another principal.
Deliberately not modeled
new javax.naming.ldap.LdapName(String)is not added as a sink. It commonlyparses an existing certificate or principal DN to read its RDNs (for example
new LdapName(cert.getSubjectX500Principal().getName()).getRdns()), which is notinjection. Modeling it as a sink would over-fire on that benign idiom. This is noted
in a code comment and in the change note. (The DN-string positions where a DN is used
to bind/look up/authenticate are the real sinks.)
DN escaping vs filter escaping
DN escaping (RFC 2253) uses a different escape set from search-filter escaping
(RFC 4515).
Rdn.escapeValueneutralizes DN metacharacters (, + " \ < > ; =,leading
#, leading/trailing space) but not filter metacharacters (* ( )). Theexisting model already treats
Rdn.escapeValueas flow-stopping (neutral model inext/generated/modelgenerator/javax.naming.ldap.model.yml), so the canonical Shiro2.2.1 fix is correctly recognized as safe; the added test confirms this.
Evidence (Apache Shiro CVE-2026-49268)
CVE-2026-49268 (fixed 2.2.1 / 3.0.0-alpha-2).
DefaultLdapRealm.getUserDnandActiveDirectoryRealm.getUsernameWithSuffixconcatenated the login username into thebind DN with no escaping. Running a 3-way comparison on a database built from
apache/shiro@shiro-root-2.2.0:java/ldap-injection(before this PR)java/ldap-injectionwith these bind-DN sinksThe zero here is expected and is exactly the point: Shiro is an authentication
library, so there is no remote flow source for the app-mode query to start from. This
PR makes the query catch the same bind-DN construction in downstream applications
where the username crosses an HTTP boundary; catching the framework itself is the job
of the companion experimental query (
java/ldap-dn-injection-library-mode).Tests
The CWE-090 query test gains bind-DN true positives for each new sink
(
Context.SECURITY_PRINCIPALvia the constant and the literal key,DirContext.bind,Context.lookup,Shiro getLdapContext) andRdn.escapeValuetrue negatives.codeql test runis green, and the query compiles with--warnings=error.