防止Java程序中的SQL注入攻击

我必须在我的java程序中添加一个语句来更新数据库表:

String insert = "INSERT INTO customer(name,address,email) VALUES('" + name + "','" + addre + "','" + email + "');"; 

我听说这可以通过SQL注入来利用,如:

 DROP TABLE customer; 

我的程序有一个Java GUI,所有的名称,地址和电子邮件值都是从Jtextfields中检索的。 我想知道以下代码( DROP TABLE customer; )如何被黑客添加到我的插入语句中以及如何防止这种情况。

您需要使用PreparedStatement 。 例如

 String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);"; PreparedStatement ps = connection.prepareStatement(insert); ps.setString(1, name); ps.setString(2, addre); ps.setString(3, email); ResultSet rs = ps.executeQuery(); 

这将防止注入攻击。

黑客把它放在那里的方式是你插入的String是否来自某个地方的输入 – 例如网页上的输入字段,或者应用程序中类似的表单上的输入字段。

我想知道黑客如何将这种代码(“DROP TABLE customer;”)添加到我的插入语句中

例如:

 name = "'); DROP TABLE customer; --" 

会将此值转换为insert

 INSERT INTO customer(name,address,email) VALUES(''); DROP TABLE customer; --"','"+addre+"','"+email+"'); 

我特别想知道如何防止这种情况发生

使用预处理语句和SQL参数(例如来自Matt Fellows的“被盗”):

 String insert = "INSERT INTO customer(name,address,email) VALUES(?, ?, ?);"; PreparedStament ps = connection.prepareStatment(insert); 

还要解析对这些变量的值,并确保它们不包含任何不允许的字符(例如名称中的“;”)。

您可以查看本文以获取相关信息! 🙂

我推荐参数化查询:

 String selectStatement = "SELECT * FROM User WHERE userId = ? "; PreparedStatement prepStmt = con.prepareStatement(selectStatement); prepStmt.setString(1, userId); ResultSet rs = prepStmt.executeQuery(); 

攻击者只需输入类似'foo@example.com"); DROP TABLE customer;进入email领域即可​​完成。

您可以通过使用适当的JDBC语句转义来防止这种情况。

这就是你应该在字符串语句中使用问号的原因:

  PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES SET SALARY = ? WHERE ID = ?"); pstmt.setBigDecimal(1, 153833.00) pstmt.setInt(2, 110592) 

引自这里

正如本文中所解释的那样,如果您仍在连接字符串,那么PreparedStatement本身并没有帮助您。

例如,一名流氓攻击者仍然可以执行以下操作:

  • 调用sleep函数,以便所有数据库连接都忙,从而使您的应用程序不可用
  • 从数据库中提取敏感数据
  • 绕过用户身份validation

并且它不仅仅是SQL,但如果您不使用绑定参数,则可能会损害JPQL和HQL:

 PreparedStatement ps = connection.prepareStatement( INSERT INTO customer(name,address,email) VALUES(?, ?, ?) ); int index = 0; ps.setString(++index, name); ps.setString(++index, address); ps.setString(++index, email); ResultSet rs = ps.executeQuery(); 

最重要的是,在构建SQL语句时,不应该使用字符串连接。 为此目的使用专用API:

  • JPA Criteria API
  • jOOQ

转到PreparedStatement PreparedStatement的优点:

SQL语句的预编译和数据库端缓存可以提高整体执行速度,并能够批量重用相同的SQL语句。

通过内置转义引号和其他特殊字符自动防止SQL注入攻击。 请注意,这要求您使用任何PreparedStatement setXxx()方法来设置值