繁体   English   中英

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

[英]Secure method to download files in Ruby

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

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

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

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

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

...话虽如此,当您还使用了require 'open-uri'这里Kernel#open的源代码:

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

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

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

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

正如这篇文章中所建议的: https : //twin.github.io/improving-open-uri/

内核#open

Ruby 有一个Kernel#open方法,它给定一个文件路径作为File.open 但是给定一个以“|”开头的字符串,它会将其解释为一个 shell 命令并返回一个连接到生成的子进程的 IO:

open("| ls") # returns an IO connected to the `ls` shell command

Open-uri 扩展了Kernel#open并具有接受 URL 的能力。 然而,如果 URL 来自用户输入,我们不应该将它传递给Kernel#open ,因为不同的用户对什么是“URL”有不同的想法; 有人可能会认为| rm -rf ~ | rm -rf ~是一个漂亮的 URL。

一个鲜为人知的事实是Kernel#open只是委托给URI::(HTTP|HTTPS|FTP)#open ,我们可以简单地使用它:

uri = URI.parse("http://example.com/image.jpg") #=> #<URI::HTTP>
uri.open #=> #<Tempfile:/var/folders/k7/6zx6dx6x7ys3rv3srh0nyfj00000gn/T/20160524-10403-xpdakz>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM