一文吃透 MyBatis 执行 SQL 的全过程,附源码解析!

一文吃透 MyBatis 执行 SQL 的全过程,附源码解析!

🎯 MyBatis执行SQL的深入分析(含完整调用链)


✅ MyBatis注入链路结构

 [Controller] → [Service] → [DAO] → [Mapper(XML/注解)] → [SQL执行]

📌 注入可能发生在:Mapper 的 SQL 映射或注解中

  • 使用 ${}:直接拼接输入参数,存在 SQL 注入风险。
  • 使用 #{}:预编译处理参数,安全。

🧪 示例场景:用户查询功能存在SQL注入漏洞

👇 1. Controller 层

 @RestController
 @RequestMapping("/admin")
 public class AdminController {
 ​
     @Autowired
     private AdminService adminService;
 ​
     @GetMapping("/search")
     public List<Admin> search(@RequestParam String username) {
         return adminService.searchByUsername(username);
     }
 }
  • 用户访问:/admin/search?username=admin
  • 参数传入 Service 层

👇 2. Service 层

 @Service
 public class AdminService {
 ​
     @Autowired
     private AdminDAO adminDAO;
 ​
     public List<Admin> searchByUsername(String username) {
         return adminDAO.findByUsername(username);
     }
 }
  • 调用 DAO,无输入校验

👇 3. DAO 层

 @Repository
 public class AdminDAO {
 ​
     @Autowired
     private AdminMapper adminMapper;
 ​
     public List<Admin> findByUsername(String username) {
         return adminMapper.selectByUsername(username);
     }
 }

👇 4. Mapper 接口

 public interface AdminMapper {
     List<Admin> selectByUsername(@Param("username") String username);
 }

👇 5. Mapper XML 配置(存在注入风险)

 <select id="selectByUsername" parameterType="String" resultType="Admin">
     SELECT * FROM admin WHERE username = '${username}'
 </select>

🧩 注解型 SQL 映射(存在注入风险)

这种方式使用 MyBatis 的注解(如 @Select)在接口中直接编写 SQL,如下注解形式

 @Select("SELECT * FROM admin WHERE username = ${username}")
 List<Admin> selectByUsername(@Param("username") String username);

🔴 实际SQL:

 SELECT * FROM admin WHERE username = 'admin' OR '1'='1'

💥 构造攻击Payload

 /admin/search?username=admin' OR '1'='1

可绕过身份验证,查询全部用户。


🔧 安全修复建议

<select id="selectByUsername" parameterType="String" resultType="Admin">
    SELECT * FROM admin WHERE username = #{username}
</select>
 @Select("SELECT * FROM admin WHERE username = #{username}")

#{} 使用预编译参数,防止注入。


🔍 实战红队审计步骤

  1. 🔍 查找输入入口(Controller)
  2. 🔗 跟踪参数传递链(Service → DAO → Mapper)
  3. 📄 审计 Mapper XML/注解中的 SQL
  4. 🧪 构造Payload测试是否可注入

🛡 防御建议汇总

风险点修复方式说明
${param}替换为 #{param}避免字符串拼接
order by 动态排序<choose> 限制字段选择控制字段范围
like 模糊查询使用 CONCAT('%', #{value}, '%')安全拼接
in 条件查询使用 <foreach> 实现集合传参安全高效

🔚 总结

MyBatis 的 SQL 注入常因 ${} 使用不当或动态SQL拼接导致,从 Controller 到 XML 是一条完整的攻击链。建议开发和安全团队:

  • 全面替换 ${}#{}
  • 动态语句使用白名单控制;
  • 对高风险字段进行正则验证;
  • 辅以全局过滤器提升防御强度。

© 版权声明
THE END
喜欢就支持一下吧
点赞12赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容