【问题标题】:Securing Java Applications from SQL injection [duplicate]保护 Java 应用程序免受 SQL 注入 [重复]
【发布时间】:2021-10-23 01:39:43
【问题描述】:

如果我们在 SQL 查询中传递 1=1,它将返回所有数据,因为它在所有条件下都为真。

String query =  "select * from users where userId= 'abcd' or '1'='1'";

我正在研究 PreparedStatement 接口,发现 setString 方法将列的值附加到准备语句。我想知道内部它是如何防止 sql 注入的?如果我通过这样的事情 -

Connection con=DriverManager.getConnection(url,username,password);  
PreparedStatement query = con.prepareStatement("select * from users where userId=?");  
query.setString(1,userId);'

 

【问题讨论】:

    标签: java sql jdbc


    【解决方案1】:

    这最终取决于数据库及其 JDBC 驱动程序。

    例如 MySQL 服务器原生支持预处理语句(ServerPreparedStatement,这意味着当您执行 query.executeQuery() 时,驱动程序会向服务器发送以下数据:

    1. 准备好的 SQL 语句 (select * from users where userId=?)
    2. 第一个参数的值(“abcd”或“1”=“1”)

    反过来,MySQL 服务器不需要解析完整的 SQL 语句(“select * from users where userId= 'abcd'”)并从中提取比较值​​(“abcd”)。

    相反,它可以解析准备好的语句(“select * from users where userId=?”)并从第二个数据元素中获取比较值。

    警告:您需要通过设置useServerPrepStmts=true 连接属性来通知 MySQL 连接器您要使用服务器端准备好的语句,请参阅MySQL Connector documentation


    如果SQL server 实现不支持prepared statements(或者没有配置使用服务器端prepared statements),改变是JDBC驱动的工作

    1. 准备好的 SQL 语句 (select * from users where userId=?)
    2. 第一个参数的值(“abcd”或“1”=“1”)

    进入安全的 SQL 查询

    select * from users where userId='abcd'' or ''1''=''1'
    

    在这个简单查询的情况下,转义值中的单引号很容易,但对于更复杂的值,这涉及更多(请参阅https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/,了解可能用于 SQL 注入攻击的示例)。

    如果您尝试自己实现转义,您很可能会错过一些特殊情况。

    【讨论】:

    • MySQL Connector/J 驱动默认使用第二个选项,服务器端预处理语句仅在显式启用时使用。参见6.3.7 Prepared Statements中的useServerPrepStmts
    • 您是否知道您正在链接到 MySQL Connector/J 的随机分支,而不是官方分支:github.com/mysql/mysql-connector-j
    • @MarkRotteveel 感谢您的 cmets。我改进了我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 2020-05-06
    • 1970-01-01
    • 2016-05-31
    • 2010-12-24
    相关资源
    最近更新 更多