Refile Gem: игнорировать исключение, когда remote_image_url является недействительным или не существует
Мы используем 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 недействителен (сродни тому, как validate_download
вариант в CarrierWave работает) и, в идеале, использовать вместо этого наше запасное изображение?
Мы попытались установить устройство с 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
, позволяя потенциальному злоумышленнику использовать удаленное выполнение кода.
У драгоценного камня Refile есть функция, где будет предоставлен URL и удаленный файл будет загружен. Это можно сделать, добавив поле вроде
remote_image_url
в форме, гдеimage
это имя вложения. Эта функция использовала open-uri для выполнения этого HTTP-запроса без проверки переданного URI. Злоумышленник может создать URI, который выполняет произвольные команды оболочки на хост-компьютере.
Если вы используете Refile
версии 0.5.0
- 0.5.3
Пожалуйста, обновитесь до последней версии. Обновление также решит проблему выше.
1 ответ
После разговора с сопровождающим 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
,
Драгоценный камень был теперь исправлен (0.5.4
), и обновление является правильным решением.