这是怎么回事,因为我在这里专门询问JOOQ?
我在我的JAVA项目中使用JOOQ来处理我的所有PostgreSQL查询。我在this文章中读到JOOQ使用预准备语句来执行所有查询。
假设在执行查询时我不需要担心SQL注入或用户输入,这是否安全?
在将用户输入转交给JOOQ之前,我不需要担心转义用户输入吗?
在旁注中,我的数据库在获取用户输入时存在哪些其他漏洞(除了那些由准备好的语句解决的漏洞),我应该注意哪些?
答案 0 :(得分:1)
1)是的,只要您正确使用提供的API即可。仍然可以注入简单的SQL查询,所以要小心。
jOOQ API中允许普通(未转义,未处理)SQL的所有方法都在其相关的Javadoc中包含警告消息
// This query will use bind values, internally.
create.fetch("SELECT * FROM BOOK WHERE ID = ? AND TITLE = ?", 5, "Animal Farm");
// This query will not use bind values, internally.
create.fetch("SELECT * FROM BOOK WHERE ID = 5 AND TITLE = 'Animal Farm'");
请参阅此处的JOOQ文档以获得更深入的解释:https://www.jooq.org/doc/3.9/manual/sql-building/bind-values/sql-injection/
2)不,见上文。
3)除此之外,请注意一般数据库安全问题,例如用户身份验证/角色以及以非加密格式存储敏感数据等
答案 1 :(得分:0)
无论您使用何种语言和框架,始终都可以编写不安全的查询。
将变量连接到SQL的简单方法为SQL注入创造了机会:
String unsafeString = "O'Reilly";
create.fetch("SELECT * FROM BOOK WHERE ID = 5 AND TITLE = '"+unsafeString+"'");
// results in SQL syntax error because of unmatched ' marks
仅使用准备好的查询不会对安全查询进行不安全的查询。
使用参数将动态值与SQL查询分开。它们在执行时在RDBMS中组合。参数无法导致SQL注入漏洞。
String unsafeString = "O'Reilly";
create.fetch("SELECT * FROM BOOK WHERE ID = 5 AND TITLE = ?", unsafeString);
// still OK
使用参数时,不需要对变量进行任何转义。实际上,你一定不能,,因为你的数据中最终会出现转义符号。
参数适用于将Java变量组合到SQL查询中,但仅限于SQL标量值。也就是说,您通常在SQL中使用带引号的字符串文字,带引号的日期文字或数字文字,您可以用参数占位符替换它。
但是你不能在SQL中使用其他任何参数:
IN ( ... )
谓词 - 您必须在列表中为每个值使用一个?
占位符。您可能会喜欢我的演示文稿SQL Injection Myths and Fallacies(video)或我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming
来自@rehas的评论:
实际上,使用预准备语句不意味着您隐式使用参数。我在上面展示了一个例子(我的第一个例子),它将一个不安全的变量连接到一个SQL字符串,然后再发送到prepare()。
一旦SQL字符串到达RDBMS服务器,就无法知道字符串的哪些部分是合法的,哪些部分是从不安全的变量连接起来的。它看到的只是一个包含SQL语句的字符串。
使用参数的目的是使(可能不安全的)变量与SQL字符串分开。在RDBMS服务器中,解析了仍然包含?
等参数占位符的SQL字符串。解析后,它将不再被解析,因此将“O'Reilly”这样的字符串绑定到参数占位符是安全的,而不会产生引号不匹配或任何内容的风险。保证在SQL执行中将参数视为单个值,即使参数的值包含将改变查询解析方式的字符,如果在准备之前已包含 ()。
使用prepare()并不意味着你总是使用参数。
准确地说,使用参数需要使用prepare()和execute()作为单独的步骤。但是有些框架会为您完成这两个步骤。我确定你是否要阅读jOOQ源代码,你会看到它。