删除字符串中的空格会防止 SQL 注入吗?

信息安全 sql注入 数据库 防御 保护
2021-08-26 11:38:49

我很好奇是否可以通过从字符串输入中删除所有空格来防止 SQL 注入攻击?

我一直在OWASP阅读 SQL Injection ,但他们没有提到任何关于删除空格的内容,所以我很好奇它为什么会或不会起作用?


我正在看这个问题,它询问关于trim,而最重要的答案是这样的:

不,添加修剪不会阻止 sql 注入。trim仅删除字符串外部的空间。

Select * from aTable where name like '%'+@SearchString+'%'

如果你 @SearchString 持有类似的东西

'' update aTable set someColumn='JackedUpValue' where someColumn like '

然后当你把它们放在一起并动态执行它时,你会得到

Select * from aTable where name like '%' update aTable set someColumn='JackedUpValue' where someColumn like '%'

但是,如果您使用该搜索字符串

update aTable set someColumn='JackedUpValue' where someColumn like 

并执行了这个问题中显示的操作,你不会得到

updateaTablesetsomeColumn='JackedUpValue'wheresomeColumnlike

哪个不应该执行,对吗?

我很好奇是否有任何形式的 SQL 注入可以解决这个问题?有没有一个字危险的命令?如果这可以被击败,那么删除空格是否至少有助于防御?

注意:我问这个问题纯粹是出于好奇,而不是为了规避使用 SQL 注入预防的“正确”方法。

4个回答

不会。删除空格不会阻止 SQL 注入,因为还有许多其他方法可以让解析器处理您的输入。让我们看一个例子。想象一下,您有一个 url,它在查询中不安全地使用了用户提供的输入:

http://example/index.php?id=1 =>SELECT * from page where id = 1

在您的示例中,攻击者将使用空格:

http://example/index.php?id=1%20or%201=1 => SELECT * from page where id = 1 or 1=1

删除空格会将注入折叠成字符串。

现在让我们假设攻击者使用了另一种形式的空白,即制表符:

http://example/index.php?id=1%09or%091=1 => SELECT * from page where id = 1 or 1=1

去除空间仍然允许注射通过。

根据使用的技术,攻击者可以用/**/ %00 %09 %0a %0d或任意数量的 unicode 替换空格,从而导致 SQL 解析器进行标记化。虽然引用的示例不仅删除了空格,但上述示例利用 SQL 注释来导致不是空格的标记化。你仍然会很脆弱。

防止 SQL 注入的唯一可靠方法是使用参数化查询。

我们在 2016 年!除非您使用不安全的代码,否则 SQL 注入已成为过去。

无论您使用哪种语言,如果您想防止任何和所有SQL 注入,请使用准备好的语句或任何其他类型的数据绑定。

Prepared statements将查询与数据分开,使数据无法影响查询。

要直接回答您的问题,删除空格会减少 SQL 注入(使用过时的代码和库时),但肯定会限制您的输入文本(任何地方都没有空格)。

它会限制问题,但不会消除它。考虑以下情况:

$un = str_replace(" ", "", $_POST["username"]);
$pw = hash($_POST["password"];
$sql = "SELECT * FROM users WHERE username = '$un' AND password = '$pw'";

假设我发布了用户名admin'--那将使我以管理员身份登录,而无需使用单个空格。

正如wireghoul指出的那样,您还需要删除其他空白字符,例如制表符。但正如Julie Pelletier指出的那样,只需使用准备好的语句。试图想出聪明的方案来阻止 SQLi 没有它可能是一个有趣的游戏,但它永远不会给你准备好的语句所提供的安全性。其他一切都只是分散注意力。

没有假设你有这个作为你的 SQL:

"select * from people where last_name = '" + surname + "'"

如果我'OR(1=1)OR'a'='在输入中输入:它会变成:

select * from people where last_name = ''OR(1=1)OR'a'=''

它至少在 Oracle 和 MySQL 中执行并返回表中的所有行。