在 Ruby 中下载文件的安全方法

jrd*_*oko 5 ruby security http

在 Ruby 中下载文件的常用方法是使用open-uri库并简单地调用open(url). 然而,已经指出 ,这种通过输入一起Kernel#open,这是不是安全与不受信任的输入(从一个管产生一个子进程,等等)来调用。

当 URL 是从可能不受信任的用户输入构建时,在 Ruby 中安全下载文件的最佳实践方法是什么?

Tom*_*ord 5

首先,考虑一下您为什么允许这样做?首先,赋予用户在服务器上打开任意 URL 的 权力是一件不寻常(且“危险”)的事情!

例如,即使您要防止进程生成,用户仍然可以从互联网打开任意代码 - 例如病毒。

任何允许这样做的系统很可能已经信任其用户。例如,也许唯一的用户就是你自己!

...话虽如此,这里是Kernel#open 您也使用过的require 'open-uri'源代码:

alias open_uri_original_open open

def open(name, *rest, &block)
  if name.respond_to?(:open)
    name.open(*rest, &block)
  elsif name.respond_to?(:to_str) &&
        %r{\A[A-Za-z][A-Za-z0-9+\-\.]*://} =~ name &&
        (uri = URI.parse(name)).respond_to?(:open)
    uri.open(*rest, &block)
  else
    open_uri_original_open(name, *rest, &block)
  end
end
Run Code Online (Sandbox Code Playgroud)

因此,对于仅打开 URL的用例,您可以看到实现是调用:URI.parse(url).open。因此,您的“安全”代码可以实现为:

def open_url(url)
  if url =~ URI.regexp
    URI.parse(url).open
  else
    # Handle this somehow?
  end
end
Run Code Online (Sandbox Code Playgroud)

...但是请记住,正如我上面所说,在下载任意 URL 之前您确实需要三思而后行!如果您已经信任用户输入,您可能应该只这样做;在这种情况下,我上面的代码可能是不必要的!