Уязвимость в популярном плагине jQuery File Upload активно эксплуатируется злоумышленниками для внедрения вредоносных файлов и перехвата контроля над серверами. Плагин и более 7800 форков, используются в огромном количестве проектов, CRM-системах, WordPress плагинах, дополнениях Drupal, компонентах Joomla и многих других приложениях.
Уязвимость обнаружил специалист компании Akamai Ларри Кэшдоллар (Larry Cashdollar). Уязвимость, которой присвоен CVE-2018-9206 существует во всех версиях jQuery File Upload до 9.22.1. Ларри опубликовал инструмент для поиска уязвимого кода.
Разработчик jQuery File Upload провел собственный анализ, по итогам которого выяснилось, что в действительности уязвимость связана не с исходным кодом приложения, а с изменением, внесенным командой проекта Apache Web Server в 2010 году, косвенным образом повлиявшим на поведение плагина на серверах Apache. Речь идет о выпущенной в ноябре 2010 года версии Apache HTTP Server 2.3.9, в которой появилась возможность игнорировать пользовательские настройки в отдельных папках, выставленных через файлы .htaccess. Данная опция включена по умолчанию в версии Apache HTTP Server 2.3.9 и последующих релизах.
В свою очередь, jQuery File Upload был создан таким образом, чтобы полагаться в работе именно на кастомный файл .htaccess, содержащий ограничения безопасности для директории загрузки. Тогда разработчик попросту не знал о том, что несколько дней назад создатели Apache HTTPD внесли в свой продукт изменение, вредящее корректной работе его плагина.
Судя по всему, злоумышленники обнаружили эту уязвимость еще несколько лет назад:
Рекомендуется обновить jQuery File Upload до версии 9.22.1, в которой данная проблема устранена.
UPD: когда комменты полезнее статьи =)
Как правильно замечает @zeen:
Если более подробно — в плагине есть пример реализации обработки загрузки/листинга файлов со стороны сервера, в том числе на php. Вся беда и была в том самом «php», а именно при инициации класса UploadHandler в конструктор забыли передать параметр accept_file_types в результате чего, тот принимал значение регулярного выражения для валидации '/.+$/i, а сама валидация выглядела вот так:
if (!preg_match($this->options['accept_file_types'], $file->name)) {
$file->error = $this->get_error_message('accept_file_types');
return false;
}
Комментарии (7)
Akuma
19.10.2018 22:24+3Плагин для jQuery, который содержит потенциально опасный код на PHP, который полагается на веб-сервер Apache при загрузке файлов?
Люди, что с вами блин такое? Свой загрузчик файлов пишется очень и очень просто. Серверная часть так вообще должна интегрироваться в ваш сайт, а не быть какой-то «из вне». Зачем вообще его использовать во время, когда даже полифилы практически не нужны?tcapb1
20.10.2018 00:39+1Это сейчас так, а 9 лет назад, во время написания плагина всё было по-другому. Тогда не было нормальной поддержки браузерами загрузки нескольких файлов, были сложности с ресайзом картинок на стороне браузера перед заливкой, нужны были фоллбэки во флэш и т.д. Разбираться со всем этим самостоятельно было бы мучительно долго.
Akuma
20.10.2018 01:30Да, я в курсе, примерно 9 лет назад находил этот плагин и в итоге все равно было проще написать свое решение с ифреймами для ИЕ, чем разбираться в этом.
А вообще плагин в статье особо не при чем. Там лишь пример обработки загрузки, а не эталонная и обязательная реализация.
zenn
19.10.2018 22:29+5Автор, вы бы хоть сами разобрались в чем проблема, перед тем как публиковать этот пост. Перефразирую пост 1 строкой, чтобы было понятно:
Используя javascript плагины будьте крайне бдительны к любой серверной части, которая может в нем содержатся.
Если более подробно — в плагине есть пример реализации обработки загрузки/листинга файлов со стороны сервера, в том числе на php. Вся беда и была в том самом «php», а именно при инициации классаUploadHandler
в конструктор забыли передать параметрaccept_file_types
в результате чего, тот принимал значение регулярного выражения для валидации'/.+$/i
, а сама валидация выглядела вот так:
if (!preg_match($this->options['accept_file_types'], $file->name)) { $file->error = $this->get_error_message('accept_file_types'); return false; }
Ничего не имею против php, такую ошибку вполне можно допустить на любом языке…
P.S. — апач тут непричем, просто забыли проверить даже расширение файла, не говоря даже о его mimetype…Sabubu
20.10.2018 07:45Тут проблема, как я понял, в том, что вместе с плагином в одной папке поставлялся этот кривой PHP код. И если вы просто копировали папку с плагином на сервер с PHP, то получали уязвимость (вам не надо было что-то подключать и вызывать из своего кода для этого). Ну и, кстати, htaccess, который должен быть предотвращать запуск php кода, не работает под nginx. Так себе защита (плюс, если там нет запрета, можно загрузить свой собственный .htaccess и переопределить правила).
Мораль: либо при сохранении файла проверяйте его расширение по белому списку, либо загружайте файлы на сервер без интерпретатора.
> не говоря даже о его mimetype…
Это не имеет смысла. Можно сделать файл, который будет иметь mime-type image/jpg и при этом будет валидным PHP-файлом.
Balek
Чё?