Refile Gem:当remote_image_url无效或不存在时忽略异常

时间:2015-03-29 08:52:33

标签: ruby-on-rails ruby-on-rails-4 refile

我们正在使用refile来允许用户将图片上传到我们的S3后端。此外,我们允许用户选择在互联网上输入任何图像的URL(通过remote_image_url属性。)

只要输入的URL指向实际文件,这样就可以正常工作。但是,如果URL中存在错误,或者给出了一些无意义的输入,Refile将抛出以下异常:

Errno::ENOENT (No such file or directory @ rb_sysopen - thiswillnotwork):
  app/controllers/my/deals_controller.rb:17:in `create'
  appsignal (0.11.2) lib/appsignal/rack/listener.rb:13:in `call'

是否可以选择忽略输入的网址无效的情况(类似于CarrierWave中validate_download选项的工作方式),理想情况下,请使用我们的后退图片?

我们尝试将raise_errors选项设置为false来安装附加者,但结果相同。

我们的项目使用Rails 4.2.0Refile 0.5.3

修改

我已确认此异常是来自SystemCallError的较低级别Kernel.open,并且此异常类型未被Refile拯救:

rescue OpenURI::HTTPError, RuntimeError => error
  raise if error.is_a?(RuntimeError) and error.message !~ /redirection loop/
  @errors = [:download_failed]
  raise if @raise_errors
end

我正在处理拉取请求以重新修复此问题。

编辑2:

在处理此问题时,我们在Refile中发现major security issue,使潜在的攻击者能够使用远程代码执行。

  

Refile gem有一个功能,即提供URL并上传远程文件。这可以通过在表单中​​添加remote_image_url之类的字段来完成,其中image是附件的名称。此功能使用open-uri来发出此HTTP请求,而不验证传递的URI。攻击者可以创建一个URI,在主机上执行任意shell命令。

如果您使用的是Refile个版本0.5.0 - 0.5.3,请升级到最新版本。升级也将解决上述问题。

1 个答案:

答案 0 :(得分:0)

在与Refile的维护者交谈之后,这将在下一次迭代中修复。就目前而言,我们已经创建了以下简单的Ruby类作为解决方法。

# app/services/remote_url.rb
class RemoteUrl
  def initialize(url)
    @url = url
  end

  def valid?
    URI.parse(@url).kind_of?(URI::HTTP)
  rescue URI::InvalidURIError
    false
  end
end

我在我的控制器中使用它,如下所示:

# app/controllers/model_controller.rb
def model_params
  sanitize_remote_url!
  params.require(:model).permit(:description, ..., :image, :remote_image_url)
end

def sanitize_remote_url!
  params[:model].delete(:remote_image_url) unless RemoteUrl.new(params[:model][:remote_image_url]).valid?
end

这是一种非常原始的方法,但考虑到它将在下一个Gem版本中修补,我现在认为这已经足够了。

<强>声明:

虽然这可以抵消原始问题的编辑2 中提到的某些漏洞,但是如果攻击者可以创建名为http:的文件夹,攻击者仍然可以执行远程代码执行在文件系统上,像http:/../etc/passwd这样的字符串将通过URL验证,但仍然通过Kernel.open读取本地文件。

Gem现已修补(0.5.4),升级是正确的解决方案。