休眠 SQL 注入 - Fortify 360

信息安全 sql注入 休眠
2021-09-02 13:36:06

我正在使用 Fortify 360 来分析我的代码的安全性。Fortify 已经确定了一种基于 Hibernate 的删除方法,可以根据传入的对象执行删除。我对 hibernate 的理解是,hibernate 会根据对象 id 删除与对象关联的表中的一行(id 为一个号码)。Fortify 已将此标记为 SQL 注入:休眠(输入验证和表示,数据流)。Fortify 似乎不喜欢 Hibernate 使用未经验证的输入执行动态 SQL 语句。是否需要进行某种修复,或者只是将其作为降低风险的警告?

public List findByItemProp(String propName, Object value){
   try{
     String qs = "from ItemTypes as model where model."+ propName +"= ?"; /* <-- flagged by Fortify */
     Query qo = getSession().createQuery(qs);
     qo.setParameter(0, value);
     return qo.list();
   } catch (){}
 }
3个回答

恐怕这份报告可能过于缺乏细节,无法提供诊断。如果没有看到代码,我无法为您诊断此问题。

当您没有采取任何措施减轻它并且不了解该警告是否代表可利用的漏洞时,您绝对不应该将静态分析警告视为“减轻风险”。

我建议您首先对自己进行有关 SQL 注入、安全 Hibernate 以及此特定警告的教育。Fortify 很可能有在线帮助,提供有关此警告的详细说明;你应该从阅读开始。阅读以下有关Hibernate 中 SQL 注入的Fortify 背景资料我还推荐以下文章:SQL 注入通常如何在 Spring/Hibernate 设置中停止ORM 注入,以及如何避免 Hibernate 中的 SQL 注入(A Hibernate Urban Legend)


更新(4/20): 我看到您更新了问题以包含代码。谢谢。您提供的代码确实可疑,我认为 Fortify 抱怨该代码是合理的。查看此代码,无法验证传递给的查询createQuery()是编译时常量,这就是 Fortify 发出警告消息的原因。

基本上,您显示的代码似乎是使用字符串连接构造 SQL 查询。那很危险。如果propName可以受到攻击者的影响,那么你就有了一个可能的 SQL 注入漏洞。最好避免以这种方式构造 SQL 查询。

特别是,有一个神话,即使用准备好的语句(或参数化查询)本质上不受 SQL 注入的影响。这是真的,但前提是查询本身是一个不受攻击者影响的编译时常量如果您将不受信任的数据插入查询本身,那么在准备好的语句中使用它并不会神奇地使您安全。

所以最好的做法是,当你使用准备好的语句时,确保查询可以很容易地被验证为编译时常量(并且不会受到攻击者的影响)。

总结一下一般的经验法则: (1) 不要使用字符串连接来构建 SQL 查询。(2) 当你想要对运行时值有一些依赖时,使用准备好的语句来绑定运行时值。(3) 确保您用于创建准备好的语句的查询可以很容易地验证为编译时常量。遵循这些做法应该有助于抵御 SQL 注入攻击。

我从文章“的答案如何避免SQL注入休眠”是DW引用

Fortify 将查询字符串识别qs为易受 SQL 注入攻击。我不明白 SQL 注入是如何发生的,因为我setParameter()按照 Hibernate 文章的建议使用。最后我意识到 Fortify 似乎认为propName是用户提供的数据。当我进行以下更改时

  String qs = "from ItemTypes as model where model.stapler = ?";

Fortify 停止将此代码识别为 SQL 注入漏洞。

"from ItemTypes as model where model."+ propName

findByItemProp("stapler = '';drop table ItemTypes;--", "");

糟糕,你的数据库到了,是的,它正在检测字符串连接,不要那样做。意识到它是方法调用上的参数可能还不够聪明,但作为程序员不会期望知道他们必须在没有适当文档的情况下对其进行清理,这仍然有点草率,最好确保它是干净的该方法本身就是当另一个开发人员做错时,您将免去无限的麻烦。