sql 排序关键字 orderby注入风险处理

This commit is contained in:
Chopper711 2023-08-16 13:39:57 +08:00
parent d5f9fbf99d
commit 8104947aec
2 changed files with 29 additions and 16 deletions

View File

@ -20,7 +20,7 @@ public class SqlFilter {
"TABLE", "INDEX", "VIEW", "DROP", "ALTER", "COLUMN", "ADD", "SET", "GROUP", "BY", "TABLE", "INDEX", "VIEW", "DROP", "ALTER", "COLUMN", "ADD", "SET", "GROUP", "BY",
"HAVING", "ORDER", "ASC", "DESC", "LIKE", "IN", "BETWEEN", "IS", "NULL", "TRUE", "FALSE", "HAVING", "ORDER", "ASC", "DESC", "LIKE", "IN", "BETWEEN", "IS", "NULL", "TRUE", "FALSE",
"JOIN", "LEFT", "RIGHT", "INNER", "OUTER", "FULL", "ON", "AS", "DISTINCT", "COUNT", "JOIN", "LEFT", "RIGHT", "INNER", "OUTER", "FULL", "ON", "AS", "DISTINCT", "COUNT",
"MAX", "MIN", "SUM", "AVG" "MAX", "MIN", "SUM", "AVG", "IF", "RAND", "UPDATEXML", "EXTRACTVALUE", "LOAD_FILE", "SLEEP","OFFSET"
)); ));

View File

@ -1,15 +1,17 @@
package cn.lili.mybatis.util; package cn.lili.mybatis.util;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.text.CharSequenceUtil;
import cn.lili.common.utils.BeanUtil; import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.StringUtils; import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO; import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.SearchVO; import cn.lili.common.vo.SearchVO;
import cn.lili.modules.search.utils.SqlFilter;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -22,19 +24,21 @@ import java.util.List;
* @version v4.0 * @version v4.0
* @since 2020/11/26 15:23 * @since 2020/11/26 15:23
*/ */
@Slf4j
public class PageUtil { public class PageUtil {
//有order by 注入风险限制长度
static final Integer orderByLengthLimit = 20;
/** /**
* Mybatis-Plus分页封装 * Mybatis-Plus分页封装
* *
* @param page 分页VO * @param page 分页VO
* @param <T> 范型 * @param <T> 范型
* @return 分页响应 * @return 分页响应
*/ */
public static <T> Page<T> initPage(PageVO page) { public static <T> Page<T> initPage(PageVO page) {
Page<T> p;
int pageNumber = page.getPageNumber(); int pageNumber = page.getPageNumber();
int pageSize = page.getPageSize(); int pageSize = page.getPageSize();
String sort = page.getSort(); String sort = page.getSort();
@ -49,30 +53,39 @@ public class PageUtil {
if (pageSize > 100) { if (pageSize > 100) {
pageSize = 100; pageSize = 100;
} }
if (StrUtil.isNotBlank(sort)) {
Boolean isAsc = false; Page<T> p = new Page<>(pageNumber, pageSize);
if (StrUtil.isBlank(order)) {
isAsc = false; if (CharSequenceUtil.isNotBlank(sort)) {
} else {
if (sort.length() > orderByLengthLimit || SqlFilter.hit(sort)) {
log.error("排序字段长度超过限制或包含sql关键字请关注{}", sort);
return p;
}
boolean isAsc = false;
if (!CharSequenceUtil.isBlank(order)) {
if ("desc".equals(order.toLowerCase())) { if ("desc".equals(order.toLowerCase())) {
isAsc = false; isAsc = false;
} else if ("asc".equals(order.toLowerCase())) { } else if ("asc".equals(order.toLowerCase())) {
isAsc = true; isAsc = true;
} }
} }
p = new Page<>(pageNumber, pageSize);
if (isAsc) { if (isAsc) {
p.addOrder(OrderItem.asc(sort)); p.addOrder(OrderItem.asc(sort));
} else { } else {
p.addOrder(OrderItem.desc(sort)); p.addOrder(OrderItem.desc(sort));
} }
} else {
p = new Page<>(pageNumber, pageSize);
} }
return p; return p;
} }
private void orderByHandler() {
}
/** /**
* 生成条件搜索 全对象对比 equals * 生成条件搜索 全对象对比 equals
* 如果需要like 需要另行处理 * 如果需要like 需要另行处理
@ -87,14 +100,14 @@ public class PageUtil {
/** /**
* 生成条件搜索 全对象对比 * 生成条件搜索 全对象对比
* *
* @param object 对象 * @param object 对象
* @param searchVo 查询条件 * @param searchVo 查询条件
* @return 查询wrapper * @return 查询wrapper
*/ */
public static <T> QueryWrapper<T> initWrapper(Object object, SearchVO searchVo) { public static <T> QueryWrapper<T> initWrapper(Object object, SearchVO searchVo) {
QueryWrapper<T> queryWrapper = new QueryWrapper<>(); QueryWrapper<T> queryWrapper = new QueryWrapper<>();
//创建时间区间判定 //创建时间区间判定
if (searchVo != null && StrUtil.isNotBlank(searchVo.getStartDate()) && StrUtil.isNotBlank(searchVo.getEndDate())) { if (searchVo != null && CharSequenceUtil.isNotBlank(searchVo.getStartDate()) && CharSequenceUtil.isNotBlank(searchVo.getEndDate())) {
Date start = DateUtil.parse(searchVo.getStartDate()); Date start = DateUtil.parse(searchVo.getStartDate());
Date end = DateUtil.parse(searchVo.getEndDate()); Date end = DateUtil.parse(searchVo.getEndDate());
queryWrapper.between("create_time", start, DateUtil.endOfDay(end)); queryWrapper.between("create_time", start, DateUtil.endOfDay(end));
@ -156,8 +169,8 @@ public class PageUtil {
* 转换分页类型 * 转换分页类型
* *
* @param originPage 原分页 * @param originPage 原分页
* @param records 新分页数据 * @param records 新分页数据
* @param <T> 新类型 * @param <T> 新类型
* @return 新类型分页 * @return 新类型分页
*/ */
public static <T> IPage<T> convertPage(IPage originPage, List<T> records) { public static <T> IPage<T> convertPage(IPage originPage, List<T> records) {