Уязвимость в Paperclip (XSS/RCE)

    Paperclip это самый популярный джем для загрузки файлов/аватарок в рельсах. В нем был найден довольно простой логический баг, ведущий к загрузке произвольного файла на сервер, то есть с произвольным extension: file.html, file.php, file.cgi и так далее.

    Paperclip имеет «магическую» (как и все в рельсах) систему адаптеров. Если на входе объект типа File, то берется файловый адаптер, если строчка то сверяется по разным паттернам. Если строчка типа URL http://* то делается запрос по этому URL чтобы выкачать файл.

    io_adapters/uri_adapter.rb содержал следующий код:
          @original_filename = @target.path.split("/").last
          @original_filename ||= "index.html"
          self.original_filename = @original_filename.strip
    
          @content_type = @content.content_type if @content.respond_to?(:content_type)
          @content_type ||= "text/html"
    

    Заметьте, контент тайп берется из хедера ответа сервера, которому доверять нет никакого смысла. Вот я создал URL возвращающий картинку www.sakurity.com/img.jpg.htm но имеющий .htm в расширении.

    Paperclip думает что мы дали ему картинку, так как Content-Type вернулся image/jpg и сохраняет файл как file.jpg.htm. Но если веб сервер (apache/ngin) сервит этот файл то смотрит уже на .htm в конце и отвечает внутренностями нашего файла и Content-Type=text/html. Браузеры парсят ответ как обычную HTML страницу.

    Ах да, нашу нагрузку мы спрячем в EXIF хедеры, так что файл все еще будет валидным JPG (на случай если на сервере есть какие то resize операции).

    ÛßÙ4Ù¬ıPıfiˆmˆ˚˜ä¯ ¯®˘8˘«˙W˙Á˚w¸ ¸ò˝)˝∫˛K˛‹ˇmˇˇˇ· ‚EifII*
    Ü å ¢ ™( 1 ≤2 «£ €iá ¯CanonCanon DIGITAL IXUS 70¥ ¥ f-spot version 0.3.52008:09:08 11:29:26 öÇ Z ùÇ b 'à Pê 0220

    image
    Для RCE (выполнения кода) нужно чтобы сервер выполнял .php/.pl/.cgi файлы, что впринципе редкость для Rails приложений, но я могу ошибаться.

    Чтобы проверить уязвимы ли вы, удалите type=file у тэга и пошлите URL.
    image

    Баг был зарепорчен 11 декабря и исправлен лишь 2 февраля. Выпущена новая мажорная версия Paperclip 4, также делающая вайтлистинг content-type-ов обязательным (ранее многие разработчики забывали вообще ограничивать типы файлов для загрузки). Ну и вообще, это может быть интересным вектором для проверки download-by-URL функциональности.
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 5

      +1
      Хабр съел все буковки 'x'. Уэ тэ эф?
        +1
        Я бы не сказал, что доверять заголовку Content-type — плохая идея и вообще не имеет смысла. В конце концов, URL может и не содержать нужного расширения вообще. Какой-нибудь example.com/avatar.php?id=12345

        Скорее, тут следовало бы на основе принятого Content-type присвоить сохраняемому файлу правильное расширение. В идеале — взять настройки веб-сервера по преобразованию расширения в mime тип — и применить это преобразование в обратном порядке.
        Но сойдет и простое неизменяемое преобразование image/jpeg -> .jpg. Вряд ли кто-то будет обрабатывать .jpg как text/html, а кто так сделает — сам и виноват.
          +1
          Да, именно. Так работают аналоги (Carrierwave). Изначально сохранять с оригинальным именем это плохая идея.

          Ну и более того я считаю адаптеры надо подключать мануально.
            0
            Carrierwave из коробки так не делает, но для него есть github.com/deviantech/carrierwave-mimetype-fu
              0
              Я имел ввиду стиль валидации. Он пользуется листом extension-ов, а не контент тайпов

        Only users with full accounts can post comments. Log in, please.