【问题标题】:Sanitizing User Regexp清理用户正则表达式
【发布时间】:2010-12-31 10:40:49
【问题描述】:

我想编写一个函数,允许用户根据正则表达式匹配数据,但我担心用户字符串的卫生。我知道使用 SQL 查询可以使用绑定变量来避免 SQL 注入攻击,但我不确定是否有这样的正则表达式机制。我看到有Regexp.escape,但我想允许有效的正则表达式。

这是示例函数:

  def tagged?(text)
    tags.each do |tag|
      return true if text =~ /#{tag.name}/i
    end
    return false
  end

由于我只是直接在 tag.name 上匹配,是否有可能有人可以插入 Proc 调用或其他东西来打破正则表达式并造成严重破坏?

任何关于最佳实践的建议都将不胜感激。

【问题讨论】:

    标签: ruby-on-rails ruby regex security sanitization


    【解决方案1】:

    Regexp 中的插值字符串不会执行,但会产生烦人的警告:

    /#{exit -3}/.match('test')
    # => exits
    
    foo = '#{exit -3}'
    /#{foo}/.match('test')
    # => warning: regexp has invalid interval
    # => warning: regexp has `}' without escape
    

    这两个警告似乎分别与开头的 #{ 和结尾的 } 相关,并且是独立的。

    作为一种更有效的策略,您可能希望将标签列表清理为可以运行一次的组合正则表达式。构造和测试 N 个正则表达式的效率通常远低于使用 N 个部分的 1 个正则表达式。

    大概是这样的:

    class Taggable
      def tags
        @tags
      end
    
      def tags=(value)
        @tags = value
    
        @tag_regexp = Regexp.new(
          [
            '^(?:',
            @tags.collect do |tag|
              '(?:' + tag.sub(/\#\{/, '\\#\\{').sub(/([^\\])\}/, '\1\\}') + ')'
            end.join('|'),
            ')$'
          ].to_s,
          Regexp::IGNORECASE
        )
      end
    
      def tagged?(text)
        !!text.match(@tag_regexp)
      end
    end
    

    可以这样使用:

    e = Taggable.new
    e.tags = %w[ #{exit-3} .*\.gif .*\.png .*\.jpe?g ]
    
    puts e.tagged?('foo.gif').inspect
    

    如果执行了 exit 调用,程序将在那里停止,但它只是将其解释为文字字符串。为了避免警告,它用反斜杠转义。

    【讨论】:

    • 我正在测试尝试插入 proc 并得到相同的错误。我看起来好像在分配给 activerecord 对象时被转义:# 我在实际尝试将它用作正则表达式的一部分时遇到了同样的错误。我只是不确定我是否遗漏了什么。
    【解决方案2】:

    您可能应该创建一个 Regexp 类的实例。

    def tagged?(text)
      return tags.any? { |tag| text =~ Regexp.new(tag.name, Regexp::IGNORECASE) }
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-31
      • 1970-01-01
      • 2010-11-27
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      相关资源
      最近更新 更多