
Laboratorio Docker PoC: concatenamento di bypass dell'upload di file e XSS memorizzato per creare account amministratore. Risorsa educativa per penetration tester.
Un'applicazione web deliberatamente vulnerabile che dimostra come un bypass del caricamento file si combini con XSS memorizzato per creare account amministrativi backdoor, anche quando le protezioni CSP, CORS e CSRF sono attive.
Post completo sul blog: KurtiseBear Blog
Questo è un laboratorio educativo per la formazione sulla sicurezza difensiva. Non distribuire questo in alcun luogo accessibile pubblicamente.
L'applicazione ha controlli di sicurezza reali:
'self' (ma con 'unsafe-inline' e 'unsafe-eval')Un attaccante con un account utente a bassi privilegi combina due vulnerabilità per bypassarli tutti:
Bypass del caricamento file -- Il modulo di caricamento limita a .pdf tramite un attributo accept lato client, ma il server non effettua alcuna validazione del tipo di file. Un attaccante carica un file .js contenente JavaScript. L'endpoint di download lo serve dalla stessa origine, quindi CSP e CORS non lo bloccano.
XSS memorizzato tramite oggetto del messaggio -- La funzione di messaggistica memorizza l'input utente senza sanitizzazione. La posta in arrivo dell'amministratore visualizza l'oggetto del messaggio come HTML grezzo. Il payload XSS utilizza un gestore `` per recuperare lo script caricato ed eseguirlo con eval(). CSP lo consente perché 'unsafe-inline' e 'unsafe-eval' sono permessi.
Mancanza di CSRF sull'endpoint API -- L'API di gestione utenti (/api/manage-user.php) non valida i token CSRF, anche se gli endpoint dei moduli lo fanno. Il payload XSS chiama questa API utilizzando la sessione same-origin dell'amministratore. Anche se CSRF fosse presente, JavaScript same-origin potrebbe leggere il token dal DOM.
Il risultato: quando un amministratore apre la propria posta in arrivo, l'XSS si attiva, il JavaScript crea un account amministrativo backdoor utilizzando la sessione dell'amministratore. Ogni difesa è in atto e funzionante. La catena funziona perché non lascia mai l'origine.
docker-compose up -d
Attendi 10-15 secondi per l'inizializzazione di MySQL, poi visita http://localhost:8080
| Ruolo | Password | |
|---|---|---|
| Admin | [email protected] | admin |
| Utente | [email protected] | user |
Vai su http://localhost:8080 e accedi con [email protected] / user.
Vai su Carica File. Il modulo dice "Solo PDF" ma lo impone solo lato client. O:
accept=".pdf" dall'input del file, oppureCarica il file payload.js fornito (o il tuo). Annota l'ID del file restituito (es. 1).
Il file caricato è ora servito da /api/download.php?file_id=1 sulla stessa origine. CSP non bloccherà le richieste a questo endpoint perché è 'self'.
Vai su Invia Messaggio. Nel campo oggetto, inserisci:
r.blob()).then(b=>b.text()).then(eval)">
(Sostituisci 1 con l'ID del file effettivo del passo 2.)
Inserisci qualsiasi cosa nel corpo. Spunta priorità se lo vuoi in cima alla posta in arrivo. Invia.
Il gestore onerror funziona perché CSP permette 'unsafe-inline'. eval() funziona perché CSP permette 'unsafe-eval'. La fetch all'endpoint di download funziona perché è same-origin.
Effettua il logout. Accedi come [email protected] / admin. Vai su Posta in arrivo.
L'oggetto del messaggio viene visualizzato come HTML grezzo. Il tag `` non riesce a caricare, il gestore onerror si attiva, recupera il payload caricato e lo esegue con eval(). Il payload esegue una POST a /api/manage-user.php utilizzando il cookie di sessione dell'amministratore (allegato automaticamente per le richieste same-origin). Nessun token CSRF necessario perché l'endpoint API non lo controlla.
Vai su Utenti. Dovresti vedere un nuovo utente: BackdoorAdmin con ruolo admin ed email [email protected].
Effettua il logout e accedi con [email protected] / Compromised1! per confermare.
CSP blocca script esterni --> Ma il payload è ospitato sulla stessa origine tramite caricamento file --> E unsafe-inline/unsafe-eval permettono il gestore onerror ed eval()
CORS blocca richieste cross-origin --> Ma ogni richiesta nella catena è same-origin
I token CSRF proteggono gli invii dei moduli --> Ma l'endpoint API non li valida --> E anche se lo facesse, JS same-origin può leggere i token dal DOM
I cookie di sessione hanno protezioni standard --> Ma le richieste same-origin li trasportano automaticamente
Le difese funzionano tutte correttamente. Sono progettate per fermare attacchi cross-origin. Questa catena non lascia mai l'origine.
Cosa romperebbe effettivamente questa catena:
htmlspecialchars() su tutti gli output controllati dall'utente. La posta in arrivo visualizza $row['subject'] grezzo. Questo elimina completamente l'XSS.'unsafe-inline' e 'unsafe-eval'. Usa nonce o hash per script inline legittimi. Questo blocca il gestore onerror e eval().docker-compose down -v
Questa applicazione è deliberatamente vulnerabile. È progettata esclusivamente per scopi educativi e di formazione sulla sicurezza difensiva. Non distribuirla su alcuna rete accessibile a utenti non fidati. Non utilizzare queste tecniche contro sistemi senza esplicita autorizzazione scritta.