为了账号安全,请及时绑定邮箱和手机立即绑定

我是否可以通过转义单引号和用单引号包围用户输入来防止SQL注入?

/ 猿问

我是否可以通过转义单引号和用单引号包围用户输入来防止SQL注入?

函数式编程 2019-07-17 10:36:56

我是否可以通过转义单引号和用单引号包围用户输入来防止SQL注入?

我意识到,在构建包含用户输入的查询时,参数化SQL查询是对用户输入进行清理的最佳方法,但我想知道接受用户输入和转义任何单引号并用单引号包围整个字符串有什么问题。下面是代码:

sSanitizedInput = "'" & Replace(sInput, "'", "''") & "'"

用户输入的任何单引号都将替换为双引号,这将消除用户结束字符串的能力,因此他们可能键入的任何其他内容(如分号、百分比符号等)都将是字符串的一部分,而不是作为命令的一部分实际执行。

我们使用的是MicrosoftSQLServer 2000,我认为单引号是唯一的字符串分隔符,也是转义字符串分隔符的唯一方法,因此无法执行用户键入的任何内容。

我看不出有什么方法可以针对这种情况发起SQL注入攻击,但我意识到,如果这像我所认为的那样防弹,其他人就会想到这一点,这将是一种常见的做法。

这个密码怎么了?是否有办法使SQL注入攻击超过这种消毒技术?使用此技术的示例用户输入将非常有用。


最新情况:

我仍然不知道如何有效地针对这段代码发起SQL注入攻击。有几个人建议反斜杠会转义一个单引号,让另一个单引号结束字符串,以便字符串的其余部分作为SQL命令的一部分执行,我意识到这个方法可以将SQL注入MySQL数据库,但是在SQL Server 2000中,我能够找到的唯一方法是用另一个单引号来转义单引号;反斜杠不能做到这一点。

而且,除非有一种方法来停止转义单引号,否则将不会执行其余的用户输入,因为它都将被视为一个连续字符串。

我知道有更好的方法来消毒输入,但我更感兴趣的是学习为什么我提供的方法不能工作。如果有人知道针对这种消毒方法进行SQL注入攻击的任何具体方法,我很乐意看到它。


查看完整描述

3 回答

?
慕妹3242003

首先,这只是糟糕的练习。输入验证总是必要的,但也总是不确定的。
更糟糕的是,黑名单验证总是有问题的,最好是显式和严格地定义您接受的值/格式。诚然,这并不总是可能的-但在某种程度上必须做到这一点。
关于这一主题的一些研究论文:

重点是,你所做的任何黑名单(以及过于宽容的白名单)都可以被绕过。我的论文的最后一个链接显示了甚至可以绕过引号转义的情况。

即使这些情况不适用于你,这仍然是个坏主意。此外,除非您的应用程序很小,否则您将不得不处理维护问题,也许还需要一定程度的治理:如何确保它在任何时候都做得对?

正确的方法:

  • 白名单验证:类型、长度、格式或接受值
  • 如果你想列入黑名单,那就去吧。引号转义是好的,但在其他缓解范围内。
  • 使用命令和参数对象,准备和验证
  • 只调用参数化查询。
  • 更好的是,只使用存储过程。
  • 避免使用动态SQL,也不要使用字符串连接来构建查询。
  • 如果使用SPS,还可以将数据库中的权限限制为只执行所需的SPS,而不是直接访问表。
  • 您还可以很容易地验证整个代码库只通过SPS访问DB.


查看完整回答
反对 回复 2019-07-17
?
慕码人2483693

好的,这个答复将与问题的更新有关:

“如果有人知道针对这种消毒方法进行SQL注入攻击的任何具体方法,我很乐意看到它。”

现在,除了MySQL反斜杠转义-并且考虑到我们实际上是在讨论MSSQL,实际上有三种可能的方法来注入您的代码

SaniizedInput=“‘”&替换(sInput、“’”)和“‘”

请考虑到,这些代码并非在任何时候都有效,并且非常依赖于其周围的实际代码:

  1. 如果基于从数据库检索的数据重新生成sql查询,则为二阶sql注入。

    逃出

    ,数据未经转义就连接在一起,可能是间接注入SQL的.看见
  2. 字符串截断-(稍微复杂一点)-场景是有两个字段,比如用户名和密码,SQL将这两个字段连接起来。这两个字段(或者仅仅是第一个字段)都有一个严格的长度限制。例如,用户名限制为20个字符。假设你有这样的代码:
username = left(Replace(sInput, "'", "''"), 20)

然后你得到的是用户名,转义,然后修剪成20个字符。这里的问题-我会坚持我的引号在第20个字符(例如,在19个a‘s之后),你的转义引号将被削减(在第21字符)。然后是SQL。

sSQL = "select * from USERS where username = '" + username + "'  and password = '" + password + "'"

与上述格式错误的用户名相结合,将导致密码已经被引号,并将直接包含有效载荷。
3.Unicode走私-在某些情况下,可以传递一个高级Unicode字符相貌就像一句名言,但是不是-直到它到达数据库,在那里突然它是..因为当你验证它的时候,它不是引号,所以它会很容易.有关更多细节,请参阅我先前的回复,并链接到原始研究。


查看完整回答
反对 回复 2019-07-17
?
冉冉说

我意识到这个问题被问了很久了,但是.。

对“引号参数”过程发起攻击的一种方法是使用字符串截断。根据MSDN,在SQLServer2000SP4(和SQLServer2005SP1)中,过长的字符串将被悄悄截断。

引用字符串时,字符串的大小会增加。每一个撇号都是重复的。然后,可以使用它将部分SQL推送到缓冲区之外。这样就可以有效地减少WHERE子句的部分内容。

这可能在“用户管理”页面场景中非常有用,在这个场景中,您可以滥用“UPDATE”语句来不执行它应该做的所有检查。

因此,如果您决定引用所有参数,请确保您知道字符串大小发生了什么变化,并确保它不会被截断。

我建议使用参数。一直都是。只希望我能在数据库里执行。作为一个副作用,您更有可能获得更好的缓存命中,因为更多的语句看起来是一样的。(Oracle 8确实如此)


查看完整回答
反对 回复 2019-07-17

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信