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

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
AfterLife — Laboratorio di rilevamento della persistenza della revoca: quando la reimpostazione della password riesce ma l'attaccante non se ne va mai. Riproduce il bug di revoca condizionale Strapi CVE-2026-22706, la sua correzione, un pacchetto di rilevamento a tre regole e la regola ingenua che non lo rileva. | Kitploit
Strumenti/GitHubGitHub/het-p301204/afterlife
Strumenti DifensiviAnalisi delle VulnerabilitàSicurezza WebAutenticazioneApprendimento e FormazioneRed TeamingRisposta agli IncidentiLab e Pratica
GitHubhet-p301204/afterlife

AfterLife

Vedi Repository
1920 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 →

Informazioni

Laboratorio di rilevamento della persistenza della revoca: quando la reimpostazione della password riesce ma l'attaccante non se ne va mai. Riproduce il bug di revoca condizionale Strapi CVE-2026-22706, la sua correzione, un pacchetto di rilevamento a tre regole e la regola ingenua che non lo rileva.

Condividi

AFTERLIFE

Laboratorio di Rilevamento della Persistenza della Revoca

Quando la reimpostazione della password riesce ma l'attaccante non se ne va mai.

Un laboratorio locale red/blue per una singola classe di vulnerabilità: la credenziale che sopravvive all'evento che avrebbe dovuto eliminarla. Include l'exploit, la causa principale, la correzione, un pacchetto di rilevamento a tre regole, un audit di stato per ciò che le regole strutturalmente non possono vedere, una console forense — e la regola di rilevamento che non funziona, mantenuta nel repository per essere dimostrata fallire.

CI tests python rules OWASP CWE license

Avvio rapido · La scoperta · Perché il rilevamento ingenuo fallisce · Il pacchetto di regole · Console · La correzione · Matrice · Test · Documentazione


Lo stesso attacco contro entrambe le implementazioni. Una barra per credenziale, dall'emissione alla morte, raggruppate in lignaggi. La linea tratteggiata è il cambio di password. In modalità vulnerabile cinque barre la attraversano e continuano; in modalità corretta ogni barra nel lignaggio rubato si ferma lì.

Lo stesso attacco. Le stesse richieste. Una sola differenza. Generato da scripts/figures.py dallo stesso payload che la console disegna — rigenerato e confrontato in CI, così una figura non può divergere dal codice.


L'azione di contenimento che non contiene```text

09:00 alice logs in ┐ refresh credential rt-001 │ the attacker steals rt-001 ┘

10:00 alice changes her password ← the one thing a victim can do alone HTTP 200 · password changed · fresh session issued

10:00:03 attacker: POST /refresh rt-002 → HTTP 200 new access credential at-004, issued 10:00:03

10:01:00 attacker: GET /me at-004 → HTTP 200 {"username": "alice", "authenticated": true}

Nessun errore. Nessuna anomalia. Nessuna autenticazione fallita da contare. La credenziale di accesso dell'attaccante ha *tre secondi di vita* ed è stata generata dal server, su richiesta, dopo il reset.

Ecco l'intera vulnerabilità:```python
def _revoke_for_security_change(self, user, kind, device_id):
    if device_id:
        revoke_credentials(user, device_id=device_id)   # ← the finding

Leggilo come farebbe un revisore. La logica di revoca è proprio lì. Chiama la funzione giusta con lo scope giusto. L'endpoint attorno ad essa aggiorna l'hash della password, restituisce 200 ed emette una nuova sessione — ogni comportamento osservabile di un corretto cambio password è presente.

E se il chiamante omette device_id, nulla viene revocato, e l'endpoint riporta comunque successo.

Questo non è ipotetico. È CVE-2026-22706 in Strapi ≤ 5.33.2, dove il passo di invalidazione del refresh-token era condizionato a un deviceId fornito dal chiamante. Punteggio 2.1, Low. Discusso di seguito.


Perché questo è importante

Il punteggio è basso perché l'attaccante aveva già accesso — questa è la condizione di ingresso, e questo bug non concede nulla di nuovo. Ciò che concede è la durata, e lo fa rompendo l'unico controllo che la vittima può azionare da sola.

  • Ogni runbook di account-takeover inizia con reimposta la password. Ogni prodotto dice all'utente la stessa cosa.
  • Quando fallisce silenziosamente, alla vittima viene detto che il problema è risolto e smette di cercare — il che disattiva il segnale di rilevamento che conta di più nel account takeover: l'utente che se ne accorge.
  • La finestra di persistenza è la durata della credenziale di refresh: 30 giorni per impostazione predefinita, rinnovabile indefinitamente tramite rotazione. test_persistence_lasts_as_long_as_the_refresh_credential percorre sette giorni di tempo simulato per dimostrarlo.
  • Non c'è una seconda azione che l'utente possa intraprendere. Un secondo cambio password fa esattamente quanto il primo.

Un bug con punteggio Low in un percorso di contenimento costa più di un bug con punteggio Low in un percorso di funzionalità, perché il costo viene pagato durante un incidente, quando nessuno sta leggendo gli advisory.


Il rilevatore ingenuo

La regola che scrivi per prima:```text IF credential.issued_at < credential_change.timestamp: ALERT

Non è una regola stupida. È economica, richiede un solo campo, si legge come la definizione
del problema, ed è **corretta nel caso semplice** — un attaccante che usa un
token di *accesso* rubato dopo il reset viene individuato.
`test_the_naive_rule_catches_the_simple_case` verifica che funzioni.

Entrambe le regole pongono la stessa domanda sulla stessa credenziale. Leggono campi
diversi per rispondere, e i due campi sono in disaccordo:

![Due righe, una per campo. credential.issued_at legge 10:00:03, tre secondi dopo la modifica, e conclude che la credenziale sembra pulita. lineage.root_issued_at legge 09:00:00, un'ora prima della modifica, e genera un avviso.](https://raw.githubusercontent.com/het-p301204/afterlife/main/docs/figures/two-fields.svg)

**Tre secondi dopo, o un'ora prima — la stessa credenziale, nello stesso
istante.** La regola ingenua interroga un campo controllato dall'attaccante, e un
singolo `POST /refresh` lo azzera.

Eseguila sul log delle richieste, che è dove questa query viene effettivamente scritta,
perché i log delle richieste sono ciò che hai a disposizione:```text
NAIVE DETECTOR (NAIVE-001), over the request log

  Result: NO ALERT

  Six requests were served to the attacker after the reset. Every one of them
  carried at-004, minted at 10:00:03 -- three seconds *after* the password
  change. By its own timestamp it is the newest credential on the account.

Sarebbe facile fermarsi qui, e disonesto, quindi il laboratorio esegue anche la versione più equa della regola ingenua — ampliata per osservare anche l'endpoint di refresh:```text NAIVE DETECTOR, widened to include POST /refresh

1 alert at 2026-09-11T10:00:03.000Z: the credential presented to /refresh was rt-002, issued 2026-09-11T09:30:00.000Z. Then it goes blind. 6 events follow that hop and it flags none of them, because every credential from there on carries a post-reset timestamp. Its incident covers 1 accepted request; the lineage rule's covers all of them.

Scarica lo strumento