Перейти к содержимому
>_ITDITDПлатформа веб-безопасности

Руководства по безопасности

Уязвимости загрузки файлов: как предотвратить веб-шеллы и RCE на уровне архитектуры

Загрузка файлов без защиты позволяет залить файл, который сервер выполнит (веб-шелл → RCE), как в массовых атаках на конструкторы страниц Joomla в 2026 году. Защита слоями: аутентификация, проверка на сервере, хранение вне корня сайта, запрет выполнения.

Опубликовано 2026-07-08 Обновлено 2026-10-04 9 мин чтения

Статья для всех, чьё приложение (или установленное расширение) принимает файлы: формы, админ-панели, плагины CMS, API. Здесь нет инструкций по атаке — только то, как сделать собственную функцию загрузки безопасной, на основе публичных фактов. По теме: как окончательно устранять уязвимости зависимостей — в руководстве по устранению CVE, а также базовый уровень безопасности для организаций.

Без аутентификации → RCE
Худшее сочетание, цель слепого сканирования
CWE-434
Неограниченная загрузка файлов опасного типа
Только проверка расширения
Обходится подделкой и двойными расширениями
Защита слоями
Если один слой не сработал, остановит следующий

Что происходит на самом деле (простыми словами)

В большинстве приложений есть место, где принимаются файлы: «загрузить изображение», «сменить значок», «прикрепить документ». Если оно слабо защищено, злоумышленник отправляет файл-скрипт под видом изображения, и тот сохраняется в папку, которую отдаёт веб-сервер. Затем достаточно открыть URL этого файла в браузере: если сервер выполняет содержимое как программу, злоумышленник может удалённо выполнять команды. Это веб-шелл (небольшая программа удалённого управления, оставленная на сервере), а за ним следуют подмена страниц, кража данных, тайно созданные учётные записи администратора и распространение на другие системы.

Проблема в месте хранения и выполнении, а не в приёме файла

Загрузка — законная функция. Опасно размещать полученное там, где оно может выполниться, и в таком виде, в котором может выполниться. И наоборот: даже если пришёл подозрительный файл, вреда не будет, если он попадает туда, где ничего не выполняется, его содержимое проверяется, а точка загрузки требует аутентификации. Смените подход с «блокировать плохие файлы» на «место хранения никогда ничего не выполняет».

Реальные случаи 2026 года: массовая эксплуатация расширений Joomla (одна и та же схема)

В 2026 году в нескольких расширениях Joomla одно за другим раскрыли одну и ту же схему «загрузка без аутентификации → RCE», и их широко эксплуатировали. По сообщениям, в них сочеталось «нет проверки аутентификации + нет проверки типа файла + хранение в корне сайта» — типичная комбинация. Проблема вышла за пределы конструкторов страниц и затронула расширение-календарь событий, а CISA установило короткие сроки устранения.

Три реальных случая (по публичным данным)
SP Page Builder (CVE-2026-48908)
Разработчик — JoomShaper. Затронуты версии ≤ 6.6.1, исправлено в 6.6.2. По сообщениям, загрузка пользовательских значков не проверяла ни аутентификацию, ни тип; CVSS 10.0, активно эксплуатируется (в каталоге CISA KEV). Разбор: CVE-2026-48908.
iCagenda (CVE-2026-48939)
Разработчик — joomlic, расширение-календарь событий. Затронуты 3.2.1–3.9.14 / 4.0.0–4.0.7, исправлено в 3.9.15 / 4.0.8. По сообщениям, контроль доступа в обработчике вложений публичной формы регистрации на событие проверялся только на уровне представления; CVSS 10.0, активно эксплуатируется (в каталоге CISA KEV). Разбор: CVE-2026-48939.
Page Builder CK (CVE-2026-56290)
Разработчик — joomlack.fr. Затронуты ≤ 3.5.10, исправлено в 3.6.0 (для старых веток перенесено в 3.1.1 / 3.4.10). По сообщениям, та же загрузка без аутентификации, ведущая к RCE; CVSS 10.0.
Что общего
Эксплуатируется без входа = цель сканирования без разбора. Сообщалось, что атаки были направлены на сохранение доступа: создание скрытых учётных записей администратора и размещение веб-шеллов, чтобы доступ остался и после исправления уязвимости.
Первое исправление
Обновите затронутое расширение до исправленной версии (и проведите инвентаризацию, удалив неиспользуемые расширения). Плюс архитектура и настройки, описанные ниже, слоями.

Урок: неиспользуемое расширение часто оказывается самым эксплуатируемым слабым местом

У обоих случаев одна общая черта: для проникновения использовалось забытое, но всё ещё установленное расширение. Каждый добавленный плагин или расширение CMS увеличивает поверхность атаки. Простая инвентаризация и удаление ненужного сокращают то, по чему может ударить такая массовая эксплуатация (как провести инвентаризацию ресурсов).

Каждый этап атаки и как его остановить

В этой схеме на каждом шаге есть место, где атаку можно остановить. Читайте это как описание того, где её можно остановить, а не как инструкцию.

1. Файл отправляется на точку без аутентификации

Кто угодно может обратиться к обработчику загрузки и отправить скрипт.

Защита: аутентификация + проверка прав + токен CSRF

↓

2. Он проходит проверку типа и сохраняется

Расширение / Content-Type подделаны, файл замаскирован под «изображение».

Защита: белый список на сервере + проверка содержимого (magic bytes)

↓

3. Он попадает в корень сайта и доступен по URL

Сохранён по угадываемому пути, открывается прямо в браузере.

Защита: хранение вне корня сайта / случайные имена файлов

↓

4. Сервер выполняет его как скрипт

В папке хранения разрешено выполнение = веб-шелл → RCE.

Защита: запрет выполнения скриптов в области загрузки

На каждом шаге есть место, где атаку можно остановить. Эшелонированная защита — это несколько таких мест, а не одна мера.

Небезопасная и безопасная конфигурация

Конфигурация, которая не выдерживает

  • На точке загрузки нет аутентификации / проверки прав (доступна любому)
  • Решение принимается только по расширению или Content-Type (подделка, двойное расширение)
  • Полученные файлы сохраняются прямо в корень сайта
  • В месте хранения всё ещё можно выполнять скрипты
  • Имена файлов задаёт пользователь / их можно угадать

Конфигурация, которая выдерживает

  • На точке загрузки обязательны аутентификация + права + CSRF
  • Тип проверяется по белому списку, реальные байты (magic bytes) проверяются
  • Хранение вне корня сайта (отдача через отдельный обработчик)
  • В области загрузки выполнение скриптов запрещено
  • Файл переименовывается в случайное имя, путям от пользователя не доверяют

Как это реализовать (по приоритету)

1

Требуйте на точке загрузки аутентификацию, права и CSRF

Точка, обрабатывающая загрузки, должна быть доступна только вошедшему пользователю с нужными правами и проверять токен CSRF. По сообщениям, в случаях с Joomla в 2026 году не хватало именно этой проверки аутентификации и прав. Сначала уберите состояние «вызвать может кто угодно».

2

Белый список и проверка содержимого на сервере

Никогда не доверяйте проверкам на стороне клиента и присланному браузером Content-Type. На сервере разрешайте только заведомо безопасные типы по белому списку и проверяйте реальные байты файла (magic bytes), чтобы убедиться, что это действительно этот тип. Перед решением нормализуйте двойные расширения, регистр и точки в конце.

3

Храните вне корня сайта (или запретите выполнение)

Сохраняйте полученные файлы там, где их нельзя открыть напрямую по URL, и отдавайте их через отдельный контроллер (с подходящим Content-Disposition). Если это сложно, хотя бы запретите выполнение скриптов в области загрузки (настройка веб-сервера). Тогда даже вредоносный файл не запустится. Это защищает вас, когда другие меры не сработали.

4

Случайные имена файлов, ограничения размера и частоты

Переименовывайте файлы в случайное имя, выбранное сервером, и никогда не доверяйте путям и именам файлов от пользователя (защита от обхода пути). Добавьте ограничения размера и частоты запросов, а где возможно — проверку на вредоносное ПО.

5

Инвентаризируйте и обновляйте расширения и CMS

Проведите инвентаризацию используемых расширений и плагинов, удалите ненужное, а остальное держите обновлённым. При массовой эксплуатации в 2026 году злоумышленники проникали через необновлённые расширения. По руководству по устранению CVE добавьте обнаружение изменений, чтобы ловить повторное появление проблемы.

Где это пересекается с тем, как устроен этот сайт

Главная проблема этой схемы — размещение недоверенного ввода там, где он может выполниться, и в таком виде, в котором может выполниться. Принципы этого сайта противоположны: не доверять полученному, изолировать важное и защищаться слоями. Не только для загрузок «проверять ввод на сервере» и «изолировать секреты и исполняемые области» — это одна и та же защита. См. также ошибки размещения в статье не храните секреты в публичных папках.

Что почитать дальше

FAQ

QПочему уязвимость загрузки файлов позволяет захватить сервер?
A

Если злоумышленник может разместить файл, который сервер выполнит (скрипт), то достаточно открыть его в браузере, чтобы код выполнился на сервере (веб-шелл → удалённое выполнение кода, RCE). Дальше — подмена страниц, кража данных, тайно созданные учётные записи администратора и распространение на другие системы. Главное не то, что файл приняли, а то, что он может выполниться там, где оказался.

QДостаточно ли проверять расширение файла?
A

Нет. Расширение и присланный браузером Content-Type легко подделать. Двойные расширения (picture.php.jpg), игра с регистром, точки и нулевые байты в конце, малоизвестные исполняемые расширения обходят наивные проверки. Защищайтесь сочетанием белого списка (разрешено только заведомо безопасное), проверки реальных байтов файла (magic bytes) и прежде всего запрета выполнения в месте хранения. Не полагайтесь на чёрный список.

QАтакуют ли небольшие сайты?
A

Да. Ошибки этого класса эксплуатируются без аутентификации, поэтому злоумышленники сканируют весь интернет и бьют по уязвимым версиям без разбора. При массовой эксплуатации расширений-конструкторов страниц для Joomla в 2026 году целью была каждая затронутая установка независимо от размера. «Мы слишком маленькие, чтобы нас атаковали» — не работает.