我在mybatis查询中使用'$'表示法:
<select id="queryOrgs" resultMap="orgLiteMap" parameterType="gov.cbrc.gzbanking.data.QueryRequest" >
select id, name from sys_orgs
<if test="filter != null">where id like #{filter, jdbcType=INTEGER} or name like #{filter, jdbcType=INTEGER}</if>
<if test="order != null">order by ${order}</if>
limit #{offset, jdbcType=INTEGER},#{fetch, jdbcType=INTEGER}
</select>
order参数可以是“id desc”,我需要担心sql注入吗?我们知道mybatis使用PreparedStatement
,如果mybatis针对“select”语句调用PreparedStatement#executeQuery()
,或者jdbc驱动程序实现在一次调用中不允许多个语句,那么sql注入是不可能的,我是对的吗?
如果在我的情况下可以进行sql注入,那么经过验证的方法是什么呢?
------------------------ 修改 --------------- --------
这足以检查order
参数是否有sql分隔符?
答案 0 :(得分:3)
如果order
直接来自用户,则可能会遇到麻烦。 您永远不应该信任用户输入。
回答你的问题:
如果将用户输入不变地发送到SQL,则使用${}
会向您公开SQL注入。以上两种方法都很脆弱:
\u003B
进行测试?攻击者还可以尝试做什么?)。始终执行您自己的转义和检查并发送您控制的值,而不是从用户收到的值。在代码中包含所有正确的值并将其发送。这只是确定用户想要哪一个并且如果你无法确定它而回退到默认值的问题,例如:
String userChoice = order.toLowerCase();
String safeOrder = null;
if ("id desc".equals(userChoice)) {
safeOrder = "id desc";
} else if ("id asc".equals(userChoice)) {
safeOrder = "id asc";
....
....
} else if ("name desc".equals(userChoice)) {
safeOrder = "name desc";
} else {
// if no clean match then maybe user tried something fishy...
// ... go with some default
safeOrder = "id desc"; // or null or whatever you like...
}
然后在您的映射中执行:
<if test="safeOrder != null">order by ${safeOrder}</if>
答案 1 :(得分:2)
见https://mybatis.github.io/mybatis-3/sqlmap-xml.html。部分&#39;字符串替换&#39;对此有正式评论。
接受用户的输入并将其提供给声明是不安全的 以这种方式不加修改。这导致潜在的SQL注入攻击 因此你应该禁止在这些字段中输入用户, 或者总是执行自己的逃脱和检查。
答案 2 :(得分:0)
我的答案是,mybatis sql模板可能是一个不错的选择。仅供参考:
<sql id="orderTypeSql">
<trim prefix=" ">
<if test="'desc'.equalsIgnoreCase(orderType)">desc</if>
</trim>
</sql>
<sql id="orderColumnSql">
<trim prefix="order by " suffix="" >
<choose>
<when test="orderColumn==null or orderColumn==''"></when>
<when test="orderColumn=='id'">
id<include refid="orderTypeSql"/>
</when>
<when test="orderColumn=='name'">
`name`<include refid="orderTypeSql"/>
</when>
</choose>
</trim>
</sql>
<select id="testOrderBy" resultType="User">
select
id,
`name`
from t_user
<include refid="orderColumnSql"/>
limit 0, 10
</select>