SQL注入是一个Web应用程序问题,与ORM没有直接关系。 ActiveJDBC将处理传递给它的任何SQL。
(请参阅此处的讨论: https : //groups.google.com/d/topic/activejdbc-group/5D2jhWuW4Sg/discussion )
是真的吗 数据库抽象层是否应该将SQL注入预防委托给客户端应用程序?
SQL注入背景
SQL注入是我们大多数开发人员在职业生涯中不得不一次或多次处理的问题。 维基百科很好地解释了这个问题 。 给出以下Java代码(或任何其他语言):
statement = "SELECT * FROM users WHERE name = '" + userName + "';"
假设“ userName”是从HTTP请求中获取的变量。 盲目粘贴HTTP请求参数可以让攻击变得简单,如下所示:
-- attacker sends this code in the userName field:
userName = "a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't"
-- resulting in the following statement:
statement = "SELECT * FROM users WHERE name = 'a';"
+ "DROP TABLE users;" +
+ "SELECT * FROM userinfo WHERE 't' = 't';"
这不是发生在你身上吗?
也许不会。 但是问题经常在Stack Overflow上看到。 搜索“ SQL注入”时有2000多个结果: http : //stackoverflow.com/search?q= sql+injection。 因此,即使您知道如何预防,团队中的某人也可能不会。 好的但是 …
如果500个语句中的一个语句被某个忽略了这种威胁的程序员糟糕地写了,那还不是那么糟糕吗?
再想一想。 您是否听说过称为sqlmap的工具? 根据注入问题的严重程度,此工具将在几秒钟/几分钟/几小时内找到应用程序中任何有问题的页面。 不仅如此,一旦发现有问题的页面,它就能从数据库中提取所有类型的数据。 我的意思是所有数据。 多种sqlmap功能:
- 支持枚举用户,密码哈希,特权,角色,数据库,表和列 。
- 支持搜索特定数据库名称,所有数据库中的特定表或所有数据库表中的特定列 。 例如,这对于识别包含自定义应用程序凭据的表很有用,其中相关列的名称包含诸如name和pass之类的字符串。
- 当数据库软件是MySQL,PostgreSQL或Microsoft SQL Server时,支持从数据库服务器基础文件系统下载和上传任何文件 。
- 当数据库软件为MySQL,PostgreSQL或Microsoft SQL Server时,支持在数据库操作系统底层操作系统上执行任意命令并检索其标准输出 。
是! 如果您遭受SQL注入不安全代码的侵害,攻击者在某些情况下可以抢占您的服务器! 在我们公司中,我们已经在沙盒环境中针对某些具有已知漏洞的开源博客软件尝试了sqlmap。 我们已经成功地立即占领了服务器,而没有编写任何一行SQL
数据库抽象和SQL注入
好的,现在我引起了您的注意,让我们再考虑一下Igor Polevoy所说的话:
SQL注入是一个Web应用程序问题,与ORM没有直接关系。 ActiveJDBC将处理传递给它的任何SQL。
是的,他可能是正确的。 鉴于ActiveJDBC是JDBC的瘦身包装,因此可以进行一些不错的CRUD简化,例如(从其网站获取):
List<Employee> people =
Employee.where("department = ? and hire_date > ? ", "IT", hireDate)
.offset(21)
.limit(10)
.orderBy("hire_date asc");
您发现SQL注入的风险了吗? 对。 即使它为基础的PreparedStatement使用绑定值,此工具也像JDBC一样不安全。 如果小心,可以避免SQL注入。 或者,您可以开始串联字符串。 但是您必须意识到这一点! jOOQ如何处理此类情况? jOOQ手册介绍了如何显式或隐式处理绑定值 。 这里有些例子:
// Implicitly creating a bind value for "Poe"
create.select()
.from(T_AUTHOR)
.where(LAST_NAME.equal("Poe"));
// Explicitly creating a (named) bind value for "Poe"
create.select()
.from(T_AUTHOR)
.where(LAST_NAME.equal(param("lastName", "Poe")));
// Explicitly inlining "Poe" in the generated SQL string
create.select()
.from(T_AUTHOR)
.where(LAST_NAME.equal(inline("Poe")));
上面的例子将产生
SELECT * FROM T_AUTHOR WHERE LAST_NAME = ?
SELECT * FROM T_AUTHOR WHERE LAST_NAME = ?
SELECT * FROM T_AUTHOR WHERE LAST_NAME = 'Poe'
在内联“ Poe”的情况下,转义由jOOQ处理,以防止语法错误和SQL注入。 但是jOOQ还支持在生成的SQL中直接注入SQL字符串 。 例如:
// Inject plain SQL into jOOQ
create.select()
.from(T_AUTHOR)
.where("LAST_NAME = 'Poe'");
在这种情况下,SQL注入可能与JDBC一样发生
结论
本质上,伊戈尔是对的。 (客户端)应用程序开发人员的责任是意识到由其代码创建的SQL注入问题。 但是,如果建立在JDBC之上的数据库抽象框架可以在其API中尽可能避免SQL注入,那就更好了。 从SQL注入的角度来看,数据库抽象框架可以分为三类:
- 简单的实用程序 。 这些包括Spring的JdbcTemplate或Apache的DbUtils 。 他们实际上只是通过便利性来增强了JDBC API(更少的异常处理,更少的冗长性,更简单的变量绑定,更简单的数据获取)。 当然,这些工具不会阻止SQL注入
- 完整的SQL抽象 。 这些包括jOOQ , JaQu , QueryDSL , JPA的CriteriaQuery等。 它们的正常操作模式将始终在生成的SQL中呈现绑定值。 在大多数情况下,这可以防止SQL注入。
- 其他的 。 许多其他框架(包括ActiveJDBC和Hibernate )主要基于(SQL或HQL)字符串操作。 尽管它们抽象了许多与SQL有关的内容,但它们根本不会阻止SQL注入。
因此,当您在Java应用程序中选择任何SQL抽象工具时,请注意SQL注入的严重性。 并且要注意一个事实,您的工具是否可以帮助您防止它!
参考:来自JAVA,SQL和JOOQ博客的JCG合作伙伴 Lukas Eder的数据库抽象和SQL注入 。
翻译自: https://www.javacodegeeks.com/2012/07/database-abstraction-and-sql-injection.html