2015-03-29 2 views
1

Мы используем refile, чтобы пользователи могли загружать изображения на наш задний конец S3. Кроме того, мы разрешаем пользователям вводить URL-адрес любого изображения в Интернете (через свойство remote_image_url.)Refile Gem: игнорировать исключение, если 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.

Edit:

Я подтвердил, что это исключение является более низкий уровень 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 

Я работаю на запрос на растяжение для исправления, чтобы исправить это.

Edit 2:

Работая над этим, мы обнаружили major security issue в Refile, что позволяет потенциальному злоумышленнику использовать удаленное выполнение кода.

В камне Refile есть функция, в которой будет указан URL-адрес, и удаленный файл будет загружен. Это можно сделать, добавив поле, например remote_image_url, в форму, где image - это имя приложения. Эта функция использовала open-uri, чтобы сделать этот HTTP-запрос без проверки пройденного URI. Злоумышленник может создавать URI, который выполняет произвольные команды оболочки на главной машине.

Если вы используете Refile версии 0.5.0 - 0.5.3, пожалуйста, обновите его до последней версии. Модернизация также решит проблему выше.

ответ

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

Смежные вопросы