完善 SqlInjectionUtils.check 注入校验方法覆盖 UpdateWrapper 条件 checkSqlInjection() 注入检测方法

This commit is contained in:
hubin 2024-05-25 10:28:43 +08:00
parent 4a273f1ba2
commit 1c5ef2cfb6
6 changed files with 40 additions and 8 deletions

View File

@ -31,11 +31,11 @@ Mybatis 增强工具包 - 只做增强不做改变,简化`CRUD`操作
# 特别用户 # 特别用户
<p> <p>
<a href="https://flowlong.gitee.io/docs/preface.html?from=mp" target="_blank"> <a href="https://doc.flowlong.com?from=mp" target="_blank">
<img alt="AiZuDa-Logo" src="https://baomidou.com/img/azd01.png" width="160px" height="50px"> <img alt="AiZuDa-Logo" src="https://foruda.gitee.com/images/1715955628416785121/954c16ef_12260.png" width="160px" height="50px">
</a> </a>
<a href="https://gitee.com/gz-yami/mall4j?from=mp" target="_blank"> <a href="https://gitee.com/gz-yami/mall4j?from=mp" target="_blank">
<img alt="Mybatis-Plus-Logo" src="https://baomidou.com/img/mall4j.gif" width="160px" height="50px"> <img alt="Mybatis-Plus-Logo" src="https://foruda.gitee.com/images/1716599753022423252/fb0139cf_12260.png" width="160px" height="50px">
</a> </a>
<a href="http://github.crmeb.net/u/MyBatis-Plus" target="_blank"> <a href="http://github.crmeb.net/u/MyBatis-Plus" target="_blank">
<img alt="Crmeb-Logo" src="https://foruda.gitee.com/images/1685339553088166856/b0a6b1a4_12260.gif" width="160px" height="50px"> <img alt="Crmeb-Logo" src="https://foruda.gitee.com/images/1685339553088166856/b0a6b1a4_12260.gif" width="160px" height="50px">

View File

@ -31,11 +31,11 @@
# Special user # Special user
<p> <p>
<a href="https://flowlong.gitee.io/docs/preface.html?from=mp" target="_blank"> <a href="https://doc.flowlong.com?from=mp" target="_blank">
<img alt="AiZuDa-Logo" src="https://baomidou.com/img/azd01.png" width="160px" height="50px"> <img alt="AiZuDa-Logo" src="https://foruda.gitee.com/images/1715955628416785121/954c16ef_12260.png" width="160px" height="50px">
</a> </a>
<a href="https://gitee.com/gz-yami/mall4j?from=mp" target="_blank"> <a href="https://gitee.com/gz-yami/mall4j?from=mp" target="_blank">
<img alt="Mybatis-Plus-Logo" src="https://baomidou.com/img/mall4j.gif" width="160px" height="50px"> <img alt="Mybatis-Plus-Logo" src="https://foruda.gitee.com/images/1716599753022423252/fb0139cf_12260.png" width="160px" height="50px">
</a> </a>
</p> </p>

View File

@ -18,9 +18,11 @@ package com.baomidou.mybatisplus.core.conditions.update;
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper; import com.baomidou.mybatisplus.core.conditions.AbstractWrapper;
import com.baomidou.mybatisplus.core.conditions.SharedString; import com.baomidou.mybatisplus.core.conditions.SharedString;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments; import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -66,6 +68,28 @@ public class UpdateWrapper<T> extends AbstractWrapper<T, String, UpdateWrapper<T
this.sqlFirst = sqlFirst; this.sqlFirst = sqlFirst;
} }
/**
* 检查 SQL 注入过滤
*/
private boolean checkSqlInjection;
/**
* 开启检查 SQL 注入
*/
public UpdateWrapper<T> checkSqlInjection() {
this.checkSqlInjection = true;
return this;
}
@Override
protected String columnToString(String column) {
if (checkSqlInjection && SqlInjectionUtils.check(column)) {
throw new MybatisPlusException("Discovering SQL injection column: " + column);
}
return column;
}
@Override @Override
public String getSqlSet() { public String getSqlSet() {
if (CollectionUtils.isEmpty(sqlSet)) { if (CollectionUtils.isEmpty(sqlSet)) {

View File

@ -29,7 +29,7 @@ public class SqlInjectionUtils {
* SQL语法检查正则符合两个关键字有先后顺序才算匹配 * SQL语法检查正则符合两个关键字有先后顺序才算匹配
*/ */
private static final Pattern SQL_SYNTAX_PATTERN = Pattern.compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" + private static final Pattern SQL_SYNTAX_PATTERN = Pattern.compile("(insert|delete|update|select|create|drop|truncate|grant|alter|deny|revoke|call|execute|exec|declare|show|rename|set)" +
"\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)|(select\\s*\\*\\s*from\\s+)|(and|or)\\s+.*(like|=|>|<|in|between|is|not|exists)", Pattern.CASE_INSENSITIVE); "\\s+.*(into|from|set|where|table|database|view|index|on|cursor|procedure|trigger|for|password|union|and|or)|(select\\s*\\*\\s*from\\s+)|(and|or)\\s+.*", Pattern.CASE_INSENSITIVE);
/** /**
* 使用';或注释截断SQL检查正则 * 使用';或注释截断SQL检查正则
*/ */

View File

@ -1,7 +1,9 @@
package com.baomidou.mybatisplus.core.conditions; package com.baomidou.mybatisplus.core.conditions;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.test.User; import com.baomidou.mybatisplus.test.User;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
/** /**
@ -12,7 +14,7 @@ class UpdateWrapperTest extends BaseWrapperTest {
@Test @Test
void test1() { void test1() {
UpdateWrapper<User> wrapper = new UpdateWrapper<User>() UpdateWrapper<User> wrapper = new UpdateWrapper<User>().checkSqlInjection().eq("hi=1 or a", 123)
.set("name", "a", "typeHandler=org.apache.ibatis.type.StringTypeHandler") .set("name", "a", "typeHandler=org.apache.ibatis.type.StringTypeHandler")
.set("name", "a", "typeHandler=org.apache.ibatis.type.StringTypeHandler,jdbcType=VARCHAR") .set("name", "a", "typeHandler=org.apache.ibatis.type.StringTypeHandler,jdbcType=VARCHAR")
.set("name", "a", "typeHandler=org.apache.ibatis.type.StringTypeHandler,jdbcType=VARCHAR,numericScale=2"); .set("name", "a", "typeHandler=org.apache.ibatis.type.StringTypeHandler,jdbcType=VARCHAR,numericScale=2");
@ -21,5 +23,6 @@ class UpdateWrapperTest extends BaseWrapperTest {
"name=#{ew.paramNameValuePairs.MPGENVAL2,typeHandler=org.apache.ibatis.type.StringTypeHandler,jdbcType=VARCHAR}," + "name=#{ew.paramNameValuePairs.MPGENVAL2,typeHandler=org.apache.ibatis.type.StringTypeHandler,jdbcType=VARCHAR}," +
"name=#{ew.paramNameValuePairs.MPGENVAL3,typeHandler=org.apache.ibatis.type.StringTypeHandler,jdbcType=VARCHAR,numericScale=2}"); "name=#{ew.paramNameValuePairs.MPGENVAL3,typeHandler=org.apache.ibatis.type.StringTypeHandler,jdbcType=VARCHAR,numericScale=2}");
logParams(wrapper); logParams(wrapper);
Assertions.assertThrows(MybatisPlusException.class, wrapper::getSqlSegment);
} }
} }

View File

@ -55,6 +55,11 @@ import org.junit.jupiter.api.Test;
assertSql(false,"ORDER BY field(status,'SUCCESS','FAILED','CLOSED')"); assertSql(false,"ORDER BY field(status,'SUCCESS','FAILED','CLOSED')");
assertSql(true,"ORDER BY id,'SUCCESS',''-- FAILED','CLOSED'"); assertSql(true,"ORDER BY id,'SUCCESS',''-- FAILED','CLOSED'");
assertSql(true, "or 1 = 1"); assertSql(true, "or 1 = 1");
assertSql(true, "and 1 = 1");
assertSql(true, "hi = 1 or abc");
assertSql(true, "(hi = 1) and abc");
assertSql(false, "orAnd");
assertSql(false, "andOr");
} }
private void assertSql(boolean injection, String sql) { private void assertSql(boolean injection, String sql) {