在用于 DB2 SQL 查询之前,需要从用户输入中过滤掉哪些危险字符?

信息安全 Web应用程序 应用安全 渗透测试 sql注入
2021-08-15 19:12:15

我希望完全了解如何从将插入 DB2 SQL 查询的用户输入中正确过滤/转义危险字符。

我正在分析的清理路由是这样工作的:

  • 删除所有反斜杠( s/\\// )
  • 用双单引号( s/'/''/ )替换所有单引号

我的第一直觉是检查现有的 db2 清理功能,以检查是否存在任何差异。所以我看了一下db2_real_escape_string,事实证明,它完全不同:它在字符串参数中的特殊字符前面加上反斜杠。前面带有反斜杠的字符是 \x00、\n、\r、\、'、" 和 \x1a。

我的一些具体问题是:

  1. 为什么 db2_real_escape_string() 反斜杠转义引号而不是加倍?这似乎不正确。
  2. 我正在分析的清理功能无法转义或过滤 \x00、\n、\r、\x1a、“。攻击者如何滥用这些字符?这是我的主要问题。
  3. 我的清理功能的另一个缺陷是它不支持字符集,但我猜这不是问题,因为在这种情况下,db2 被配置为使用默认字符集(我猜是' t 多字节)。所以 AFAIK,除非配置了像 GBK 这样的多字节字符集,否则像mysql GBK 中的这个已知漏洞这样的多字节 sql 注入攻击应该不是问题。
  4. 我正在分析的清理功能是否缺少任何其他注意事项/步骤?

我知道使用参数化查询是显而易见的解决方案。但是,在这种情况下,我负责 A) 确定当前设计是否可利用,以及 B) 为清理功能提供补丁(如果有必要)。

编辑考虑到上述清理功能和以下用法,我基本上希望构建一个概念验证 sql 注入有效负载: execute( " SELECT foo FROM bar WHERE col='" + my_sanitize($_GET['input']) + "'" )

鉴于当前的清理功能设计(删除反斜杠和双引号),有没有办法像上面的用法示例那样打破单引号?

感谢你的协助!

3个回答

“消毒”是脆弱的。您必须考虑数据库如何解释“特殊字符”的每一个细节,并且必须密切跟踪它,以防数据库的新子版本引入额外的特殊字符。这是一项令人筋疲力尽的工作,而且经常失败。

将用户数据插入 SQL 查询的(非常)首选方法是使用准备好的语句这对你(程序员)来说会更容易,更健壮,更安全,而且很可能更快。

“我正在分析的清理功能无法转义或过滤 \x00, \n, \r, \x1a, ”。攻击者如何滥用这些角色?这是我的首要问题。

空格和替换字符的 \x00 和 \x1a 十六进制表示。\n 和 \r 是换行和回车。

在大多数情况下,我不认为这些是非常可解释的角色。在我在这里输入的同时思考,您也许可以使用 \x00 (空白)来淹没静态缓冲区。如果系统处于二进制模式,或者如果您正在流式传输二进制文件,则 \x1a(子)字符可能会诱使系统认为您过早地到达文件末尾。

至于 \n & \r... 我想不到太多。

根据您在系统上拥有/可以获得多少信息,您可能需要调查不同的可能字符编码。有时您可以执行诸如将 UTF-8 传递给设置为 UTF-7 的进程(随机示例,不是我想到的任何实际应用程序)之类的事情,并从转换错误的魔力中获得令人兴奋的结果。

祝你的渗透测试好运。

为了验证关键用户输入,这可能会破坏您的 SQL 字符串,我将创建一个“有效字符数组/字符串”,然后检查用户输入中的每个字符是否必须在允许的字符串内。

就像您只允许数字一样,字符串可以执行如下操作:

function ParseIntoValid(userinput)
{
    string validOutput = "";
    Array allowedChars = new Array("0123456789");

    foreach (char c in userinput[])
    {

        if (c.instr(allowedChars))
        {

            // if this is a parser, then add valid chars to new output
            validOutput += c;
         }
         else
         { 
            // exit loop and return false/error if you just need a check or just ignore the illigal chars
         }
    }
}

您可以根据您的目标轻松地将此检查包装成简单的“CheckIfValid(input)”或“ParseIntoValid(input)”。

通过解析而不只是检查,你会得到一个有效的输出,也许它的字符更少,但是如果用户错误地输入了一个非法字符,这个函数将帮助“好用户”而“坏用户”仍然不会获得使用它们访问。