Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Invia
StrumentiExploitsBlog
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.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2026-18322 — Analisi della causa principale, verifica passiva della versione e PoC di laboratorio per CVE-2026-18322, un'escalation di privilegi non autenticata nel plugin WordPress Smart Popup di Supsystic. | Kitploit
Strumenti/GitHubGitHub/i3it/cve-2026-18322
Escalation di PrivilegiScanner di VulnerabilitàAnalisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebVirtualizzazione per la SicurezzaSicurezza WebPenetration TestingPaper e RicercaLab e Pratica
GitHub
326 giorni faNon ancora revisionato

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
i3it/cve-2026-18322

CVE-2026-18322

Analisi della causa principale, verifica passiva della versione e PoC di laboratorio per CVE-2026-18322, un'escalation di privilegi non autenticata nel plugin WordPress Smart Popup di Supsystic.

Vedi Repository

CVE-2026-18322 — Smart Popup di Supsystic Privilege Escalation

CVE Severity Affected Fixed in CWE Python Tests License

Ricerca di sicurezza su CVE-2026-18322, una vulnerabilità di privilege-escalation non autenticata nel plugin WordPress Smart Popup by Supsystic (popup-by-supsystic). Questo repository contiene un'analisi della causa radice derivata dal diff del codice sorgente upstream, le patch estratte, uno strumento di rilevamento (fingerprinter passivo di versione) per identificare le installazioni affette e un laboratorio per il PoC di sfruttamento.

La vulnerabilità è pubblica e corretta. Questo lavoro è pubblicato per uso difensivo: aiutare gli operatori a trovare e correggere gli host affetti.


Versioni affette

Intervallo di versioniStato
< 1.13.0Vulnerabile
>= 1.13.0Corretta

La 1.13.0 (rilasciata il 31.07.2026) è la prima release corretta; ripara tutti e tre gli anelli della catena descritta di seguito. Vedi §1 dell'analisi.


Riepilogo della vulnerabilità

Tre debolezze indipendenti si compongono nella creazione non autenticata di un amministratore:

1. Una collisione nella mappa dei permessi — havePermissions() combinava due mappe di permessi con array_merge(). Entrambe usano la chiave stringa PPS_USERLEVELS ('userlevels'), e array_merge() sovrascrive le chiavi stringa, quindi la lista breve predefinita del controller di base sostituiva in blocco la lista del modulo popup — rimuovendo silenziosamente la restrizione di amministratore da save e da altri nove metodi:

root@kitploit:~
$permissions     = $mod->getController()->getPermissions();      // [... 'save' ...]
$permissionsBase = $mod->getController()->getBasePermissions();  // ['getListForTbl','removeGroup','clear']
$permissions     = array_merge($permissions, $permissionsBase);  // base vince — 'save' è sparito

Il controllo fallisce aperto: un'azione assente dalla mappa non viene mai negata.

2. Un nonce riutilizzabile inviato a estranei — save richiedeva comunque un pps_nonce, ma l'email di conferma dell'iscrizione incorporava esattamente quell'azione nonce. Per gli utenti non autenticati un nonce di WordPress è legato a uid=0, quindi il token generato per un iscritto anonimo risulta valido per qualsiasi attaccante anonimo.

3. Nessuna allowlist di ruoli lato server — createWpSubscriber() passava il ruolo configurato direttamente a WP_User::set_role(). La lista di ruoli sicuri del plugin (che esclude administrator) era applicata solo durante il rendering del menu a tendina di amministrazione — un controllo solo di UI.

Concatenate: iscriviti per ottenere un nonce → riproducilo contro popup::save per impostare sub_wp_create_user_role=administrator → attiva il flusso di iscrizione → account amministratore persistente.

Procedura completa con riferimenti a file/righe: docs/ANALYSIS.md.


Rilevamento — il checker passivo

poc/cve_2026_18322_check.py determina se un sito esegue una versione affetta. Non tenta mai lo sfruttamento: emette semplici GET HTTP e legge la versione che l'installazione pubblica su se stessa.

Installazione

root@kitploit:~
git clone <this-repo> && cd CVE-2026-18322
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

requests è consigliato ma opzionale — lo strumento ripiega sulla libreria standard.

Utilizzo

root@kitploit:~
# Singolo target
python3 poc/cve_2026_18322_check.py https://example.com

# Con evidenze di supporto
python3 poc/cve_2026_18322_check.py https://example.com -v

# Molti target, in concorrenza, esportando i risultati
python3 poc/cve_2026_18322_check.py -f targets.txt -t 20 --json results.json
python3 poc/cve_2026_18322_check.py -f targets.txt --csv results.csv --only-vulnerable

# Attraverso un proxy, ignorando gli errori TLS (uso in laboratorio)
python3 poc/cve_2026_18322_check.py https://staging.internal -k --proxy http://127.0.0.1:8080

I target possono essere forniti come argomenti o tramite -f (- legge da stdin). Un hostname nudo è assunto come https://.

Esempio

root@kitploit:~
$ python3 poc/cve_2026_18322_check.py https://example.com -v
[VULNERABLE] https://example.com/  (Smart Popup by Supsystic 1.11.2)  < 1.13.0 affected by CVE-2026-18322; upgrade to 1.13.0+
      - asset-version: plugin asset enqueued with ?ver=1.11.2  (https://example.com/)
      - homepage-reference: references /plugins/popup-by-supsystic/  (https://example.com/)
      - readme: plugin readme.txt is publicly readable  (https://example.com/wp-content/plugins/popup-by-supsystic/readme.txt)
      - readme-stable-tag: Stable tag: 1.11.2  (.../readme.txt)

Stati

Codici di uscita: 0 = nessun target vulnerabile, 1 = almeno uno vulnerabile, 2 = errore di utilizzo.

Come rileva

Due segnali passivi, entrambi semplici GET HTTP di risorse pubbliche:

  1. Cache-buster degli asset — il plugin accoda i suoi CSS/JS con ?ver=PPS_VERSION (classes/frame.php:410,473), quindi la homepage spesso rivela la versione esatta.
  2. readme.txt — Stable tag: è autorevole e ha la precedenza su un asset in cache potenzialmente obsoleto; il changelog funge da fallback.

La scansione della homepage scopre anche directory wp-content rinominate (es. /app/ di Bedrock) così la ricerca del readme segue il layout reale del sito.


Sicurezza

Lo strumento di rilevamento non tenta lo sfruttamento. Nessun exploit weaponizzato per questa CVE è pubblicato qui: l'unico codice che esegue la catena completa è rigidamente vincolato al laboratorio locale (vedi sotto).

Il checker passivo esegue solo il fingerprinting della versione. Il suo HttpClient non espone nessun verbo HTTP diverso da GET — imposto per costruzione e verificato nella suite di test, così non può emettere una richiesta che modifica lo stato nemmeno per errore. Non chiama mai popup::save, non invia un parametro sub_wp_create_user_role, non invia un modulo di iscrizione, non attiva un'email di conferma, né crea o modifica alcun utente, popup o impostazione. Legge due risorse pubbliche — la homepage e readme.txt — e nient'altro.

Questa sicurezza ha un costo, dichiarato apertamente: il verdetto vale solo quanto i metadati di versione che l'host pubblica. Compromessi e modalità di fallimento: §9.

L'exploit del laboratorio viene eseguito solo nel laboratorio

lab/exploit_full_chain.py è l'unico pezzo di codice qui che esegue l'attacco reale, e crea un amministratore WordPress. È pubblicato affinché l'analisi possa essere riprodotta anziché presa per fede — un'affermazione su un bug di autorizzazione che non può essere dimostrata è un'asserzione, non una scoperta. È scritto per lo stack usa e getta in lab/ e per nient'altro:

  • I target non locali vengono rifiutati. L'hostname del target viene risolto e ogni indirizzo che restituisce deve essere loopback o privato RFC1918. Un nome DNS pubblico viene rifiutato anche se attualmente risolve a un indirizzo privato — è un modo ben noto per puntare uno strumento "da laboratorio" alla produzione.
  • --lab-confirm è obbligatorio. Entrambi i controlli vengono eseguiti in assert_lab_target() prima della prima richiesta HTTP, quindi un'invocazione rifiutata non tocca affatto il target.
  • Può leggere solo la casella di posta del laboratorio. La fase 1 raccoglie il pps_nonce riutilizzabile dall'email di conferma dell'iscrizione tramite l'API Mailpit del laboratorio (http://localhost:8025/api/v1/…). Non esiste un percorso di codice per recuperare quell'email da qualsiasi altro luogo, quindi la catena non ha un primo passo contro un host al di fuori del laboratorio.
  • Il laboratorio che prende di mira è irraggiungibile dall'esterno. Ogni servizio in lab/docker-compose.yml si lega a 127.0.0.1.

Così com'è distribuito, quindi, non può essere puntato a un sito reale — si ferma a REFUSING TO RUN prima di emettere una richiesta:

root@kitploit:~
$ python3 exploit_full_chain.py https://example.com --lab-confirm
REFUSING TO RUN: example.com resolves to non-local address(es) 104.20.23.154, ...
This script creates a WordPress administrator and is for the local lab only.
To test a real site, use the non-destructive checker in ../poc/.

Queste protezioni sono portanti anziché decorative: lo script è la catena reale, e ciò che lo mantiene una dimostrazione è che non verrà eseguito al di fuori di uno stack locale usa e getta. Si prega di non rimuoverle, e vedi SECURITY.md — modifiche che le indeboliscono, o un exploit autonomo pensato per essere eseguito al di fuori del laboratorio, sono fuori ambito per questo repository. Per scoprire se un sito reale è affetto, usa poc/ — il checker risponde alla stessa domanda senza toccare nulla.

Per una risposta autorevole su un host che controlli:

root@kitploit:~
grep -n "array_merge(\$permissions, \$permissionsBase)" \
     wp-content/plugins/popup-by-supsystic/classes/frame.php

Qualsiasi output significa che l'host è vulnerabile — quella riga è precisamente ciò che la 1.13.0 ha sostituito.

Usare solo contro sistemi di tua proprietà o per cui sei esplicitamente autorizzato a testare. Vedi SECURITY.md.


Riprodurlo — il laboratorio dimostrativo

lab/ contiene uno stack Docker usa e getta che esegue la vulnerabilità end-to-end, così l'analisi può essere verificata anziché presa per fede:

root@kitploit:~
cd lab
./setup.sh                                                    # WordPress + plugin 1.12.0
../.venv/bin/python exploit_full_chain.py http://localhost:8080 --lab-confirm
./verify.sh                                                   # confirm from the database
./teardown.sh

Il suo output più utile è il confronto delle versioni — richieste identiche contro tre release:

root@kitploit:~
./setup.sh --plugin-version 1.11.2    # exploit succeeds
./setup.sh --plugin-version 1.12.0    # exploit succeeds
./setup.sh --plugin-version 1.13.0    # exploit fails at phase 2

Il laboratorio è intenzionalmente vulnerabile e il suo script di exploit crea un amministratore WordPress. Tutto si lega a 127.0.0.1, e lo script non verrà eseguito contro altro che un laboratorio locale — vedi l'exploit del laboratorio viene eseguito solo nel laboratorio. Non è uno scanner; per controllare un sito reale, usa poc/.


Remediation

  1. Aggiorna alla 1.13.0 o successiva.
  2. Se non puoi aggiornare, disabilita il plugin. Le mitigazioni parziali sono deboli — l' azione vulnerabile è raggiungibile da qualsiasi richiesta anonima.
  3. Se hai eseguito una versione affetta con i popup di iscrizione abilitati, verifica la presenza di compromissione: account amministratore inattesi, popup con sub_wp_create_user_role impostato a un ruolo privilegiato, e richieste POST a admin-ajax.php che trasportano pl=pps&mod=popup&action=save.

Query e grep sui log: §10.


Struttura del repository

root@kitploit:~
.
├── README.md
├── SECURITY.md                  Scope, authorized-use policy, disclosure
├── LICENSE                      MIT
├── requirements.txt
├── docs/
│   └── ANALYSIS.md              Full root-cause analysis and fix rationale
├── patches/
│   ├── 01-frame-permission-merge.diff              array_merge() → _mergePermissions()
│   ├── 02-subscribe-role-allowlist-and-nonce.diff  Role allowlist + dedicated nonce
│   └── 03-v1.12.0-confirmation-page-hardening.diff Unrelated hardening added in 1.12.0
├── poc/
│   └── cve_2026_18322_check.py  Passive version fingerprint (GET only)
├── lab/                         Disposable Docker lab — INTENTIONALLY VULNERABLE
│   ├── docker-compose.yml       MariaDB + WordPress 1.12.0 + Mailpit (loopback only)
│   ├── setup.sh / teardown.sh   Bring the lab up / destroy it
│   ├── exploit_full_chain.py    Full attack chain — CREATES AN ADMIN; lab-gated
│   └── verify.sh                Independent confirmation from the database
├── scripts/
│   └── fetch_versions.sh        Export plugin versions from SVN and regenerate diffs
└── tests/
    └── test_check.py            Offline unit tests for the passive checker

Sviluppo

root@kitploit:~
pip install -r requirements.txt pytest
python3 -m pytest tests/ -v

La suite è completamente offline — usa fixture registrate, mai target live. Copre il triage delle versioni attraverso il confine della 1.13.0, la normalizzazione dei target, e le regole di evidenza che decidono ogni stato.

Le proprietà di sicurezza sono verificate, non solo documentate: che una scansione completa non emetta richieste che modificano lo stato, e che HttpClient non esponga alcun verbo HTTP diverso da GET.

Due regressioni trovate durante lo sviluppo sono bloccate: un readme.txt con CRLF che vanifica il parsing ancorato alle righe, e una pagina di errore HTTP conteggiata erroneamente come evidenza del plugin.

Per riprodurre l'analisi dalle fonti upstream:

root@kitploit:~
./scripts/fetch_versions.sh          # exports 1.11.2 / 1.12.0 / 1.13.0 and regenerates patches/

Licenza

MIT — vedi LICENSE. Il plugin analizzato è GPLv2-or-later e non è ridistribuito qui; scripts/fetch_versions.sh lo recupera dal repository SVN ufficiale di WordPress.

Scarica lo strumento
StatoSignificato
VULNERABLEPlugin rilevato a < 1.13.0
NOT_VULNERABLEPlugin rilevato a >= 1.13.0
PLUGIN_DETECTED_VERSION_UNKNOWNPlugin presente, versione non determinabile — verificare manualmente
PLUGIN_NOT_DETECTEDNessuna evidenza del plugin (non prova dell'assenza)
ERRORTarget irraggiungibile o malformato