【问题标题】:Is it possible to run a string injection attack on a redis query?是否可以对 redis 查询进行字符串注入攻击?
【发布时间】:2014-10-23 22:48:20
【问题描述】:

我正在为我的(基于 Rails 的)api 服务器构建一个基于令牌的小型身份验证库,它使用 redis 来存储生成的身份验证令牌。我担心的是:user_id = $redis.get("auth:#{token}"),其中 token 是传递给 authenticate_or_request_with_http_token 的内容。

如果这是 SQL,那将是一个巨大的危险信号 - 字符串插值 SQL 查询非常不安全。然而,据我所知,对 redis 键查询进行字符串插值并不是不安全的。

上述声明的来源是这里的 redis 文档:http://redis.io/topics/security(在 string escaping and nosql injection 标头下),但我想在我得到之前确保是这种情况Bobby Tables 攻击。

【问题讨论】:

    标签: ruby-on-rails redis


    【解决方案1】:

    您指向的文档非常明确:

    Redis 协议没有字符串转义的概念,所以在正常情况下使用普通的客户端库是不可能注入的。该协议使用前缀长度的字符串,并且是完全二进制安全的。

    【讨论】:

      【解决方案2】:

      这类字符串注入有一个小的攻击向量。虽然 redis 文档清楚地说明了在数据库上执行多个命令的难度,但它没有提到键分隔符(在您的示例中为“:”)通常需要在用作键的一部分时进行转义。

      我见过使用这些键的 redis 数据库:

      • oauth_token:123456(其中包含 OAuth 令牌参数的哈希)和
      • oauth_token:123456:is_temp(其中包含一个布尔属性以指示 OAuth 令牌是否为临时令牌)

      信任用户输入而不转义可能会导致GET oauth_token:#{token} 意外地以GET oauth_token:123456:is_temp 结尾(当用户将令牌设置为123456:is_temp 时)。

      因此,我强烈建议从潜在用户输入中正确转义冒号,以确保您的关键路径不会被这样欺骗。

      注意:有人建议使用oauth_token:123456oauth_token:is_temp:123456 修复上面的示例,但这是有缺陷的(对于用户提供的令牌is_temp:123456)。该问题的正确解决方案(不转义)是使用键 oauth_token:info:123456oauth_token:is_temp:123456 以确保这些键不能重叠,无论用户提供的输入是什么(或只是转义冒号)。

      【讨论】:

      • 另一种解决方案是确保您的缓存键永远不会以受用户污染的数据结尾。
      • 我发现这个答案非常有用。谢谢@herzi!
      【解决方案3】:

      基本上,当逐字使用输入字符串时,Redis 不会出现转义问题。例如:

      SET mykey <some-attacker-chosen-data>
      

      然而,正如 Sven Herzberg 所展示的那样,Redis 无法避免在字符串 interpolation 的上下文中使用非验证输入所产生的问题。为了将 Sven 示例转换为安全示例,可以只使用 Hash,并避免恢复到插值。否则,要么使用不常见的前缀与键插值一起使用,要么对输入使用某种基本形式的完整性检查,即过滤掉使用的分隔符,或者更好地验证输入实际上是一个数字(在特定的示例)。

      因此,虽然 Redis 不会遭受典型的 SQL 注入攻击,但当在用于创建键名的字符串插值的上下文中使用不受信任的输入时,或者更糟糕的是,Lua 脚本,应该小心。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-23
        • 2011-03-27
        • 2011-07-06
        • 1970-01-01
        • 2015-11-04
        相关资源
        最近更新 更多