【发布时间】:2010-09-20 10:40:12
【问题描述】:
我已经读过,为了防止 SQL 注入,必须使用 PreparedStatement。
这是否意味着如果我使用 perparedStatement 那么没有人可以在我的任何页面中执行 SQL 注入?它对 SQL 注入是万无一失的吗?如果不是,请举一些例子来证明这一点。
【问题讨论】:
标签: security prepared-statement sql-injection
我已经读过,为了防止 SQL 注入,必须使用 PreparedStatement。
这是否意味着如果我使用 perparedStatement 那么没有人可以在我的任何页面中执行 SQL 注入?它对 SQL 注入是万无一失的吗?如果不是,请举一些例子来证明这一点。
【问题讨论】:
标签: security prepared-statement sql-injection
只要您实际使用预准备语句的参数替换功能(可能会误用它们而不使用该功能),并且您正在使用的预准备语句库中没有错误,那么你应该对原始 SQL 注入没问题。但这并不意味着你不应该怀疑用户给你的任何东西。 :-)
【讨论】:
准备好的语句不包括查询的非数据部分 - 标识符和运算符。
因此,如果其中一些是可变的并直接添加到查询中,则可以进行注入。
由于可能的选项数量有限,所有变量标识符都应根据用户输入从预先编写的变体中选择。操作员也一样。
不应将任何用户输入直接添加到查询中。
【讨论】:
使用所提供语言的预准备语句功能意味着您正在使用经过试验和测试的解决方案来解决问题 - 这并不意味着 SQL 注入的可能性永远不会存在任何错误或范围,但它的真正含义是你不是唯一使用该实现的人。使用相同实现的人越多,发现和消除错误的机会就越大 - 如果您使用自己的实现,那么只有您可以找到并修复错误。
【讨论】:
虽然Prepared Statements有助于防御SQL Injection,但不恰当地使用Prepared Statements可能会引发SQL Injection攻击。
下面的示例解释了输入变量直接传递到 Prepared Statement 从而为 SQL 注入攻击铺平道路的场景。
String strUserName = request.getParameter("Txt_UserName");
PreparedStatement prepStmt = con.prepareStatement("SELECT * FROM user WHERE userId = '+strUserName+'");
准备好的语句如果处理不当,很容易受到 SQL 注入的攻击。
【讨论】:
简短回答:是的,如果使用得当。
但是,这并不意味着 JDBC 驱动程序中不能有 bug,从而为 SQL 注入开放。当我为我工作的一家公司调查此问题时,我发现我们使用的一个 JDBC 驱动程序(PostgreSQL)中确实存在 SQL 注入错误。这是几年前的事了,bug 已经修复了。
虽然我不记得具体细节,但我记得查看 JDBC 实现的源代码,发现它是通过字符串连接实现的。
不过,我希望这种情况很少见,我的建议是相信实现并正确使用 PreparedStatements。
【讨论】: