<codeclass="language-xml"><select id="findByUserNameVuln" resultType="User"> select * from users where username like '%${_parameter}%' </select></code>
安全用法:使用数据库函数实现预编译,避免直接拼接:
1 2 3
<codeclass="language-xml"><select id="findByUserNameSec" resultType="User"> select * from users where username like concat('%', #{_parameter}, '%') </select></code>
2. in多值查询
危险用法:直接用${ }拼接in语句,会导致注入风险:
1 2 3
<codeclass="language-xml"><select id="findByUserNameVuln04" resultType="User"> select * from users where id in (${id}) </select></code>
安全用法:使用foreach循环生成占位符,实现参数绑定:
1 2 3 4 5 6
<codeclass="language-xml"><select id="selectBookByIds" parameterType="list" resultType="Book"> SELECT * FROM Book WHERE id IN <foreach collection="list" item="id" open="(" separator="," close=")"> #{id} </foreach> </select></code>
3. order by排序
危险用法:因为#{ }会给字段加引号,导致排序失效,所以错误地使用${ }进行拼接:
1 2 3
<codeclass="language-xml"><select id="getUsersBySort" resultType="User"> SELECT * FROM users ORDER BY ${sortColumn} </select></code>
安全用法:可以采用字段列数预编译的方式,或者严格过滤字段名,只允许白名单中的字段参与排序。
(三)实战审计案例
以某医院管理系统(Spring Boot + MyBatis)为例:
审计入口:在 Mapper 文件中搜索${关键字,定位可能存在风险的代码位置。
漏洞代码:发现存在SELECT distinct ${column} FROM users这样的代码,其中column由路由参数传入,攻击者可以控制该参数。