mirror of
http://192.168.1.205:9980/cf_devdept2/cf_imes_server.git
synced 2026-08-14 05:42:06 +08:00
1、性别校验器空不校验;2、报表sql相关入参新增支持注入校验;
This commit is contained in:
+2
@@ -1,5 +1,6 @@
|
|||||||
package com.cf.imes.module.report.controller.admin.dataset.vo;
|
package com.cf.imes.module.report.controller.admin.dataset.vo;
|
||||||
|
|
||||||
|
import com.cf.imes.module.report.validation.datasource.SqlParamInjectionValid;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -37,5 +38,6 @@ public class ReportDatasetParameterVO implements Serializable {
|
|||||||
* 默认值
|
* 默认值
|
||||||
*/
|
*/
|
||||||
@Schema(description = "参数默认值")
|
@Schema(description = "参数默认值")
|
||||||
|
@SqlParamInjectionValid
|
||||||
private String defaultValue;
|
private String defaultValue;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -1,5 +1,6 @@
|
|||||||
package com.cf.imes.module.report.controller.admin.dataset.vo;
|
package com.cf.imes.module.report.controller.admin.dataset.vo;
|
||||||
|
|
||||||
|
import com.cf.imes.module.report.validation.datasource.SqlIllegalValid;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@@ -42,6 +43,7 @@ public class ReportDatasetSaveReqVO implements Serializable {
|
|||||||
private Long datasourceId;
|
private Long datasourceId;
|
||||||
|
|
||||||
@Schema(description = "动态查询SQL")
|
@Schema(description = "动态查询SQL")
|
||||||
|
@SqlIllegalValid
|
||||||
private String sql;
|
private String sql;
|
||||||
|
|
||||||
@Schema(description = "bean数据源方法名")
|
@Schema(description = "bean数据源方法名")
|
||||||
|
|||||||
+2
@@ -1,5 +1,6 @@
|
|||||||
package com.cf.imes.module.report.controller.admin.datasource.vo;
|
package com.cf.imes.module.report.controller.admin.datasource.vo;
|
||||||
|
|
||||||
|
import com.cf.imes.module.report.validation.datasource.SqlParamInjectionValid;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -38,5 +39,6 @@ public class ReportDatasourceParameterVO implements Serializable {
|
|||||||
* 默认值
|
* 默认值
|
||||||
*/
|
*/
|
||||||
@Schema(description = "参数默认值")
|
@Schema(description = "参数默认值")
|
||||||
|
@SqlParamInjectionValid
|
||||||
private String defaultValue;
|
private String defaultValue;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -1,5 +1,6 @@
|
|||||||
package com.cf.imes.module.report.controller.admin.datasource.vo;
|
package com.cf.imes.module.report.controller.admin.datasource.vo;
|
||||||
|
|
||||||
|
import com.cf.imes.module.report.validation.datasource.SqlIllegalValid;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
@@ -29,6 +30,7 @@ public class ReportDatasourcePreviewReqVO {
|
|||||||
|
|
||||||
@Schema(description = "查询语句")
|
@Schema(description = "查询语句")
|
||||||
@NotBlank(message = "查询语句不能为空")
|
@NotBlank(message = "查询语句不能为空")
|
||||||
|
@SqlIllegalValid
|
||||||
private String sql;
|
private String sql;
|
||||||
|
|
||||||
@Schema(description = "查询参数列表")
|
@Schema(description = "查询参数列表")
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package com.cf.imes.module.report.validation.datasource;
|
||||||
|
|
||||||
|
import javax.validation.Constraint;
|
||||||
|
import javax.validation.Payload;
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 非法sql校验注解
|
||||||
|
*
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2024/10/21 18:42
|
||||||
|
*/
|
||||||
|
@Target({
|
||||||
|
ElementType.FIELD,
|
||||||
|
ElementType.PARAMETER,
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Constraint(
|
||||||
|
validatedBy = {SqlIllegalValidator.class}
|
||||||
|
)
|
||||||
|
public @interface SqlIllegalValid {
|
||||||
|
String message() default "sql语句非法输入,请检查";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
}
|
||||||
+137
@@ -0,0 +1,137 @@
|
|||||||
|
package com.cf.imes.module.report.validation.datasource;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 非法sql校验器
|
||||||
|
*
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2024/10/21 18:44
|
||||||
|
*/
|
||||||
|
public class SqlIllegalValidator implements ConstraintValidator<SqlIllegalValid, String> {
|
||||||
|
|
||||||
|
private static final Pattern annotationPattern = Pattern.compile("/\\*[\\s\\S]*\\*/");
|
||||||
|
|
||||||
|
private static final String[] someKeywordPattern = new String[]{"chr\\s*\\(", "mid\\s*\\(", " char\\s*\\(", "sleep\\s*\\(", "user\\s*\\(", "show\\s+tables", "user[\\s]*\\([\\s]*\\)", "show\\s+databases", "sleep\\(\\d*\\)", "sleep\\(.*\\)"};
|
||||||
|
|
||||||
|
private static final List<String> specialSymbolList = new ArrayList<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
specialSymbolList.add(";");
|
||||||
|
specialSymbolList.add("+");
|
||||||
|
specialSymbolList.add("--");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(String sql, ConstraintValidatorContext context) {
|
||||||
|
if (StringUtils.isEmpty(sql)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 校验注释
|
||||||
|
if (hasAnnotation(sql)) {
|
||||||
|
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
|
||||||
|
context.buildConstraintViolationWithTemplate("SQL中不允许包含注释,存在安全风险").addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
sql = sql.toLowerCase();
|
||||||
|
sql = sql.replaceAll("/\\*.*\\*/", "");
|
||||||
|
// 敏感关键字数组
|
||||||
|
String[] arrayOfSensitiveKey = "exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|insert |alter |delete |grant |update |drop |master |truncate |declare |--|".split("\\|");
|
||||||
|
// 校验敏感关键字
|
||||||
|
for (byte b = 0; b < arrayOfSensitiveKey.length; b++) {
|
||||||
|
if (checkSensitiveKey(sql, arrayOfSensitiveKey[b])) {
|
||||||
|
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
|
||||||
|
context.buildConstraintViolationWithTemplate("SQL不合法,存在注入风险").addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 校验一些函数关键字
|
||||||
|
for (String skw : someKeywordPattern) {
|
||||||
|
String someKeywordStr = ".*" + skw + ".*";
|
||||||
|
if (Pattern.matches(someKeywordStr, sql)) {
|
||||||
|
context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
|
||||||
|
context.buildConstraintViolationWithTemplate("SQL不合法,存在注入风险").addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查敏感关键字
|
||||||
|
*
|
||||||
|
* @param sql
|
||||||
|
* @param sensitiveKey
|
||||||
|
* @return true:带敏感关键字,反之不带
|
||||||
|
*/
|
||||||
|
private boolean checkSensitiveKey(String sql, String sensitiveKey) {
|
||||||
|
if (sql.startsWith(sensitiveKey.trim())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (sql.contains(sensitiveKey)) {
|
||||||
|
String sk1 = " " + sensitiveKey;
|
||||||
|
if (specialSymbolList.contains(sensitiveKey)) {
|
||||||
|
sk1 = sensitiveKey;
|
||||||
|
}
|
||||||
|
if (sql.contains(sk1)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
String sk2 = "\\s+\\S+" + sensitiveKey;
|
||||||
|
List<String> list = matchInjectKeyword(sk2, sql);
|
||||||
|
for (String keyword : list) {
|
||||||
|
if (keyword.contains("%") || keyword.contains("+") || keyword.contains("#") || keyword.contains("/") || keyword.contains(")")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验注释
|
||||||
|
*
|
||||||
|
* @param sql
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private boolean hasAnnotation(String sql) {
|
||||||
|
// 不允许存在注释
|
||||||
|
if (sql.contains("--")) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Matcher var1 = annotationPattern.matcher(sql);
|
||||||
|
if (var1.find()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匹配注入关键字
|
||||||
|
*
|
||||||
|
* @param sensitiveKey
|
||||||
|
* @param sql
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<String> matchInjectKeyword(String sensitiveKey, CharSequence sql) {
|
||||||
|
Pattern paramPattern = Pattern.compile(sensitiveKey, 32);
|
||||||
|
List<String> paramT = new ArrayList<>();
|
||||||
|
if (ObjectUtil.isAllNotEmpty(paramPattern, sql)) {
|
||||||
|
Matcher matcher = paramPattern.matcher(sql);
|
||||||
|
while (matcher.find()) {
|
||||||
|
paramT.add(matcher.group(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paramT;
|
||||||
|
}
|
||||||
|
}
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package com.cf.imes.module.report.validation.datasource;
|
||||||
|
|
||||||
|
import javax.validation.Constraint;
|
||||||
|
import javax.validation.Payload;
|
||||||
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql参数注入攻击校验注解
|
||||||
|
*
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2024/10/25 10:30
|
||||||
|
*/
|
||||||
|
@Target({
|
||||||
|
ElementType.FIELD,
|
||||||
|
ElementType.PARAMETER,
|
||||||
|
})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
@Constraint(
|
||||||
|
validatedBy = {SqlParamInjectionValidator.class}
|
||||||
|
)
|
||||||
|
public @interface SqlParamInjectionValid {
|
||||||
|
String message() default "sql查询参数默认值非法输入,请检查";
|
||||||
|
|
||||||
|
Class<?>[] groups() default {};
|
||||||
|
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.cf.imes.module.report.validation.datasource;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import javax.validation.ConstraintValidator;
|
||||||
|
import javax.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql参数注入攻击校验器
|
||||||
|
*
|
||||||
|
* @author Gqr
|
||||||
|
* @since 2024/10/25 10:30
|
||||||
|
*/
|
||||||
|
public class SqlParamInjectionValidator implements ConstraintValidator<SqlParamInjectionValid, String> {
|
||||||
|
@Override
|
||||||
|
public boolean isValid(String value, ConstraintValidatorContext context) {
|
||||||
|
if (StringUtils.isEmpty(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// mybatisplus工具校验注入攻击
|
||||||
|
return !SqlInjectionUtils.check(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -1,5 +1,6 @@
|
|||||||
package com.cf.imes.module.system.validation.user;
|
package com.cf.imes.module.system.validation.user;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.cf.imes.module.system.enums.common.SexEnum;
|
import com.cf.imes.module.system.enums.common.SexEnum;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
@@ -16,6 +17,9 @@ public class SexValidator implements ConstraintValidator<SexValid, Integer> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isValid(Integer value, ConstraintValidatorContext context) {
|
public boolean isValid(Integer value, ConstraintValidatorContext context) {
|
||||||
|
if (ObjectUtil.isNull(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
for (SexEnum sexEnum : SexEnum.values()) {
|
for (SexEnum sexEnum : SexEnum.values()) {
|
||||||
if (Objects.equals(sexEnum.getSex(), value)) {
|
if (Objects.equals(sexEnum.getSex(), value)) {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user