保护 Java 应用程序免受 SQL 注入
Securing Java Applications from SQL injection
如果我们在 SQL 查询中传递 1=1,它将 return 所有数据,因为它在所有条件下都为真。
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);'
最终这取决于数据库及其 JDBC 驱动程序。
例如,MySQL 服务器本身支持准备好的语句(ServerPreparedStatement
,这意味着当您执行 query.executeQuery()
时,驱动程序会向服务器发送以下数据:
- 准备好的SQL语句(
select * from users where userId=?
)
- 第一个参数的值("abcd' or '1'='1")
MySQL 服务器不需要解析完整的 SQL 语句(select * 来自 userId= 'abcd' 的用户)并提取来自那个的比较值(“abcd”)。
相反,它可以解析准备好的语句(“select * from users where userId=?”)并从第二个数据元素中获取比较值。
警告:您需要通过设置 useServerPrepStmts=true
连接 属性 来通知 MySQL 连接器您想要使用服务器端准备好的语句,请参阅 MySQL Connector documentation
如果 SQL 服务器实现不支持准备语句(或未配置为使用服务器端准备语句),JDBC 驱动程序的工作是更改
- 准备好的SQL语句(
select * from users where userId=?
)
- 第一个参数的值("abcd' or '1'='1")
进入安全的SQL查询
select * from users where userId='abcd'' or ''1''=''1'
在这个简单查询的情况下,很容易转义值中的单引号,但对于更复杂的值,这就复杂得多(请参阅 https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/ 以了解 [=58] 中可能使用的示例=]注入攻击)。
如果您尝试实现自己的转义,您很可能会错过一些特殊情况。
如果我们在 SQL 查询中传递 1=1,它将 return 所有数据,因为它在所有条件下都为真。
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);'
最终这取决于数据库及其 JDBC 驱动程序。
例如,MySQL 服务器本身支持准备好的语句(ServerPreparedStatement
,这意味着当您执行 query.executeQuery()
时,驱动程序会向服务器发送以下数据:
- 准备好的SQL语句(
select * from users where userId=?
) - 第一个参数的值("abcd' or '1'='1")
MySQL 服务器不需要解析完整的 SQL 语句(select * 来自 userId= 'abcd' 的用户)并提取来自那个的比较值(“abcd”)。
相反,它可以解析准备好的语句(“select * from users where userId=?”)并从第二个数据元素中获取比较值。
警告:您需要通过设置 useServerPrepStmts=true
连接 属性 来通知 MySQL 连接器您想要使用服务器端准备好的语句,请参阅 MySQL Connector documentation
如果 SQL 服务器实现不支持准备语句(或未配置为使用服务器端准备语句),JDBC 驱动程序的工作是更改
- 准备好的SQL语句(
select * from users where userId=?
) - 第一个参数的值("abcd' or '1'='1")
进入安全的SQL查询
select * from users where userId='abcd'' or ''1''=''1'
在这个简单查询的情况下,很容易转义值中的单引号,但对于更复杂的值,这就复杂得多(请参阅 https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/ 以了解 [=58] 中可能使用的示例=]注入攻击)。
如果您尝试实现自己的转义,您很可能会错过一些特殊情况。