Hibernate createSQLQuery - 它如何验证SQL?

时间:2015-10-06 21:46:40

标签: mysql hibernate sql-injection

我有一些代码可以将用户的搜索词转换为MySQL查询:

String sql = String.format("SELECT * FROM my_table WHERE my_column = '%s'", value);
HibernateUtil.getCurrentSession().createSQLQuery(sql);

测试我是否受到保护 - 并且因为我认为以这种方式学习会很有趣 - 我想尝试SQL注入我自己的应用程序。所以我搜索了:

x'; DROP TABLE test;--

导致以下查询:

SELECT * FROM my_table WHERE my_column = 'x'; DROP TABLE test;--

但是Hibernate会抛出一个SQLGrammarException。当我通过phpMyAdmin运行此代码时,它正确地删除了测试表。

Hibernate如何验证我的SQL?也许更重要的是 - 这可以保护我免受SQL注入,或者我应该使用setParameter。如果它不保护我,我可以举一些SQL来执行注入。我认为实际验证会很有趣。

2 个答案:

答案 0 :(得分:1)

根据Hibermate documentation,方法createSQLQuery“为给定的SQL字符串创建一个新的Query实例”,因此我们可以假设Hibernate在每次调用此方法时都会对单个查询执行SQL检查。 / p>

重要:在Hibernate上不推荐使用createSQLQuery,请查看上面给出的链接以查看更新的执行SQL查询的方法。

现在,谈谈如何保护自己免受SQL注入攻击,最好的方法是在查询中使用参数。

This question有您需要的确切示例,请查看。

希望这能帮助你学习,祝你好运!

答案 1 :(得分:1)

您受到保护,不会执行多个语句,因为createSQLQuery只允许一个语句。它不是Hibernate在这里保护你,而是你的JDBC驱动程序分别是你的数据库 - 因为它不知道如何在单个语句的上下文中处理分隔符;

但是你仍然不能安全地反对SQL注入。在这种情况下,还有很多其他可能性来注入SQL。只举一个例子:

想象一下,您在查询中搜索某些特定于用户的项目:

 String sql = String.format(
     "SELECT * FROM my_table WHERE userId = %s AND my_column = '%s'", 
     currentUserId, value);

用户现在可以输入:

 x' OR '1' = '1

这将导致SQL:

 SELECT * FROM my_table WHERE userId = 1234 AND my_column = 'x' OR '1' = '1'

由于AND具有更高的优先级,因此他会看到所有项目 - 甚至是其他用户的项目。

即使您提供的示例也很危险,例如

 x' OR (SELECT userName FROM USER) = 'gwg
如果您的数据库包含名为gwg的用户(假设我知道您的数据库布局,我可以通过类似的查询找到),

将告诉我。