如何击败加倍撇号以创建 SQLi 攻击?

信息安全 sql注入
2021-08-21 11:58:10

我知道一些开发人员将撇号加倍以减轻 SQLi 的影响。(这是当输入是'所以它变成'')

有没有办法打败这个?

这是在 MS SQL Server 上。

3个回答

我试图展示安全范围的两面。安全性很重要,因此您不应该只知道如何克服安全性,还应该知道如何实施它。因此,我将首先列出预防措施。如果您不想阅读此内容,请向下滚动。

如何防止 SQL 注入?


当涉及到安全性时,将撇号加倍并不是答案,它可能会导致不安全感。答案取决于您使用的编程语言。

  • 对于 SQL Server / Oracle / MySQL
    • 对于 Java,正确使用 CallableStatements 和 PreparedStatements。
    • 使用 PHP,您将需要适当的预处理语句。
    • 使用 C#/VB.NET,您将需要参数化查询。

请注意,这些在每种语言中都是相同的概念。他们只是有不同的名字。

即使使用准备好的/可调用的语句或参数化查询,以下内容也不正确:

// Bad code, don't use 
string sqlString = "SELECT * FROM [table] WHERE [col] = '"+ something +"' AND [col2] = @Param";

您绝不能连接您的 SQL 变量。

使用 SQL Server,根据您选择的语言,您的查询应如下所示:

  • C#

    using (SqlCommand command = new ("SELECT * FROM [tab] WHERE LName = @LName", connection))
    {
        // Add new SqlParameter to the command.
        command.Parameters.Add(new SqlParameter("LName", txtBox.Test));
    
        // Read in the SELECT results.
        SqlDataReader reader = command.ExecuteReader();
        while (reader.Read())
        {
        }
    }
    
  • 爪哇

    Connection con = DriverManager.getConnection("database-connection-string","name","pass");
    
    // Question marks are the bound variables which are parsed in the defined column order. 
    PreparedStatement findLName = con.prepareStatement("SELECT * FROM [tab] WHERE LName = ?");
    
    // The order in which the question marks appear. You can have more than one in a prepared statement. First one is "1", second is "2", and so on.
    findLName.setString(1, Lastname);
    
    findLName.executeQuery();
    
    Statement stmt = con.createStatement();
    
  • PHP

    以 w3schools 为例,我不希望我的答案太长。

请注意,这仍然不能消除将脚本注入网页的可能性。您可以在可接受的范围内完全按照他们的要求插入,然后将结果输出到 HTML。

如果他们插入以下内容(简化示例):

<script> window.location.href='hxxp://www.mymalwarewebsite.com/'; </script>

...然后您将结果输出到您的页面,那么您就有大麻烦了。那么如果你从<script>to中删除任何东西</script>呢?如果他们插入怎么办:

<scri<script>pt> window.location.href='hxxp://www.mymalwarewebsite.com/'; </scri<script>pt>

...?如果您使用替换删除脚本标签,您仍然会被该漏洞利用。

除了上述内容之外,您真正想要的是以下内容

闭嘴,马克!我如何击败加倍撇号?


  • 你也许可以不同的方式打败他们您也许可以强制各种 SQL 数据库将 unicode 转换为本地字符集例如,可以转换为. 更糟糕的是:, or会被翻译成, 即. 这称为基于 Unicode 的走私ĀAU+02BCʼ'U+0027
  • 虽然不是真正的 SQL 注入攻击,但您可以尝试强制网站注入恶意代码以显示给用户。您可以尝试插入脚本标签(阅读上面的示例)。想象一下,当人们查看您的页面或用户列表时,注入一个路过式下载。
  • 尽管从技术上讲不是 SQL 注入攻击,但您可以通过浏览浏览器中的控制台并检查发送到数据库的整数,然后修改请求来克服这种保护。这称为直接对象引用漏洞利用。有各种工具可以做到这一点。Prepared Statements不会保护您免受这种攻击。请阅读 OWASP 文章

有没有办法打败这个?

也许(至少对于 MySQL)。这真的很简单(你不需要任何特殊的编码或没有引号,或任何东西):

\' [injection] -- -

例如,您有以下查询:

SELECT FROM table WHERE user = '[INPUT]';

输入是\' [injection] -- -,但'加倍后变成:\'' [injection] -- -,这导致我们进入这个查询:

SELECT FROM table WHERE user = '\'' [injection] -- -';

注入的部分将作为查询执行,因为它不再在引号内。

对 SQL 注入的唯一适当防御是准备好的语句。它们也不难使用,并且通常会产生更好的代码。对于诸如双引号之类的自制防御确实没有很好的借口。

// 更新:这似乎在 MSSQL 中实际上是不可能的。所以这将留下其他答案中已经提到的两个问题:如果在 query 中没有使用引号,或者(可能)对于某些字符集,它仍然很容易受到攻击。

这也取决于加倍实际上是如何发生的。如果它是通过数据库完成的,它可能很容易受到攻击。

这只能防止通过字符串参数进行的 SQL 注入攻击。有时,参数是一个整数(想想http://www.example.org/?page=3),那么你就不需要撇号了。例如,有时您可以检查参数是否易受攻击,如果您替换page=3page=1+2