Mybatis 混合预处理语句和 sql 注入

Posted

技术标签:

【中文标题】Mybatis 混合预处理语句和 sql 注入【英文标题】:Mybatis mix prepared statement with sql injection 【发布时间】:2021-06-21 12:34:07 【问题描述】:

我有一个查询,我希望 Mybatis 将它的一部分视为 sql 注入,也可以视为准备好的语句。我使用的是 Mybatis xml 文件而不是注释。这就是我想要做的......

我的 java 对象正在传递一个包含 processId 和开始和结束日期的参数映射。 processId 是 WHERE 子句之前查询“顶部”的一部分。开始和结束日期在 WHERE 子句中。所以我试图获得作为准备好的语句运行的好处,但直到运行时我才知道 processId。我的 sql 如下所示,但不确定如何将这两种构建 sql 的模式混合在一起。有什么办法可以做到吗?

   SELECT $processId, x, y, z FROM AnotherTable t
     WHERE t.startDate >= ? AND t.endDate <= ?```

【问题讨论】:

【参考方案1】:

我找到了答案。我只需要在我的插入标签中指定参数类型和参数映射属性...

<parameterMap type="java.util.Map" id="myParameterMap">
    <parameter property="startDate"/>
    <parameter property="endDate"/>
  </parameterMap>

  <insert  id="theSqlToRun" parameterType="java.util.Map" parameterMap="myParameterMap">
SELECT $processId, x, y, z FROM AnotherTable t
     WHERE t.startDate >= ? AND t.endDate <= ?
</insert>

【讨论】:

那是因为您决定不命名第二个和第三个参数,而是使用?(位置参数)。我建议不要这样做(并将它们命名为#startDate#endDate),因为将来修改 SQL 语句时很容易出错。 如doc 中所述,&lt;parameterMap /&gt; 已弃用。没有需要它的功能。不清楚processId在SQL语句中是用作常量值还是列名。如果它是一个常数值,@TheImpaler 的答案是正确的。如果processId 是列名,则@TheImpaler 的上述评论是正确的解决方案。【参考方案2】:

您不需要 SQL 注入(如$a)。普通参数(如#a)将起作用。你没有提到具体的数据库,但据我记得所有 JDBC 驱动程序我都在“选择列表”中尝试过支持参数。

你可以这样做:

<select id="mySelect">
  select #processId, x, y, z 
  from AnotherTable t
  where t.startDate >= #startDate AND t.endDate &lt;= #endDate
</select>

记得如上所示转义你的&lt;

【讨论】:

谢谢穿刺者。看起来我可以使用 $processId 以及 #startDate 和 #endDate 来混合“statement”和“prepared statement”,并按预期工作。 是的,您可以这样做,但除非绝对必要,否则最好避免 SQL 注入。下一个修改应用程序的开发人员可能不会像您那样小心,并且可能会在应用程序中打开一个很大的安全漏洞。

以上是关于Mybatis 混合预处理语句和 sql 注入的主要内容,如果未能解决你的问题,请参考以下文章

mybatis源码解析之如何调用JDBC的预处理器Statement完成交互

Mybatis #和$的区别

PDO预处理语句规避SQL注入攻击

mybatis如何传入java中拼接的sql语句

MySQL pdo预处理能防止sql注入的原因

00310_防止SQL注入