fix: 【漏洞】修复核心 JDBC URL/Driver 校验分散

This commit is contained in:
tjlygdx
2026-05-18 16:46:54 +08:00
parent 7c574f0626
commit 304104d70e
12 changed files with 271 additions and 296 deletions

View File

@@ -7,8 +7,10 @@ import io.dataease.dataset.utils.FieldUtils;
import io.dataease.datasource.dao.auto.entity.CoreDatasource;
import io.dataease.datasource.dao.auto.entity.CoreDriver;
import io.dataease.datasource.dao.auto.mapper.CoreDatasourceMapper;
import io.dataease.datasource.dao.auto.mapper.CoreDriverMapper;
import io.dataease.datasource.manage.EngineManage;
import io.dataease.datasource.request.EngineRequest;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.datasource.type.*;
import io.dataease.exception.DEException;
import io.dataease.extensions.datasource.dto.*;
@@ -59,6 +61,8 @@ public class CalciteProvider extends Provider {
@Resource
protected CoreDatasourceMapper coreDatasourceMapper;
@Resource
protected CoreDriverMapper coreDriverMapper;
@Resource
private EngineManage engineManage;
protected ExtendedJdbcClassLoader extendedJdbcClassLoader;
private Map<Long, ExtendedJdbcClassLoader> customJdbcClassLoaders = new HashMap<>();
@@ -407,44 +411,11 @@ public class CalciteProvider extends Provider {
@Override
public ConnectionObj getConnection(DatasourceDTO coreDatasource) throws Exception {
ConnectionObj connectionObj = new ConnectionObj();
DatasourceConfiguration configuration = null;
DatasourceConfiguration.DatasourceType datasourceType = DatasourceConfiguration.DatasourceType.valueOf(coreDatasource.getType());
switch (datasourceType) {
case mysql:
case mongo:
case StarRocks:
case doris:
case TiDB:
case mariadb:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), Mysql.class);
break;
case impala:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), Impala.class);
break;
case sqlServer:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), Sqlserver.class);
break;
case oracle:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), Oracle.class);
break;
case db2:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), Db2.class);
break;
case pg:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), Pg.class);
break;
case redshift:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), Redshift.class);
break;
case h2:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), H2.class);
break;
case ck:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), CK.class);
break;
default:
configuration = JsonUtil.parseObject(coreDatasource.getConfiguration(), Mysql.class);
}
DatasourceConfiguration configuration = parseDatasourceConfiguration(coreDatasource.getConfiguration(), datasourceType);
CoreDriver customDriver = resolveCustomDriver(coreDatasource.getType(), configuration.getCustomDriver());
String driverClassName = JdbcUrlSecurityPolicy.resolveDriverClass(coreDatasource.getType(), configuration.getDriver(), configuration.getCustomDriver(), customDriver);
configuration.setDriver(driverClassName);
startSshSession(configuration, connectionObj, null);
Properties props = new Properties();
if (StringUtils.isNotBlank(configuration.getUsername())) {
@@ -453,8 +424,7 @@ public class CalciteProvider extends Provider {
if (StringUtils.isNotBlank(configuration.getPassword())) {
props.setProperty("password", configuration.getPassword());
}
String driverClassName = configuration.getDriver();
ExtendedJdbcClassLoader jdbcClassLoader = extendedJdbcClassLoader;
ExtendedJdbcClassLoader jdbcClassLoader = JdbcUrlSecurityPolicy.isDefaultCustomDriver(configuration.getCustomDriver()) ? extendedJdbcClassLoader : getCustomJdbcClassLoader(customDriver);
Connection conn = null;
try {
Driver driverClass = (Driver) jdbcClassLoader.loadClass(driverClassName).newInstance();
@@ -467,6 +437,40 @@ public class CalciteProvider extends Provider {
return connectionObj;
}
private DatasourceConfiguration parseDatasourceConfiguration(String config, DatasourceConfiguration.DatasourceType datasourceType) {
return switch (datasourceType) {
case mysql, StarRocks, doris, TiDB, mariadb -> JsonUtil.parseObject(config, Mysql.class);
case mongo -> JsonUtil.parseObject(config, Mongo.class);
case impala -> JsonUtil.parseObject(config, Impala.class);
case sqlServer -> JsonUtil.parseObject(config, Sqlserver.class);
case oracle -> JsonUtil.parseObject(config, Oracle.class);
case db2 -> JsonUtil.parseObject(config, Db2.class);
case pg -> JsonUtil.parseObject(config, Pg.class);
case redshift -> JsonUtil.parseObject(config, Redshift.class);
case h2 -> JsonUtil.parseObject(config, H2.class);
case ck -> JsonUtil.parseObject(config, CK.class);
default -> JsonUtil.parseObject(config, Mysql.class);
};
}
private CoreDriver resolveCustomDriver(String datasourceType, String customDriver) {
if (JdbcUrlSecurityPolicy.isDefaultCustomDriver(customDriver)) {
return null;
}
Long customDriverId;
try {
customDriverId = Long.valueOf(customDriver);
} catch (NumberFormatException e) {
DEException.throwException("invalid driver");
return null;
}
CoreDriver coreDriver = coreDriverMapper.selectById(customDriverId);
if (coreDriver == null || !StringUtils.equalsIgnoreCase(coreDriver.getType(), datasourceType)) {
DEException.throwException("invalid driver");
}
return coreDriver;
}
private DatasetTableDTO getTableDesc(DatasourceRequest datasourceRequest, ResultSet resultSet) throws SQLException {
DatasetTableDTO tableDesc = new DatasetTableDTO();
tableDesc.setDatasourceId(datasourceRequest.getDatasource().getId());

View File

@@ -0,0 +1,175 @@
package io.dataease.datasource.security;
import io.dataease.datasource.dao.auto.entity.CoreDriver;
import io.dataease.exception.DEException;
import org.apache.commons.lang3.StringUtils;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.text.Normalizer;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public final class JdbcUrlSecurityPolicy {
private static final String DEFAULT_CUSTOM_DRIVER = "default";
private static final Map<String, String> JDBC_PREFIXES = Map.ofEntries(
Map.entry("mysql", "jdbc:mysql"),
Map.entry("mongo", "jdbc:mysql"),
Map.entry("mariadb", "jdbc:mysql"),
Map.entry("starrocks", "jdbc:mysql"),
Map.entry("doris", "jdbc:mysql"),
Map.entry("tidb", "jdbc:mysql"),
Map.entry("impala", "jdbc:impala"),
Map.entry("sqlserver", "jdbc:sqlserver"),
Map.entry("oracle", "jdbc:oracle"),
Map.entry("db2", "jdbc:db2"),
Map.entry("pg", "jdbc:postgresql"),
Map.entry("redshift", "jdbc:redshift"),
Map.entry("h2", "jdbc:h2"),
Map.entry("ck", "jdbc:clickhouse"),
Map.entry("sqlite", "jdbc:sqlite:")
);
private static final Map<String, String> DEFAULT_DRIVERS = Map.ofEntries(
Map.entry("mysql", "com.mysql.cj.jdbc.Driver"),
Map.entry("mongo", "com.mysql.cj.jdbc.Driver"),
Map.entry("mariadb", "com.mysql.cj.jdbc.Driver"),
Map.entry("starrocks", "com.mysql.cj.jdbc.Driver"),
Map.entry("doris", "com.mysql.cj.jdbc.Driver"),
Map.entry("tidb", "com.mysql.cj.jdbc.Driver"),
Map.entry("impala", "com.cloudera.impala.jdbc.Driver"),
Map.entry("sqlserver", "com.microsoft.sqlserver.jdbc.SQLServerDriver"),
Map.entry("oracle", "oracle.jdbc.driver.OracleDriver"),
Map.entry("db2", "com.ibm.db2.jcc.DB2Driver"),
Map.entry("pg", "org.postgresql.Driver"),
Map.entry("redshift", "com.amazon.redshift.jdbc42.Driver"),
Map.entry("h2", "org.h2.Driver"),
Map.entry("ck", "com.clickhouse.jdbc.ClickHouseDriver"),
Map.entry("sqlite", "org.sqlite.JDBC")
);
private static final Set<String> COMMON_DANGEROUS_FRAGMENTS = Set.of(
"jndi:",
"rmi:",
"ldap:",
"ldaps:",
"dns:",
"file:",
"ftp:",
"nis:",
"corba:",
"corbaname",
"iiop",
"iiopname",
"java.naming.factory.initial",
"java.naming.provider.url",
"java.naming.factory.object",
"java.naming.factory.state",
"autodeserialize",
"queryinterceptors",
"statementinterceptors",
"detectcustomcollations",
"connectionproperties",
"initsql"
);
private static final Map<String, Set<String>> TYPE_DANGEROUS_FRAGMENTS = Map.ofEntries(
Map.entry("mysql", Set.of("maxallowedpacket", "allowloadlocalinfile", "allowurlinlocalinfile", "allowloadlocalinfileinpath", "allowmultiqueries")),
Map.entry("mongo", Set.of()),
Map.entry("mariadb", Set.of("maxallowedpacket", "allowloadlocalinfile", "allowurlinlocalinfile", "allowloadlocalinfileinpath", "allowmultiqueries")),
Map.entry("starrocks", Set.of("maxallowedpacket", "allowloadlocalinfile", "allowurlinlocalinfile", "allowloadlocalinfileinpath", "allowmultiqueries")),
Map.entry("doris", Set.of("maxallowedpacket", "allowloadlocalinfile", "allowurlinlocalinfile", "allowloadlocalinfileinpath", "allowmultiqueries")),
Map.entry("tidb", Set.of("maxallowedpacket", "allowloadlocalinfile", "allowurlinlocalinfile", "allowloadlocalinfileinpath", "allowmultiqueries")),
Map.entry("impala", Set.of("krbjaasfile", "krb5.conf")),
Map.entry("sqlserver", Set.of()),
Map.entry("oracle", Set.of()),
Map.entry("db2", Set.of()),
Map.entry("pg", Set.of("socketfactory", "socketfactoryarg", "sslfactory", "sslhostnameverifier", "sslpasswordcallback", "authenticationpluginclassname")),
Map.entry("redshift", Set.of("socketfactory", "socketfactoryarg", "sslfactory", "sslhostnameverifier", "sslpasswordcallback", "authenticationpluginclassname", "inifile")),
Map.entry("h2", Set.of("init=", "runscript")),
Map.entry("ck", Set.of())
);
private JdbcUrlSecurityPolicy() {
}
public static String validate(String type, String driver, String jdbcUrl, String extraParams) {
if (StringUtils.isBlank(jdbcUrl)) {
DEException.throwException("Illegal jdbcUrl: " + jdbcUrl);
}
String normalizedType = normalizeType(type);
String normalizedUrl = canonicalize(jdbcUrl);
String normalizedExtraParams = canonicalize(extraParams);
String expectedPrefix = JDBC_PREFIXES.get(normalizedType);
if (StringUtils.isBlank(expectedPrefix) || !normalizedUrl.startsWith(expectedPrefix)) {
DEException.throwException("Illegal jdbcUrl: " + jdbcUrl);
}
Set<String> dangerousFragments = new LinkedHashSet<>(COMMON_DANGEROUS_FRAGMENTS);
dangerousFragments.addAll(TYPE_DANGEROUS_FRAGMENTS.getOrDefault(normalizedType, Set.of()));
for (String fragment : dangerousFragments) {
if (normalizedUrl.contains(fragment) || normalizedExtraParams.contains(fragment)) {
DEException.throwException("Illegal parameter: " + fragment);
}
}
return jdbcUrl;
}
public static String trustedDriverClass(String type) {
String driverClass = DEFAULT_DRIVERS.get(normalizeType(type));
if (StringUtils.isBlank(driverClass)) {
DEException.throwException("invalid driver");
}
return driverClass;
}
public static String resolveDriverClass(String type, String requestedDriverClass, String customDriver, CoreDriver registeredDriver) {
if (!isDefaultCustomDriver(customDriver)) {
if (registeredDriver == null
|| StringUtils.isBlank(registeredDriver.getDriverClass())
|| !StringUtils.equalsIgnoreCase(normalizeType(type), normalizeType(registeredDriver.getType()))) {
DEException.throwException("invalid driver");
}
return registeredDriver.getDriverClass();
}
String trustedDriverClass = trustedDriverClass(type);
if (StringUtils.isNotBlank(requestedDriverClass) && !StringUtils.equalsIgnoreCase(requestedDriverClass, trustedDriverClass)) {
DEException.throwException("invalid driver");
}
return trustedDriverClass;
}
public static boolean isDefaultCustomDriver(String customDriver) {
return StringUtils.isBlank(customDriver) || StringUtils.equalsIgnoreCase(customDriver, DEFAULT_CUSTOM_DRIVER);
}
private static String canonicalize(String value) {
if (StringUtils.isBlank(value)) {
return "";
}
String normalized = value;
for (int i = 0; i < 3; i++) {
try {
String decoded = URLDecoder.decode(normalized, StandardCharsets.UTF_8);
if (StringUtils.equals(decoded, normalized)) {
normalized = decoded;
break;
}
normalized = decoded;
} catch (IllegalArgumentException e) {
break;
}
}
normalized = Normalizer.normalize(normalized, Normalizer.Form.NFKC);
normalized = normalized.replace("\\", "");
return normalized.toLowerCase(Locale.ROOT);
}
private static String normalizeType(String type) {
return StringUtils.defaultString(type).toLowerCase(Locale.ROOT);
}
}

View File

@@ -1,6 +1,6 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.exception.DEException;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
@@ -15,8 +15,6 @@ import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
@@ -32,16 +30,9 @@ public class CK extends DatasourceConfiguration {
private String sslCert;
private String sslKey;
@JsonIgnore
private List<String> ILLEGAL_PARAMETERS = Arrays.asList("jndi:", "rmi:", "ldap:", "ldaps:", "dns:", "nis:", "corba:",
"java.naming.factory.initial", "java.naming.provider.url");
public String getJdbc() {
String jdbcUrl;
if (StringUtils.isNotEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
if (!getJdbcUrl().startsWith("jdbc:clickhouse")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
jdbcUrl = getJdbcUrl();
} else {
StringBuilder builder = new StringBuilder();
@@ -76,8 +67,7 @@ public class CK extends DatasourceConfiguration {
jdbcUrl = appendCertParam(jdbcUrl, "sslCert", sslCert, "cert");
jdbcUrl = appendCertParam(jdbcUrl, "sslKey", sslKey, "key");
}
checkIllegalParameters(jdbcUrl);
return jdbcUrl;
return JdbcUrlSecurityPolicy.validate("ck", getDriver(), jdbcUrl, getExtraParams());
}
private String appendCertParam(String jdbcUrl, String paramName, String certContent, String filePrefix) {
@@ -135,14 +125,4 @@ public class CK extends DatasourceConfiguration {
private boolean containsParam(String jdbcUrl, String paramName) {
return Pattern.compile("(?i)([?&])" + Pattern.quote(paramName) + "=").matcher(jdbcUrl).find();
}
private void checkIllegalParameters(String jdbcUrl) {
String lowerUrl = jdbcUrl.toLowerCase();
for (String illegalParam : ILLEGAL_PARAMETERS) {
if (lowerUrl.contains(illegalParam.toLowerCase())) {
throw new SecurityException("Illegal parameter detected in JDBC URL: " + illegalParam);
}
}
}
}

View File

@@ -1,44 +1,22 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.exception.DEException;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Data
@Component("db2")
public class Db2 extends DatasourceConfiguration {
private String driver = "com.ibm.db2.jcc.DB2Driver";
private String extraParams = "";
@JsonIgnore
private List<String> illegalParameters = Arrays.asList(
// 原有参数如RMI相关
"java.naming.factory.initial", "java.naming.provider.url", "rmi",
// 新增LDAP协议及相关危险参数
"ldap://", "ldaps://", "java.naming.factory.object", "java.naming.factory.state",
// 其他JDBC危险参数
"autoDeserialize", "connectionProperties", "initSQL", "dns", "file", "ftp", "iiop", "corbaname", "iiopname"
);
public String getJdbc() {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
for (String illegalParameter : illegalParameters) {
if (getJdbcUrl().toLowerCase().contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
if (!getJdbcUrl().startsWith("jdbc:db2")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
return getJdbcUrl();
}
String url = "";
if (StringUtils.isEmpty(extraParams.trim())) {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
url = getJdbcUrl();
} else if (StringUtils.isEmpty(extraParams.trim())) {
if (StringUtils.isEmpty(getSchema())) {
url = "jdbc:db2://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getLHost().trim())
@@ -58,11 +36,6 @@ public class Db2 extends DatasourceConfiguration {
.replace("DATABASE", getDataBase().trim())
.replace("EXTRA_PARAMS", getExtraParams().trim());
}
for (String illegalParameter : illegalParameters) {
if (url.toLowerCase().contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
return url;
return JdbcUrlSecurityPolicy.validate("db2", getDriver(), url, getExtraParams());
}
}

View File

@@ -1,6 +1,6 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.exception.DEException;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
@@ -8,10 +8,6 @@ import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@EqualsAndHashCode(callSuper = true)
@Data
@Component("h2")
@@ -19,20 +15,11 @@ public class H2 extends DatasourceConfiguration {
private String driver = "org.h2.Driver";
public String getJdbc() {
for (String illegalParameter : getH2IllegalParameters()) {
if (jdbc.toUpperCase(Locale.ENGLISH).replace("\\", "").contains(illegalParameter)) {
DEException.throwException("Has illegal parameter: " + jdbc);
}
}
if (StringUtils.isNotEmpty(jdbc) && !jdbc.startsWith("jdbc:h2")) {
String jdbcUrl = StringUtils.defaultIfBlank(jdbc, getJdbcUrl());
if (StringUtils.isBlank(jdbcUrl)) {
DEException.throwException("Illegal jdbcUrl: " + jdbc);
}
return jdbc;
}
@JsonIgnore
private List<String> getH2IllegalParameters() {
return Arrays.asList("INIT", "RUNSCRIPT");
return JdbcUrlSecurityPolicy.validate("h2", getDriver(), jdbcUrl, getExtraParams());
}
}

View File

@@ -1,15 +1,11 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.exception.DEException;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
@Data
@@ -17,34 +13,12 @@ import java.util.regex.Pattern;
public class Impala extends DatasourceConfiguration {
private String driver = "com.cloudera.impala.jdbc.Driver";
private String extraParams = "";
@JsonIgnore
private List<String> illegalParameters = Arrays.asList(
// 原有非法参数
"autoDeserialize", "queryInterceptors", "statementInterceptors", "detectCustomCollations",
// 新增Kerberos认证相关危险参数漏洞利用核心参数
"krbJAASFile", "KrbJAASFile", "krb5.conf", "Krb5Conf",
// 新增JDNI/反序列化相关危险参数
"jndi", "JNDI", "java.naming.factory.initial", "java.naming.provider.url",
// 新增其他JDBC危险参数
"connectionProperties", "ConnectionProperties", "initSQL", "InitSQL"
);
private List<String> showTableSqls = Arrays.asList("show tables");
public String getJdbc() {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(getJdbcUrl()).toLowerCase().contains(illegalParameter.toLowerCase()) || URLDecoder.decode(getExtraParams()).contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
if (!getJdbcUrl().startsWith("jdbc:impala")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
return getJdbcUrl();
}
String jdbcUrl = "";
if (StringUtils.isEmpty(extraParams.trim())) {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
jdbcUrl = getJdbcUrl();
} else if (StringUtils.isEmpty(extraParams.trim())) {
jdbcUrl = "jdbc:impala://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getLHost().trim())
.replace("PORT", getLPort().toString().trim())
@@ -56,12 +30,7 @@ public class Impala extends DatasourceConfiguration {
.replace("DATABASE", getDataBase().trim())
.replace("EXTRA_PARAMS", getExtraParams().trim());
}
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(jdbcUrl).toLowerCase().contains(illegalParameter.toLowerCase()) || URLDecoder.decode(jdbcUrl).contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
return jdbcUrl;
return JdbcUrlSecurityPolicy.validate("impala", getDriver(), jdbcUrl, getExtraParams());
}
private static final Pattern DB_NAME_PATTERN = Pattern.compile("//[^/]+/([^?;]+)");

View File

@@ -1,33 +1,22 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.exception.DEException;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Data
@Component("mongo")
public class Mongo extends DatasourceConfiguration {
private String driver = "com.mysql.cj.jdbc.Driver";
private String extraParams = "characterEncoding=UTF-8&connectTimeout=5000&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull";
@JsonIgnore
private List<String> illegalParameters = Arrays.asList("autoDeserialize", "queryInterceptors", "statementInterceptors", "detectCustomCollations");
private List<String> showTableSqls = Arrays.asList("show tables");
public String getJdbc() {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
if (!getJdbcUrl().startsWith("jdbc:mysql")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
return getJdbcUrl();
}
String jdbcUrl = "";
if (StringUtils.isEmpty(extraParams.trim())) {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
jdbcUrl = getJdbcUrl();
} else if (StringUtils.isEmpty(extraParams.trim())) {
jdbcUrl = "jdbc:mysql://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getLHost().trim())
.replace("PORT", getLPort().toString().trim())
@@ -39,11 +28,6 @@ public class Mongo extends DatasourceConfiguration {
.replace("DATABASE", getDataBase().trim())
.replace("EXTRA_PARAMS", getExtraParams().trim());
}
for (String illegalParameter : illegalParameters) {
if (jdbcUrl.contains(illegalParameter)) {
throw new RuntimeException("Illegal parameter: " + illegalParameter);
}
}
return jdbcUrl;
return JdbcUrlSecurityPolicy.validate("mongo", getDriver(), jdbcUrl, getExtraParams());
}
}

View File

@@ -1,39 +1,22 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.exception.DEException;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
@Data
@Component("mysql")
public class Mysql extends DatasourceConfiguration {
private String driver = "com.mysql.cj.jdbc.Driver";
private String extraParams = "characterEncoding=UTF-8&connectTimeout=5000&useSSL=false&allowPublicKeyRetrieval=true&zeroDateTimeBehavior=convertToNull";
@JsonIgnore
private List<String> illegalParameters = Arrays.asList("maxAllowedPacket", "autoDeserialize", "queryInterceptors", "statementInterceptors", "detectCustomCollations", "allowloadlocalinfile", "allowUrlInLocalInfile", "allowLoadLocalInfileInPath", "allowMultiQueries");
private List<String> showTableSqls = Arrays.asList("show tables");
public String getJdbc() {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(getJdbcUrl()).toLowerCase().contains(illegalParameter.toLowerCase()) || URLDecoder.decode(getExtraParams()).contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
if (!getJdbcUrl().startsWith("jdbc:mysql")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
return getJdbcUrl();
}
String jdbcUrl = "";
if (StringUtils.isEmpty(extraParams.trim())) {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
jdbcUrl = getJdbcUrl();
} else if (StringUtils.isEmpty(extraParams.trim())) {
jdbcUrl = "jdbc:mysql://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getLHost().trim())
.replace("PORT", getLPort().toString().trim())
@@ -45,11 +28,6 @@ public class Mysql extends DatasourceConfiguration {
.replace("DATABASE", getDataBase().trim())
.replace("EXTRA_PARAMS", getExtraParams().trim());
}
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(jdbcUrl).toLowerCase().contains(illegalParameter.toLowerCase()) || URLDecoder.decode(jdbcUrl).contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
return jdbcUrl;
return JdbcUrlSecurityPolicy.validate("mysql", getDriver(), jdbcUrl, getExtraParams());
}
}

View File

@@ -1,13 +1,11 @@
package io.dataease.datasource.type;
import io.dataease.exception.DEException;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -16,41 +14,23 @@ import java.util.regex.Pattern;
public class Oracle extends DatasourceConfiguration {
private String driver = "oracle.jdbc.driver.OracleDriver";
private String extraParams = "";
private List<String> getOracleIllegalParameters() {
return Arrays.asList(
// 原有参数如RMI相关
"java.naming.factory.initial", "java.naming.provider.url", "rmi",
// 新增LDAP协议及相关危险参数
"ldap://", "ldaps://", "java.naming.factory.object", "java.naming.factory.state",
// 其他JDBC危险参数
"autoDeserialize", "connectionProperties", "initSQL", "dns", "file", "ftp"
);
}
public String getJdbc() {
String jdbcUrl;
if(StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")){
if (!getJdbcUrl().startsWith("jdbc:oracle")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
for (String illegalParameter : getOracleIllegalParameters()) {
if (getJdbcUrl().toLowerCase().contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal jdbcUrl: " + illegalParameter);
}
}
return getJdbcUrl();
}
if (StringUtils.isNotEmpty(getConnectionType()) && getConnectionType().equalsIgnoreCase("serviceName")) {
return "jdbc:oracle:thin:@HOSTNAME:PORT/DATABASE"
jdbcUrl = getJdbcUrl();
} else if (StringUtils.isNotEmpty(getConnectionType()) && getConnectionType().equalsIgnoreCase("serviceName")) {
jdbcUrl = "jdbc:oracle:thin:@HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getLHost().trim())
.replace("PORT", getLPort().toString().trim())
.replace("DATABASE", getDataBase().trim());
}else {
return "jdbc:oracle:thin:@HOSTNAME:PORT:DATABASE"
} else {
jdbcUrl = "jdbc:oracle:thin:@HOSTNAME:PORT:DATABASE"
.replace("HOSTNAME", getLHost().trim())
.replace("PORT", getLPort().toString().trim())
.replace("DATABASE", getDataBase().trim());
}
return JdbcUrlSecurityPolicy.validate("oracle", getDriver(), jdbcUrl, getExtraParams());
}
private static final Pattern SERVICE_PATTERN = Pattern.compile(":@//[^/]+/([^?]+)");

View File

@@ -1,15 +1,11 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.exception.DEException;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
@Data
@@ -17,23 +13,12 @@ import java.util.regex.Pattern;
public class Pg extends DatasourceConfiguration {
private String driver = "org.postgresql.Driver";
private String extraParams = "";
@JsonIgnore
private List<String> illegalParameters = Arrays.asList("socketFactory", "socketFactoryArg", "sslfactory", "sslhostnameverifier", "sslpasswordcallback", "authenticationPluginClassName");
public String getJdbc() {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(getJdbcUrl()).contains(illegalParameter)) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
if (!getJdbcUrl().startsWith("jdbc:postgresql")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
return getJdbcUrl();
}
String jdbcUrl = "";
if (StringUtils.isEmpty(extraParams.trim())) {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
jdbcUrl = getJdbcUrl();
} else if (StringUtils.isEmpty(extraParams.trim())) {
if (StringUtils.isEmpty(getSchema())) {
jdbcUrl = "jdbc:postgresql://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getLHost().trim())
@@ -54,12 +39,7 @@ public class Pg extends DatasourceConfiguration {
.replace("EXTRA_PARAMS", getExtraParams().trim());
}
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(jdbcUrl).toLowerCase().contains(illegalParameter.toLowerCase()) || URLDecoder.decode(jdbcUrl).contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
return jdbcUrl;
return JdbcUrlSecurityPolicy.validate("pg", getDriver(), jdbcUrl, getExtraParams());
}
private static final Pattern DB_NAME_PATTERN = Pattern.compile("//[^/]+/([^?]+)");

View File

@@ -1,50 +1,31 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.exception.DEException;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import static java.awt.SystemColor.info;
@Data
@Component("redshift")
public class Redshift extends DatasourceConfiguration {
private String driver = "com.amazon.redshift.jdbc42.Driver";
private String extraParams = "";
@JsonIgnore
private List<String> illegalParameters = Arrays.asList("socketFactory", "socketFactoryArg", "sslfactory", "sslhostnameverifier", "sslpasswordcallback", "authenticationPluginClassName", "IniFile");
public String getJdbc() {
String jdbcUrl;
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(getJdbcUrl()).contains(illegalParameter)) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
if (!getJdbcUrl().startsWith("jdbc:redshift")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
return getJdbcUrl();
jdbcUrl = getJdbcUrl();
} else {
jdbcUrl = "jdbc:redshift://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getLHost().trim())
.replace("PORT", getLPort().toString().trim())
.replace("DATABASE", getDataBase().trim());
}
String jdbcUrl = "jdbc:redshift://HOSTNAME:PORT/DATABASE"
.replace("HOSTNAME", getLHost().trim())
.replace("PORT", getLPort().toString().trim())
.replace("DATABASE", getDataBase().trim());
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(jdbcUrl).contains(illegalParameter)) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
return jdbcUrl;
return JdbcUrlSecurityPolicy.validate("redshift", getDriver(), jdbcUrl, getExtraParams());
}
private static final Pattern DB_NAME_PATTERN = Pattern.compile("//[^/]+/([^?]+)");

View File

@@ -1,15 +1,11 @@
package io.dataease.datasource.type;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.dataease.exception.DEException;
import io.dataease.datasource.security.JdbcUrlSecurityPolicy;
import io.dataease.extensions.datasource.vo.DatasourceConfiguration;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;
@Data
@@ -17,19 +13,12 @@ import java.util.regex.Pattern;
public class Sqlserver extends DatasourceConfiguration {
private String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private String extraParams = "";
@JsonIgnore
private List<String> illegalParameters = Arrays.asList("autoDeserialize", "queryInterceptors", "statementInterceptors", "detectCustomCollations", "jndi:", "rmi:", "ldap:", "ldaps:", "java.naming.factory.initial");
private List<String> showTableSqls = Arrays.asList("show tables");
public String getJdbc() {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
if (!getJdbcUrl().startsWith("jdbc:sqlserver")) {
DEException.throwException("Illegal jdbcUrl: " + getJdbcUrl());
}
return getJdbcUrl();
}
String jdbcUrl = "";
if (StringUtils.isEmpty(extraParams.trim())) {
if (StringUtils.isNoneEmpty(getUrlType()) && !getUrlType().equalsIgnoreCase("hostName")) {
jdbcUrl = getJdbcUrl();
} else if (StringUtils.isEmpty(extraParams.trim())) {
jdbcUrl = "jdbc:sqlserver://HOSTNAME:PORT;DatabaseName=DATABASE"
.replace("HOSTNAME", getLHost().trim())
.replace("PORT", getLPort().toString().trim())
@@ -41,12 +30,7 @@ public class Sqlserver extends DatasourceConfiguration {
.replace("DATABASE", getDataBase().trim())
.replace("EXTRA_PARAMS", getExtraParams().trim());
}
for (String illegalParameter : illegalParameters) {
if (URLDecoder.decode(jdbcUrl).toLowerCase().contains(illegalParameter.toLowerCase()) || URLDecoder.decode(jdbcUrl).contains(illegalParameter.toLowerCase())) {
DEException.throwException("Illegal parameter: " + illegalParameter);
}
}
return jdbcUrl;
return JdbcUrlSecurityPolicy.validate("sqlServer", getDriver(), jdbcUrl, getExtraParams());
}
private static final Pattern DB_NAME_PATTERN = Pattern.compile(";databaseName=([^;]+)");