Merge pull request #4818 from dataease/pr@dev@fix_sql_inject

perf: sql注入bug-issue#4795
This commit is contained in:
fit2cloud-chenyw 2023-03-20 13:02:32 +08:00 committed by GitHub
commit ca69db7bff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 108 additions and 1 deletions

View File

@ -0,0 +1,17 @@
package io.dataease.auth.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Documented
@Target(ElementType.METHOD)
@Retention(RUNTIME)
public @interface SqlInjectValidator {
String[] value() default {};
}

View File

@ -0,0 +1,68 @@
package io.dataease.auth.aop;
import cn.hutool.core.util.ArrayUtil;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.commons.exception.DEException;
import io.dataease.controller.sys.base.BaseGridRequest;
import org.apache.commons.collections4.CollectionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@Component
@Aspect
public class SqlInjectAop {
@Around(value = "@annotation(io.dataease.auth.annotation.SqlInjectValidator)")
public Object around(ProceedingJoinPoint point) {
try {
Signature signature = point.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
Object[] args = point.getArgs();
if (args == null || args.length == 0) {
return point.proceed();
}
BaseGridRequest request = null;
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof BaseGridRequest) {
request = (BaseGridRequest) args[i];
break;
}
}
if (request == null) return point.proceed(args);
SqlInjectValidator annotation = AnnotationUtils.findAnnotation(method, SqlInjectValidator.class);
String[] value = annotation.value();
boolean illegal = isIllegal(value, request.getOrders());
if (illegal) {
DEException.throwException("Illegal order exp");
}
return point.proceed(args);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
private boolean isIllegal(String[] value, List<String> orderList) {
if (CollectionUtils.isEmpty(orderList) || ArrayUtil.isEmpty(value)) return false;
Set<String> wordList = Arrays.stream(value).collect(Collectors.toSet());
wordList.add("asc");
wordList.add("desc");
return orderList.stream().anyMatch(exp ->
Arrays.stream(exp.toLowerCase().split(",")).anyMatch(word ->
Arrays.stream(word.split(" ")).anyMatch(item ->
!wordList.contains(item))));
}
}

View File

@ -225,7 +225,7 @@ public class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrappe
if (Arrays.stream(whiteLists.split(",")).anyMatch(item -> url.indexOf(item) != -1)) return false;
}
Pattern pattern= Pattern.compile("(.*\\=.*\\-\\-.*)|(.*(\\+).*)|(.*\\w+(%|\\$|#|&)\\w+.*)|(.*\\|\\|.*)|(.*\\s+(and|or)\\s+.*)" +
"|(.*\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|sleep|extractvalue|updatexml|substring|database|concat|rand)\\b.*)");
"|(.*\\b(select|update|union|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|sleep|extractvalue|updatexml|substring|database|concat|rand|gtid_subset)\\b.*)");
Matcher matcher=pattern.matcher(orders.toLowerCase());
return matcher.find();
}

View File

@ -2,6 +2,7 @@ package io.dataease.controller.panel.api;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.plugins.common.base.domain.PanelShare;
import io.dataease.commons.constants.DePermissionType;
import io.dataease.controller.request.panel.PanelShareFineDto;
@ -30,6 +31,7 @@ public interface ShareApi {
@ApiOperation("查询分享给我")
@PostMapping("/treeList")
@SqlInjectValidator(value = {"s.create_time"})
List<PanelShareDto> treeList(BaseGridRequest request);
@ApiOperation("查询我分享的")

View File

@ -2,6 +2,7 @@ package io.dataease.controller.panel.api;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.commons.constants.DePermissionType;
import io.dataease.controller.sys.base.BaseGridRequest;
import io.dataease.dto.panel.PanelStoreDto;
@ -31,6 +32,7 @@ public interface StoreApi {
@ApiOperation("查询收藏")
@PostMapping("/list")
@SqlInjectValidator(value = {"s.create_time"})
List<PanelStoreDto> list(@RequestBody BaseGridRequest request);

View File

@ -3,6 +3,7 @@ package io.dataease.controller.sys;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.service.AuthUserService;
import io.dataease.plugins.common.base.domain.SysMsgChannel;
import io.dataease.plugins.common.base.domain.SysMsgSetting;
@ -47,6 +48,7 @@ public class MsgController {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "msgRequest", value = "查询条件", required = true)
})
@SqlInjectValidator(value = {"create_time", "type_id"})
public Pager<List<MsgGridDto>> messages(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody MsgRequest msgRequest) {
Long userId = AuthUtils.getUser().getUserId();
List<Long> typeIds = null;

View File

@ -1,5 +1,6 @@
package io.dataease.controller.sys;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.commons.utils.BeanUtils;
import io.dataease.controller.ResultHolder;
import io.dataease.controller.sys.base.BaseGridRequest;
@ -40,6 +41,7 @@ public class SysDeptController extends ResultHolder {
}
@PostMapping("/search")
@SqlInjectValidator({"name"})
public List<DeptNodeResponse> search(@RequestBody BaseGridRequest request){
List<SysDept> nodes = deptService.nodesTreeByCondition(request);
List<DeptNodeResponse> nodeResponses = nodes.stream().map(node -> {

View File

@ -3,6 +3,7 @@ package io.dataease.controller.sys;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.commons.utils.PageUtils;
import io.dataease.commons.utils.Pager;
import io.dataease.controller.handler.annotation.I18n;
@ -36,6 +37,7 @@ public class SysLogController {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@SqlInjectValidator(value = {"time"})
public Pager<List<SysLogGridDTO>> logGrid(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody KeyGridRequest request) {
request = logService.logRetentionProxy(request);

View File

@ -2,6 +2,7 @@ package io.dataease.controller.sys;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.plugins.common.base.domain.MyPlugin;
import io.dataease.commons.utils.PageUtils;
import io.dataease.commons.utils.Pager;
@ -30,6 +31,7 @@ public class SysPluginController {
@ApiOperation("查询已安装插件")
@PostMapping("/pluginGrid/{goPage}/{pageSize}")
@RequiresPermissions("plugin:read")
@SqlInjectValidator(value = {"install_time"})
public Pager<List<MyPlugin>> pluginGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody BaseGridRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
return PageUtils.setPageInfo(page, pluginService.query(request));

View File

@ -5,6 +5,7 @@ import com.github.pagehelper.PageHelper;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import io.dataease.auth.annotation.DeLog;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.api.dto.CurrentUserDto;
import io.dataease.auth.entity.AccountLockStatus;
import io.dataease.auth.service.AuthUserService;
@ -78,6 +79,7 @@ public class SysUserController {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@SqlInjectValidator(value = {"create_time", "u.enabled", "nick_name", "u.dept_id"})
public Pager<List<SysUserGridResponse>> userGrid(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody KeyGridRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);
@ -102,6 +104,7 @@ public class SysUserController {
@ApiIgnore
@PostMapping("/userLists")
@SqlInjectValidator({"nick_name", "create_time"})
public List<SysUserGridResponse> userLists(@RequestBody BaseGridRequest request) {
KeyGridRequest keyGridRequest = BeanUtils.copyBean(new KeyGridRequest(), request);
return sysUserService.query(keyGridRequest);
@ -224,6 +227,7 @@ public class SysUserController {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@SqlInjectValidator({"create_time", "update_time"})
public Pager<List<SysRole>> roleGrid(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody BaseGridRequest request) {
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);

View File

@ -6,6 +6,7 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.DeLog;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.service.ExtAuthService;
import io.dataease.commons.constants.AuthConstants;
import io.dataease.commons.constants.DePermissionType;
@ -155,6 +156,7 @@ public class XDeptServer {
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@PostMapping("/userGrid/{goPage}/{pageSize}")
@SqlInjectValidator(value = {"dept_name", "nick_name"})
public Pager<List<DeptUserItemDTO>> userGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackDeptUserRequest request) {
DeptXpackService deptService = SpringContextUtil.getBean(DeptXpackService.class);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);

View File

@ -5,6 +5,7 @@ import cn.hutool.core.util.ArrayUtil;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.DeRateLimiter;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.api.dto.CurrentUserDto;
import io.dataease.commons.exception.DEException;
import io.dataease.commons.model.excel.ExcelSheetModel;
@ -59,6 +60,7 @@ public class XEmailTaskServer {
@RequiresPermissions("task-email:read")
@PostMapping("/queryTasks/{goPage}/{pageSize}")
@SqlInjectValidator(value = {"create_time"})
public Pager<List<XpackTaskGridDTO>> queryTask(@PathVariable int goPage, @PathVariable int pageSize,
@RequestBody XpackGridRequest request) {
EmailXpackService emailXpackService = SpringContextUtil.getBean(EmailXpackService.class);

View File

@ -5,6 +5,7 @@ import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.dataease.auth.annotation.DeLog;
import io.dataease.auth.annotation.DePermission;
import io.dataease.auth.annotation.SqlInjectValidator;
import io.dataease.auth.service.ExtAuthService;
import io.dataease.commons.constants.AuthConstants;
import io.dataease.commons.constants.DePermissionType;
@ -93,6 +94,7 @@ public class XRoleServer {
@ApiImplicitParam(paramType = "path", name = "pageSize", value = "页容量", required = true, dataType = "Integer"),
@ApiImplicitParam(name = "request", value = "查询条件", required = true)
})
@SqlInjectValidator(value = {"create_time", "name"})
public Pager<List<XpackRoleDto>> roleGrid(@PathVariable int goPage, @PathVariable int pageSize, @RequestBody XpackGridRequest request) {
RoleXpackService roleXpackService = SpringContextUtil.getBean(RoleXpackService.class);
Page<Object> page = PageHelper.startPage(goPage, pageSize, true);