This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new 5e6a7724abc [fix](ldap) Replace custom LDAP filter escaping with
`LdapEncoder.filterEncode` to prevent injection vulnerabilities and add related
documentation. (#61662) (#61777)
5e6a7724abc is described below
commit 5e6a7724abc326633035a7d6bfe2cee4bc2aa2a0
Author: seawinde <[email protected]>
AuthorDate: Fri Mar 27 09:42:41 2026 +0800
[fix](ldap) Replace custom LDAP filter escaping with
`LdapEncoder.filterEncode` to prevent injection vulnerabilities and add related
documentation. (#61662) (#61777)
pick from #61662
---
.../doris/mysql/authenticate/ldap/LdapClient.java | 18 +++++++------
.../mysql/authenticate/ldap/LdapClientTest.java | 30 ++++++++++++++++++++++
2 files changed, 40 insertions(+), 8 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapClient.java
b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapClient.java
index 79248ab0212..5d03917f0d3 100644
---
a/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapClient.java
+++
b/fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/ldap/LdapClient.java
@@ -25,7 +25,6 @@ import org.apache.doris.common.util.NetUtils;
import org.apache.doris.common.util.SymmetricEncryption;
import org.apache.doris.persist.LdapInfo;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import lombok.Data;
import org.apache.logging.log4j.LogManager;
@@ -37,6 +36,7 @@ import
org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.pool.factory.PoolingContextSource;
import org.springframework.ldap.pool.validation.DefaultDirContextValidator;
import org.springframework.ldap.query.LdapQuery;
+import org.springframework.ldap.support.LdapEncoder;
import
org.springframework.ldap.transaction.compensating.manager.TransactionAwareContextSourceProxy;
import java.util.List;
@@ -146,7 +146,7 @@ public class LdapClient {
try {
clientInfo.getLdapTemplateNoPool().authenticate(org.springframework.ldap.query.LdapQueryBuilder.query()
.base(LdapConfig.ldap_user_basedn)
- .filter(getUserFilter(LdapConfig.ldap_user_filter,
userName)), password);
+ .filter(applyLoginFilter(LdapConfig.ldap_user_filter,
userName)), password);
return true;
} catch (Exception e) {
LOG.info("ldap client checkPassword failed, userName: {}",
userName, e);
@@ -167,7 +167,7 @@ public class LdapClient {
List<String> groupDns;
if (!LdapConfig.ldap_group_filter.isEmpty()) {
// Support Open Directory implementations
- String filter = LdapConfig.ldap_group_filter.replace("{login}",
userName);
+ String filter = applyLoginFilter(LdapConfig.ldap_group_filter,
userName);
groupDns =
getDn(org.springframework.ldap.query.LdapQueryBuilder.query()
.attributes("dn")
.base(LdapConfig.ldap_group_basedn)
@@ -195,13 +195,13 @@ public class LdapClient {
private String getUserDn(String userName) {
List<String> userDns =
getDn(org.springframework.ldap.query.LdapQueryBuilder.query()
-
.base(LdapConfig.ldap_user_basedn).filter(getUserFilter(LdapConfig.ldap_user_filter,
userName)));
+
.base(LdapConfig.ldap_user_basedn).filter(applyLoginFilter(LdapConfig.ldap_user_filter,
userName)));
if (userDns == null || userDns.isEmpty()) {
return null;
}
if (userDns.size() > 1) {
String msg = String.format("[%s] not unique in LDAP server: [%s]",
- getUserFilter(LdapConfig.ldap_user_filter, userName),
userDns);
+ applyLoginFilter(LdapConfig.ldap_user_filter, userName),
userDns);
LOG.error(msg);
ErrorReport.report(ErrorCode.ERROR_LDAP_USER_NOT_UNIQUE_ERR,
userName);
throw new RuntimeException(msg);
@@ -209,7 +209,6 @@ public class LdapClient {
return userDns.get(0);
}
- @VisibleForTesting
public List<String> getDn(LdapQuery query) {
init();
try {
@@ -229,7 +228,10 @@ public class LdapClient {
}
}
- private String getUserFilter(String userFilter, String userName) {
- return userFilter.replaceAll("\\{login}", userName);
+ private String applyLoginFilter(String filter, String userName) {
+ if (filter == null) {
+ return null;
+ }
+ return filter.replace("{login}", LdapEncoder.filterEncode(userName));
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java
b/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java
index c0d6c36f83b..7790816856f 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/mysql/authenticate/ldap/LdapClientTest.java
@@ -28,6 +28,7 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.ldap.query.LdapQuery;
+import org.springframework.ldap.support.LdapEncoder;
import java.util.Arrays;
import java.util.List;
@@ -118,6 +119,35 @@ public class LdapClientTest {
secureUrl.startsWith("ldaps://"));
}
+ @Test
+ public void testLdapFilterEncoding() {
+ // Combined special characters
+ String input = "test*()\\\u0000";
+ String expected = "test\\2a\\28\\29\\5c\\00";
+ Assert.assertEquals(expected, LdapEncoder.filterEncode(input));
+
+ // Null input
+ Assert.assertNull(LdapEncoder.filterEncode(null));
+
+ // Normal username should not be altered
+ Assert.assertEquals("zhangsan", LdapEncoder.filterEncode("zhangsan"));
+ Assert.assertEquals("[email protected]",
LdapEncoder.filterEncode("[email protected]"));
+
+ // Empty string
+ Assert.assertEquals("", LdapEncoder.filterEncode(""));
+
+ // Each special character individually
+ Assert.assertEquals("\\2a", LdapEncoder.filterEncode("*"));
+ Assert.assertEquals("\\28", LdapEncoder.filterEncode("("));
+ Assert.assertEquals("\\29", LdapEncoder.filterEncode(")"));
+ Assert.assertEquals("\\5c", LdapEncoder.filterEncode("\\"));
+ Assert.assertEquals("\\00", LdapEncoder.filterEncode("\u0000"));
+
+ // Injection payload: dorisuser6)(mail=testp*
+ Assert.assertEquals("dorisuser6\\29\\28mail=testp\\2a",
+ LdapEncoder.filterEncode("dorisuser6)(mail=testp*"));
+ }
+
@After
public void tearDown() {
LdapConfig.ldap_use_ssl = false; // restoring default value for other
tests
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]