首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >针对SQL注入的预准备语句效果

问针对SQL注入的预准备语句效果
EN

Stack Overflow用户
提问于 2018-05-10 03:26:34
回答 2查看 76关注 0票数 0

例如,我有以下代码:

代码语言:javascript
复制
import java.sql.*; ...
public void main (string[] args){ 
try {
 Class.forName („COM.ibm.db2.jdbc.net.DB2Driver“);} catch (ClassNotFoundException e) {//error handling}
try {
    String url = "jdbc:db2://host:6789/myDB2"
    Connection con = DriverManager.getConnection(url, "login", "password");
    PreparedStatement pStmt = con.prepareStatement("UPDATE PERS SET Salary=Salary*2.0 WHERE PNR=?"

    pStmt.setInt (1, 35);
    pStmt.executeUpdate();

    pStmt.setString (1, args[0]); 
    pStmt.executeUpdate();

    con.close();
    } catch (SQLException e) { //error handling}
}

假设我们有这样的表:

代码语言:javascript
复制
+--------+----------+-----------+
|PNR     |Name      |Salary     |
+--------+----------+-----------+
|34      |Tim       |20000      |
+--------+----------+-----------+
|35      |John      |45000      |
+--------+----------+-----------+

在以下情况下,我很难预测会发生什么:

代码语言:javascript
复制
args[0]="35 OR Salary<100000" 

setString命令不是用35 OR Salary < 100000替换了args[0],然后所有的工资记录都加倍了吗?

EN

回答 2

Stack Overflow用户

发布于 2018-05-10 03:29:48

这不会导致SQL注入问题。它将转换为:

代码语言:javascript
复制
UPDATE PERS SET Salary=Salary*2.0 WHERE PNR='35 OR Salary<100000'

插入的引号将使您免于SQL注入。我做了一点简化。JDBC实现决定了PreparedStatement如何准确地转换为真正的SQL查询。它实际上并不一定要将它转换成上面的SQL。但这是它可以防止攻击的一种方式。

不过,要小心。如果您使用用户输入来创建SQL,您仍然很容易受到SQL注入的影响。只要您只使用用户输入来调用.setXYZ()参数,您就不会受到影响。

票数 2
EN

Stack Overflow用户

发布于 2018-05-10 04:27:38

服务器端预准备语句

SQL参数有助于避免SQL注入,因为参数值根本不会与SQL查询相结合。带有参数占位符的SQL查询被发送到MySQL服务器,在那里它被解析和分析。它执行的操作包括检查您编写的SQL语法是否有效,您引用的表和列是否存在,以及您是否具有访问这些表和列的适当权限。

这就是参数不能用于表名、列名或其他语法的原因。因为当参数仍然保留为占位符时,验证就会发生。参数的值是稍后发送的,因此验证必须假定参数必须仅替换SQL查询中的单个标量值。

在此之后,查询将作为非文本数据结构存储在MySQL服务器内部。它不再存在于SQL中,它只是MySQL代码中的一些内部对象。使用?的地方变成了查询元素,MySQL知道在执行查询之前需要为这些元素提供值。

当您运行pStmt.executeUpdate()时,绑定到参数的变量的值将被发送到MySQL服务器。它们被填充到查询的非文本表示中的占位符中。

这样,直到解析完成后才组合参数值,因此参数的内容无法更改SQL语法。它只会像单个字符串那样影响SQL查询,就好像有一种类型的引号分隔符不能被参数内容中不匹配的引号字符打断一样。

查询参数是防止SQL注入的可靠方法。

模拟的预准备语句

一些驱动程序实现了一个“模拟的”预准备语句。这意味着它对传递给prepareStatement()的SQL查询没有任何作用,只是将SQL字符串保存在JDBC驱动程序中(在客户端)。此时它不会将SQL查询发送到服务器。

然后,当您运行executeUpdate()时,您的变量被插入到SQL字符串中的参数占位符中,并且完整的字符串被发送到服务器。然后,MySQL服务器使用参数值和all来解析组合的SQL查询。Server甚至不能区分原始MySQL查询中哪些值是文字值,哪些值被组合为参数。它们都以字面值的形式出现在解析器中。

在这种情况下,您必须相信JDBC驱动程序能够正确地进行转义,这样参数内容中的引号和其他字符就不会混淆SQL解析器。驱动程序应该经过良好的测试,以处理所有情况,如特殊字符集、十六进制编码的引号字符和其他欺骗它的方法。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50260726

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档