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), и обновление является правильным решением.

Другие вопросы по тегам