防止 Java 程序中的 SQL 注入攻击
Posted
技术标签:
【中文标题】防止 Java 程序中的 SQL 注入攻击【英文标题】:Prevent SQL injection attacks in a Java program 【发布时间】:2012-03-19 23:19:55 【问题描述】:我必须在我的 java 程序中添加一条语句来更新数据库表:
String insert =
"INSERT INTO customer(name,address,email) VALUES('" + name + "','" + addre + "','" + email + "');";
我听说这可以通过 SQL 注入来利用,例如:
DROP TABLE customer;
我的程序有一个 Java GUI,所有姓名、地址和电子邮件值都是从 Jtextfields
检索的。我想知道黑客如何将以下代码 (DROP TABLE customer;
) 添加到我的插入语句中,以及如何防止这种情况发生。
【问题讨论】:
必填XKCD cartoon Java - escape string to prevent SQL injection的可能重复 【参考方案1】:您可以查看THIS 文章了解相关信息! :)
我推荐参数化查询:
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
【讨论】:
【参考方案2】:您需要使用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();
这将防止注入攻击。
如果您插入的字符串来自某处的输入,那么黑客将其放入其中的方式 - 例如。网页上的输入字段,或应用程序或类似表单中的输入字段。
【讨论】:
这确实会在一定程度上防止SQL注入攻击,因为它把代码和数据分开了。这是一个简短的教程,涵盖 using Prepared Statements with Java JDBC.【参考方案3】:攻击者只需在email
的字段中输入类似'foo@example.com"); DROP TABLE customer;
的内容即可。
您可以通过对 JDBC 语句使用正确的转义来防止这种情况发生。
【讨论】:
【参考方案4】:这就是为什么你应该在你的字符串语句中使用问号:
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00)
pstmt.setInt(2, 110592)
引自here
【讨论】:
【参考方案5】:我想知道这种代码(“DROP TABLE customer;”)如何 被黑客添加到我的插入语句中
例如:
name = "'); DROP TABLE customer; --"
会将这个值生成到插入:
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);
同时解析这些变量的值,并确保它们不包含任何不允许的字符(例如名称中的“;”)。
【讨论】:
我使用的是 GUI。人员只能通过文本字段输入值。他们怎么能在我的声明中添加这样的代码。像这样 INSERT INTO customer(name,address,email) VALUES(''); DROP TABLE 客户; --"','"+地址+"','"+email+"'); 你为什么不输入 '); DROP TABLE 客户; -- 在文本字段中?无论如何,恶意用户可以破解这些文本字段的限制(例如直接修改 RAM、注入伪造的网络数据包等)。 我不想自己重写它:D @m0skit0 抱歉回复晚了。一个理想的攻击向量可能是一个受限系统,其中用户没有管理员权限,甚至没有办法逃到主操作系统。拥有一个带有 SQL 注入可能性的文本框和一个键盘输入可能允许窃取存储在 DB 中的凭据和其他信息。您将如何在咖啡店客户计算机中编辑 RAM,即使可以,您难道不能从程序配置中获取身份验证凭据并在服务器上造成严重破坏吗?【参考方案6】:使用 PreparedStatement PreparedStatement 的优点:
SQL 语句的预编译和数据库端缓存可提高整体执行速度,并能够批量重用相同的 SQL 语句。
通过对引号和其他特殊字符的内置转义自动防止 SQL 注入攻击。请注意,这要求您使用任何 PreparedStatement setXxx() 方法来设置值
【讨论】:
【参考方案7】:正如this post 中所解释的,如果您仍在连接字符串,单独的PreparedStatement
并不能帮助您。
例如,一个流氓攻击者仍然可以执行以下操作:
调用 sleep 函数,使您的所有数据库连接都处于忙碌状态,从而使您的应用程序不可用 从数据库中提取敏感数据 bypassing the user authentication而且不只是 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【讨论】:
【参考方案8】:尽管所有其他答案都告诉您如何在 Java 中修复 SQL 注入,但 Mukesh Kumar 的回答实际上告诉您谁在实际阻止此类攻击。了解它实际上是防止 SQL 注入攻击的数据库服务器为您作为程序员提供了使用 parametrized 查询的建议。
Refer Here - Preventing SQL Injection Vulnerabilities
Java 程序员不可能清理每个输入字符串,因此 DB 供应商为我们提供了 Prepared Statements 选项,他们告诉我们使用该字符串准备和执行查询,其余的事情将得到处理由数据库供应商提供。
像DROP TABLE customer;
这样激烈的事情可能不会发生,但 SQL 注入的基本前提是没有人应该能够通过提供无效输入(有意或无意)来破坏您的查询。
OWASP - SQL Injection Prevention Cheat Sheet
【讨论】:
【参考方案9】:您还应该尽可能严格地限制访问数据库的帐户的权限。例如,对于搜索,该帐户只需要对那些需要的表和列具有读取权限。这将防止任何破坏性的 SQL 注入并限制对敏感数据的访问。
【讨论】:
以上是关于防止 Java 程序中的 SQL 注入攻击的主要内容,如果未能解决你的问题,请参考以下文章
使用“database/sql”时如何防止 Go 中的 SQL 注入攻击?