Руководства по безопасности
Уязвимости загрузки файлов: как предотвратить веб-шеллы и RCE на уровне архитектуры
Загрузка файлов без защиты позволяет залить файл, который сервер выполнит (веб-шелл → RCE), как в массовых атаках на конструкторы страниц Joomla в 2026 году. Защита слоями: аутентификация, проверка на сервере, хранение вне корня сайта, запрет выполнения.
Статья для всех, чьё приложение (или установленное расширение) принимает файлы: формы, админ-панели, плагины CMS, API. Здесь нет инструкций по атаке — только то, как сделать собственную функцию загрузки безопасной, на основе публичных фактов. По теме: как окончательно устранять уязвимости зависимостей — в руководстве по устранению CVE, а также базовый уровень безопасности для организаций.
Что происходит на самом деле (простыми словами)
В большинстве приложений есть место, где принимаются файлы: «загрузить изображение», «сменить значок», «прикрепить документ». Если оно слабо защищено, злоумышленник отправляет файл-скрипт под видом изображения, и тот сохраняется в папку, которую отдаёт веб-сервер. Затем достаточно открыть 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) проверяются
- Хранение вне корня сайта (отдача через отдельный обработчик)
- В области загрузки выполнение скриптов запрещено
- Файл переименовывается в случайное имя, путям от пользователя не доверяют
Как это реализовать (по приоритету)
Требуйте на точке загрузки аутентификацию, права и CSRF
Точка, обрабатывающая загрузки, должна быть доступна только вошедшему пользователю с нужными правами и проверять токен CSRF. По сообщениям, в случаях с Joomla в 2026 году не хватало именно этой проверки аутентификации и прав. Сначала уберите состояние «вызвать может кто угодно».
Белый список и проверка содержимого на сервере
Никогда не доверяйте проверкам на стороне клиента и присланному браузером Content-Type. На сервере разрешайте только заведомо безопасные типы по белому списку и проверяйте реальные байты файла (magic bytes), чтобы убедиться, что это действительно этот тип. Перед решением нормализуйте двойные расширения, регистр и точки в конце.
Храните вне корня сайта (или запретите выполнение)
Сохраняйте полученные файлы там, где их нельзя открыть напрямую по URL, и отдавайте их через отдельный контроллер (с подходящим Content-Disposition). Если это сложно, хотя бы запретите выполнение скриптов в области загрузки (настройка веб-сервера). Тогда даже вредоносный файл не запустится. Это защищает вас, когда другие меры не сработали.
Случайные имена файлов, ограничения размера и частоты
Переименовывайте файлы в случайное имя, выбранное сервером, и никогда не доверяйте путям и именам файлов от пользователя (защита от обхода пути). Добавьте ограничения размера и частоты запросов, а где возможно — проверку на вредоносное ПО.
Инвентаризируйте и обновляйте расширения и CMS
Проведите инвентаризацию используемых расширений и плагинов, удалите ненужное, а остальное держите обновлённым. При массовой эксплуатации в 2026 году злоумышленники проникали через необновлённые расширения. По руководству по устранению CVE добавьте обнаружение изменений, чтобы ловить повторное появление проблемы.
Где это пересекается с тем, как устроен этот сайт
Главная проблема этой схемы — размещение недоверенного ввода там, где он может выполниться, и в таком виде, в котором может выполниться. Принципы этого сайта противоположны: не доверять полученному, изолировать важное и защищаться слоями. Не только для загрузок «проверять ввод на сервере» и «изолировать секреты и исполняемые области» — это одна и та же защита. См. также ошибки размещения в статье не храните секреты в публичных папках.
Что почитать дальше
- Вторжение ИИ-агента: вторжение в Hugging Face (2026): атака автономного ИИ-агента
- Утечка Gyazo (сентябрь 2026): что утекло и что пользователям сделать сегодня
- Подмена страницы оплаты (сентябрь 2026): программа для кражи данных карт на странице оплаты PhotoGoods (Daiko Printing) (случай, где причиной назвали злоупотребление функцией загрузки файлов)
- Термины: небезопасная десериализация (внешние данные определяют тип) / что такое RCE (удалённое выполнение кода) / что такое вредоносное ПО (веб-шелл — один из его видов)
- Предупреждения: CVE-2026-48908 (SP Page Builder) / CVE-2026-48939 (iCagenda) (та же схема «загрузка без аутентификации → RCE»)
- Практика: базовый уровень безопасности для организаций / руководство по устранению CVE / не храните секреты в публичных папках
FAQ
QПочему уязвимость загрузки файлов позволяет захватить сервер?
Если злоумышленник может разместить файл, который сервер выполнит (скрипт), то достаточно открыть его в браузере, чтобы код выполнился на сервере (веб-шелл → удалённое выполнение кода, RCE). Дальше — подмена страниц, кража данных, тайно созданные учётные записи администратора и распространение на другие системы. Главное не то, что файл приняли, а то, что он может выполниться там, где оказался.
QДостаточно ли проверять расширение файла?
Нет. Расширение и присланный браузером Content-Type легко подделать. Двойные расширения (picture.php.jpg), игра с регистром, точки и нулевые байты в конце, малоизвестные исполняемые расширения обходят наивные проверки. Защищайтесь сочетанием белого списка (разрешено только заведомо безопасное), проверки реальных байтов файла (magic bytes) и прежде всего запрета выполнения в месте хранения. Не полагайтесь на чёрный список.
QАтакуют ли небольшие сайты?
Да. Ошибки этого класса эксплуатируются без аутентификации, поэтому злоумышленники сканируют весь интернет и бьют по уязвимым версиям без разбора. При массовой эксплуатации расширений-конструкторов страниц для Joomla в 2026 году целью была каждая затронутая установка независимо от размера. «Мы слишком маленькие, чтобы нас атаковали» — не работает.