java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatis Example模式SQL注入

浅谈MyBatis Example模式SQL注入风险

作者:就叫飞六吧

在使用MyBatis逆向工程生成的Example查询模式时,很多开发者看到XML中存在${}占位符就会担心SQL注入问题,本文就来介绍一下MyBatis Example模式SQL注入风险,感兴趣的可以了解一下

在使用MyBatis逆向工程生成的Example查询模式时,很多开发者看到XML中存在${}占位符就会担心SQL注入问题。但实际上,存在${}并不等同于存在SQL注入风险。本文将详细分析何时会存在真正的注入风险。

存在SQL注入的两个关键前提

前提一:Criteria存在自定义扩展且接受外部输入

MyBatis Generator生成的标准Criteria类是相对安全的,但如果开发者添加了自定义扩展方法,就可能引入风险:

// 危险的自定义扩展示例
public class MTaxSbPayExample {
    public static class Criteria extends GeneratedCriteria {
        
        // ❌ 危险:允许用户直接传入SQL条件
        public Criteria andCustomCondition(String sqlCondition, Object value) {
            addCriterion(sqlCondition, value, "custom");
            return (Criteria) this;
        }
        
        // ❌ 危险:动态表名或列名
        public Criteria andDynamicColumn(String columnName, String operator, Object value) {
            addCriterion(columnName + " " + operator, value, columnName);
            return (Criteria) this;
        }
    }
}

如果用户输入直接传递给这些方法:

// 恶意输入示例
String userInput = "1=1; DROP TABLE users;--";
example.createCriteria().andCustomCondition(userInput, "someValue");

前提二:Example对象作为接口参数且orderByClause被不当赋值

另一个风险点是orderByClause字段,因为ORDER BY子句通常需要使用${}来处理列名:

<if test="orderByClause != null">
  order by ${orderByClause}
</if>

危险场景:

// ❌ 危险:直接将用户输入作为排序条件
@RestController
public class DataController {
    
    public List<MTaxSbPay> getData(@RequestParam String sortBy) {
        MTaxSbPayExample example = new MTaxSbPayExample();
        // 直接使用用户输入,存在注入风险
        example.setOrderByClause(sortBy);  
        return mapper.selectByExample(example);
    }
}

恶意请求:

GET /getData?sortBy=id; DROP TABLE users;--

为什么存在${}不一定有SQL注入风险

1. 硬编码的安全使用

在标准的MyBatis Generator实现中,${criterion.condition}中的condition是硬编码的:

// 生成的安全方法
public Criteria andIdEqualTo(String value) {
    addCriterion("ID =", value, "id");  // "ID =" 是硬编码字符串
    return (Criteria) this;
}

对应的XML处理:

<when test="criterion.singleValue">
  and ${criterion.condition} #{criterion.value}
</when>

最终生成安全的SQL:

WHERE ID = ?  -- 参数: 用户输入值

2. 参数分离的设计模式

MyBatis Generator采用了条件与参数分离的设计:

这种设计确保了即使使用${},也不会直接拼接用户输入的内容。

3. 用户输入路径受限

标准的Criteria类只提供预定义的方法:

// 用户只能通过这些安全的方法构建查询
criteria.andIdEqualTo(userInput);      // 安全
criteria.andNameLike("%" + userInput + "%");  // 安全  
criteria.andStatusIn(Arrays.asList("ACTIVE", "INACTIVE"));  // 安全

用户无法直接控制criterion.condition的值,只能影响criterion.value,而后者是参数化处理的。

总结

MyBatis的${}占位符本身并不等同于SQL注入漏洞。关键在于:

标准的MyBatis Generator生成的Example代码通常是安全的,真正的风险往往来自于开发者的不当扩展和使用。

到此这篇关于浅谈MyBatis Example模式SQL注入风险的文章就介绍到这了,更多相关MyBatis Example模式SQL注入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文