Ruby on rails Refile Gem:当远程图像url无效或不';不存在
我们使用它允许用户将图像上传到我们的S3后端。此外,我们允许用户输入指向internet上任何图像的URL(通过Ruby on rails Refile Gem:当远程图像url无效或不';不存在,ruby-on-rails,ruby-on-rails-4,refile,Ruby On Rails,Ruby On Rails 4,Refile,我们使用它允许用户将图像上传到我们的S3后端。此外,我们允许用户输入指向internet上任何图像的URL(通过remote\u image\u URL属性) 只要输入的URL指向实际文件,这种方法就可以正常工作。但是,如果URL中有错误,或者提供了一些无意义的输入,Refile将抛出以下异常: Errno::ENOENT (No such file or directory @ rb_sysopen - thiswillnotwork): app/controllers/my/deals_
remote\u image\u 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'
是否有一个选项可以忽略输入的URL无效的情况(类似于CarrierWave中的validate\u download
选项的工作方式),理想情况下,使用我们的回退图像
我们已尝试将raise\u errors
选项设置为false
安装附件,但结果相同
我们的项目使用了rails4.2.0
和refile0.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
中发现了一个漏洞,使潜在的攻击者能够使用远程代码执行
refilegem有一个功能,其中将提供一个URL,并上传远程文件。这可以通过在表单中添加类似remote\u image\u url
的字段来实现,其中image
是附件的名称。此功能使用开放uri发出此HTTP请求,而不验证传递的uri。攻击者可以创建一个URI,在主机上执行任意shell命令
如果您使用的是
Refile
版本0.5.0
-0.5.3
,请升级至最新版本。升级也将解决上述问题。在与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
这是一个非常原始的方法,但是考虑到它将被修补在下一个宝石版本中,我认为这已经足够好了。 免责声明:
虽然这弥补了原始问题的编辑2中提到的一些漏洞,但攻击者仍然能够执行远程代码,如果他们能够在文件系统上创建名为http:的文件夹,就像http:///etc/passwd这样的字符串将通过URL验证一样,但是仍然通过内核读取本地文件。打开
Gem现在已经补丁(0.5.4
),升级是正确的解决方案