当前位置: 首页 > 知识库问答 >
问题:

不使用预准备语句删除SQL注入

卫泉
2023-03-14

我的应用程序有很多使用语句编写的JDBC查询,因此容易受到SQL注入的影响。不幸的是,这个应用程序是大约10年前开发的,可能开发人员不知道准备语句。

我知道解决这个问题的最好方法是使用PreparedStatement,但是在整个应用程序中转换它是非常繁琐的。此外,为SQL注入编写任何类型的模式匹配可能非常棘手,因为像Select、insert、union等关键字都是英语单词,它们也可能出现在用户键入的文本字段中。

有没有更聪明的方法来避免SQL注入而不使用预准备语句。如果这是一个重复的问题,请给我一个有好答案的问题的链接。感谢您的帮助。

共有1个答案

方昊阳
2023-03-14

哈。不幸的是,它几乎总是取决于货币和管理决策,但“非常乏味”通常不被认为是一个有效的工程问题——它只是适当重构代码的借口。

同时,该问题要求非准备语句方法:简而言之,如果您不能将工作卸载到库(例如准备语句),那么唯一的另一种方法是为每个“注入”项目自己做。无论哪种方式,都必须执行检查输入的工作。唯一的问题是它在哪里完成,以及程序员的专业知识是什么使输入验证代码

例如,考虑一个简单的SELECT语句:

    sql = "SELECT * FROM mytable WHERE id = " + untrustedVar;

为了完整起见,我们可以假设注入示例,其中< code>untrustedVar是类似于< code>1或1或< code>1的字符串;删除表mytable显然,这将导致不必要的行为,对于返回给调用者的所有行,或者现在缺失的数据库表:

SELECT * FROM mytable WHERE id = 1;
DROP mytable;

强制性参考

在这种情况下,您可以让语言语义学至少确保unstrustedVar是一个整数,也许在您的函数定义中:

String[] selectRowById ( int untrustedVar ) { ...

或者如果它是一个字符串,您可以使用正则表达式执行此操作,例如:

Pattern valid_id_re = Pattern.compile('^\d{1,10}$');  // ensure id is between 1 and 10 billion
Matcher m = valid_id_re.matcher( unstrustedVar );
if ( ! m.matches() )
    return null;

但是,如果您有没有任何语法或结构保证的较长输入(例如,web表单文本区域),则需要进行较低级别的字符替换,以转义潜在的错误字符。每个声明。每个变量。每种数据库风格(PostgreSQL、Oracle、MySQL、SQLite等)。这…是一罐蠕虫。

当然,好处是,如果您没有使用准备好的语句,并且还没有人完成避免应用程序SQL注入攻击的工作,那么您除了向上之外别无选择。

与此同时,我敦促,敦促,敦促你重新考虑你对“我们不能因为原因而使用事先准备好的声明”的立场更重要的是,正如戈登·汤普森在下面的评论中正确指出的那样,“无论如何,这将是一项相当大的工作,所以为什么不把它做好,然后结束呢?”

在写了以上内容之后,我突然想到,有些人可能会认为,仅仅写一份准备好的声明就意味着更好的安全性。实际上,它是带有绑定参数的准备好的语句,提高了安全性。例如,可以这样写:

String sql = "SELECT * FROM mytable WHERE id = " + untrustedVar;
PreparedStatment pstmt = dbh.prepareStatement( sql );
return pstmt.executeQuery();

此时,您所做的只是准备一个已经注入恶意代码的语句。相反,考虑参数的实际绑定:

String sql = "SELECT * FROM mytable WHERE id = ?";  // Raw string; never touched by "tainted" variable
PreparedStatment pstmt = dbh.prepareStatement( sql );
pstmt.setObject(1, p);  // Perform the actual binding.
return pstmt.executeQuery();

后一个示例执行两项操作。它首先创建一个已知的安全格式,并将其发送到数据库进行准备。然后,在数据库返回预准备语句的句柄后,我们是否绑定变量,最后执行该语句。

 类似资料:
  • 假设上面的代码是我的查询。什么是一个安全的替代方案,将允许自动增加在mySQL数据库。

  • 问题内容: 我有一个关于将字符串插入SQL Server 2008 R2的问题。当我尝试插入带有一些国家字母的字符串时,会收到“?” 反而。 我知道在字符串文字的开头添加将解决此问题,但是我正在使用JDBC准备的语句,如下所示: 我的问题是:如何添加此“ N”字母?我应该做这样的事情吗? 老实说,我不相信,因为这根本行不通。 问题答案: 根据@a_horse_with_no_name和@ gofr

  • 问题内容: 停止使用不推荐使用的mysql_ *函数后,我切换到mysqli。但是后来,我注意到未准备好的语句对于SQL注入是不安全的。然后,我再次更改了代码。 我所拥有的是以下函数,该函数检查数据库中是否存在变量 $ ID 并打印该行的 title 值: 我将其更改为: 我的问题是:这是执行准备好的语句的正确方法吗?另外,我现在可以安全使用SQL注入吗?非常感谢任何愿意回答这个问题的人:) 问题

  • 问题内容: 我在程序中尝试了准备好的语句,但是没有用。 注释的部分是“准备报表”部分。当我将其更改为常规语句时,一切都正确。 有人可以告诉我我想念什么吗? 非常感谢。 问题答案: 尝试从查询中删除并在添加参数后使用:

  • 问题内容: 嗨,我需要在我的网站中使用“准备好的声明”。我尝试使用这个 但这不起作用。当我改变并以它的工作。 问题答案: CodeIgniter不支持预备语句。如果查看CI的Database类的源代码,您将看到它们仅通过用传递的数组中的数据替换问号来解析绑定: https://github.com/EllisLab/CodeIgniter/blob/develop/system/database/