Refile Gem: 当remote_image_url无效或不存在时忽略异常
Refile Gem: Ignore exception when remote_image_url is invalid or doesn't exist
我们正在使用 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'
是否可以选择忽略输入的 URL 无效的情况(类似于 CarrierWave 中的 validate_download
选项的工作方式),理想情况下,使用我们的后备图像代替?
我们已尝试将 raise_errors
选项设置为 false
来安装附件,但结果相同。
我们的项目使用 Rails 4.2.0
和 Refile 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,使潜在的攻击者能够使用远程代码执行。
The Refile gem has a feature where a URL will be supplied and the remote file will be uploaded. This can be done by adding a field like remote_image_url
in a form, where image
is the name of the attachment. This feature was using open-uri to make this HTTP request without validating the passed URI. An attacker can craft a URI which executes arbitrary shell commands on the host machine.
如果您使用的是 Refile
版本 0.5.0
- 0.5.3
,请升级到最新版本。升级也会解决上述问题。
在与 Refile
的维护者交谈后,这将在下一次迭代中修复。现在,我们创建了以下非常简单的 Ruby class 作为变通方法。
# 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版本中打补丁,我认为现在已经足够了。
免责声明:
尽管这抵消了原始问题 edit 2 中提到的一些漏洞,但如果攻击者可以创建一个名为http:
在文件系统上,像http:/../etc/passwd
这样的字符串会通过URL 验证,但仍然通过Kernel.open
.
读取本地文件
Gem 现已打上补丁 (0.5.4
),升级是正确的解决方案。
我们正在使用 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'
是否可以选择忽略输入的 URL 无效的情况(类似于 CarrierWave 中的 validate_download
选项的工作方式),理想情况下,使用我们的后备图像代替?
我们已尝试将 raise_errors
选项设置为 false
来安装附件,但结果相同。
我们的项目使用 Rails 4.2.0
和 Refile 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,使潜在的攻击者能够使用远程代码执行。
The Refile gem has a feature where a URL will be supplied and the remote file will be uploaded. This can be done by adding a field like
remote_image_url
in a form, whereimage
is the name of the attachment. This feature was using open-uri to make this HTTP request without validating the passed URI. An attacker can craft a URI which executes arbitrary shell commands on the host machine.
如果您使用的是 Refile
版本 0.5.0
- 0.5.3
,请升级到最新版本。升级也会解决上述问题。
在与 Refile
的维护者交谈后,这将在下一次迭代中修复。现在,我们创建了以下非常简单的 Ruby class 作为变通方法。
# 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版本中打补丁,我认为现在已经足够了。
免责声明:
尽管这抵消了原始问题 edit 2 中提到的一些漏洞,但如果攻击者可以创建一个名为http:
在文件系统上,像http:/../etc/passwd
这样的字符串会通过URL 验证,但仍然通过Kernel.open
.
Gem 现已打上补丁 (0.5.4
),升级是正确的解决方案。