Un log di sicurezza serve a ricostruire chi ha tentato di fare cosa, su quale risorsa, quando e con quale esito. Non è una copia di tutte le richieste né un dump delle eccezioni. Il suo obiettivo è fornire prove utili per indagare accessi e azioni sospetti, usando il minimo di dati necessario e applicando controlli che impediscano al log stesso di diventare una fonte di esposizione.
Per progettare il logging di sicurezza in PHP, è utile innanzitutto definire gli eventi importanti e il loro utilizzo: rilevamento, indagine, audit operativo o conformità a una policy interna. Si stabilisce poi un formato comune, si decide chi può consultare i log e si verifica l’intero flusso. Un log che esiste ma non permette di ordinare gli eventi, identificare l’esito o distinguere i tentativi dalle azioni completate non soddisfa le esigenze investigative.
Distinguere i log tecnici, le attività e gli eventi di sicurezza

I log tecnici descrivono il funzionamento dell’applicazione: errori, eccezioni, latenza, problemi di connessione o di configurazione. Aiutano a diagnosticare la disponibilità e il comportamento. Il log delle attività documenta azioni aziendali attribuibili agli utenti, come modificare una fattura o cambiare i dati di un account. Gli eventi di sicurezza, invece, si concentrano sui fatti rilevanti per proteggere identità, autorizzazioni, risorse e limiti di accesso.
Esistono intersezioni, ma le categorie non sono intercambiabili. Una modifica di ruolo può essere un’attività aziendale e un evento di sicurezza; un’eccezione del database è solitamente tecnica, anche se una serie di errori durante un’operazione sensibile può giustificare un alert di sicurezza. Definire gli scopi evita di duplicare informazioni senza criterio e consente di assegnare periodi di conservazione, accessi e formati adeguati.
Non utilizzi il log di sicurezza come archivio di audit illimitato né come sostituto di metriche e tracce. Non dia per scontato che registrare un evento equivalga a rilevarlo: per generare alert servono regole, soglie e responsabili della risposta. Documenti quale sistema produce ciascun dato e quale team lo utilizza.
Scegliere azioni e contesto che permettano di indagare
Cominci con un inventario delle azioni e delle minacce rilevanti per l’applicazione. Tra gli eventi da valutare rientrano spesso i tentativi di accesso non riusciti, i blocchi degli account, le modifiche delle credenziali, la concessione o la revoca di autorizzazioni, le modifiche della configurazione, le esportazioni di dati sensibili e le operazioni amministrative. L’elenco deve rispecchiare il prodotto: registrare ogni visualizzazione di pagina può generare rumore, mentre omettere una modifica dei privilegi impedisce di ricostruire un accesso non autorizzato.
Per ogni evento, definisca a quale domanda deve poter rispondere. Se, per esempio, si indaga una modifica di autorizzazione, è importante identificare l’attore, l’utente o la risorsa interessati, l’autorizzazione precedente e quella nuova, l’esito e il momento. In caso di autenticazione non riuscita, può essere rilevante l’identificativo dell’account normalizzato o pseudonimizzato secondo la policy, insieme all’esito e all’origine della richiesta, se la raccolta è giustificata. Eviti di dedurre un’identità da un indirizzo IP condiviso.
Distingua tentativo, decisione ed esito. Una richiesta negata non equivale a una modifica completata; una richiesta accettata può non riuscire prima che i dati siano persistiti. Registri l’esito effettivo e, quando serve per indagare, la fase raggiunta. Definisca anche il significato di ciascun valore, come denied, failed o succeeded, in modo che componenti diversi non li utilizzino in modo contraddittorio.
Usare uno schema coerente e correlabile
Un formato strutturato, di norma JSON, facilita il filtraggio e la correlazione degli eventi negli strumenti operativi. Come punto di partenza, valuti questi campi:
- Identificativo dell’evento: nome stabile e versionato, per esempio
authorization.permission_changed. - Timestamp: data e ora in UTC, con precisione adeguata e orologi dei sistemi sincronizzati.
- Attore: identificativo interno o pseudonimo; rappresenti esplicitamente processi e attività automatizzate.
- Azione e risorsa: operazione eseguita e tipo e identificativo della risorsa interessata, evitando di includerne il contenuto.
- Esito: successo, rifiuto o errore, con una motivazione categorizzata e non sensibile.
- Correlazione: identificativo della richiesta o dell’operazione per mettere in relazione gli eventi senza riversare nei log l’intera richiesta.
- Origine contestuale: servizio o componente che ha emesso l’evento e, se giustificato, dati limitati sull’origine di rete.
I nomi e i tipi dei campi devono rimanere stabili. Un identificativo di correlazione della richiesta deve essere generato o convalidato dall’infrastruttura; accettare senza controlli un identificativo arbitrario può causare collisioni o confusione. Non includa indiscriminatamente header completi, corpi HTTP o parametri. Il contesto deve aiutare a ricostruire la sequenza, non replicare tutti i dati elaborati.
Escludere i segreti e ridurre al minimo i dati personali
Non registri mai password, token di accesso, chiavi API, segreti di sessione, codici di recupero né valori che consentano di autenticarsi. Eviti anche di registrare dati personali completi quando è sufficiente un identificativo interno. Per campi come email, telefono o indirizzo, decida se è indispensabile conservarli, se possono essere mascherati o se è preferibile utilizzare un riferimento pseudonimizzato. La decisione dipende dallo scopo, dal rischio e dagli obblighi applicabili.
La rimozione o l’oscuramento dei dati sensibili deve avvenire prima che l’evento esca dal processo: non faccia affidamento unicamente su un filtro successivo applicato dall’aggregatore. In PHP, eviti di serializzare direttamente oggetti di richiesta, header o eccezioni che potrebbero contenere valori sensibili. Crei un oggetto o un array esplicito con un elenco di campi consentiti; una strategia basata su un elenco di blocco è fragile quando compaiono nuovi campi. Convalidi e limiti anche la lunghezza dei valori controllabili dall’utente per ridurre l’iniezione di righe, il rumore e il consumo eccessivo di risorse.
Verifichi i casi in cui i dati segreti compaiono nei parametri o nei messaggi di errore e controlli che non raggiungano la destinazione dei log. La sanitizzazione deve conservare informazioni sufficienti per indagare, per esempio una categoria di errore, senza mantenere il messaggio completo se potrebbe includere credenziali.
Proteggere accesso, integrità e ciclo di vita
Anche i log contengono informazioni sensibili. Limiti chi può scrivere, leggere, esportare e gestire la conservazione; queste funzioni possono richiedere autorizzazioni diverse. Protegga il trasporto e l’archiviazione con i controlli appropriati per l’infrastruttura ed eviti che un account dell’applicazione compromesso possa cancellare o alterare senza lasciare traccia l’intera cronologia. Quando il rischio lo giustifica, utilizzi un’archiviazione in sola aggiunta o controlli di integrità verificabili e ne documenti i limiti.
Definisca un periodo di conservazione esplicito per ogni classe di evento. Conservare i dati a tempo indeterminato aumenta l’esposizione e i costi; eliminarli troppo presto può compromettere un’indagine. La policy deve tenere conto di copie, esportazioni, ambienti di test e richieste di cancellazione che riguardano dati personali. Registri e verifichi gli accessi degli operatori ai log stessi, in particolare le esportazioni o le modifiche alle policy.
Il logging può non riuscire a causa dell’indisponibilità della destinazione, dei limiti di archiviazione o di errori di serializzazione. Decida cosa accade in ciascun caso in base alla criticità. Non trasformi un’interruzione del sistema di logging in un modo per completare silenziosamente un’operazione ad alto rischio, ma non lasci nemmeno che un’eccezione di logging provochi risultati incoerenti o duplichi una transazione. Per le operazioni critiche può essere necessario garantire la scrittura dell’evento insieme alla modifica mediante una strategia transazionale, come il pattern outbox. Se si usa una coda, definisca i tentativi, la deduplicazione e la gestione degli eventi in sospeso.
Verificare che l’evento esista e sia sicuro
I test devono verificare più di una semplice chiamata a una funzione di logging. Esegua scenari rappresentativi: accesso negato, privilegio concesso, privilegio revocato e modifica sensibile completata o non riuscita. Verifichi che l’evento includa attore, risorsa, esito, timestamp e correlazione; che l’esito corrisponda a quanto è realmente accaduto; e che non compaiano password, token o dati non necessari.
Includa test per i malfunzionamenti della destinazione dei log e osservi se l’operazione principale rimane in uno stato coerente, se viene generato un segnale alternativo e se l’errore è visibile al team operativo. Per un’azione sensibile, verifichi che non venga indicato un esito positivo se la modifica non è stata persistita. Provi anche i limiti e gli input manipolati, come i ritorni a capo nei valori controllabili, e la lettura in base ai ruoli: un utente aziendale non dovrebbe avere accesso predefinito al repository degli eventi.
Checklist per verificare un’implementazione

- Ogni evento ha uno scopo, un responsabile e una policy di conservazione definiti?
- Si distinguono i tentativi, i rifiuti, gli errori e le operazioni completate?
- Lo schema permette di identificare attore, azione, risorsa, esito e timestamp?
- È possibile correlare l’evento alla richiesta senza registrarne l’intero contenuto?
- I segreti sono esclusi e i dati personali ridotti al minimo prima dell’invio?
- Accesso, trasporto, archiviazione ed eliminazione sono controllati?
- Sono stati verificati l’indisponibilità della destinazione, l’integrità dell’operazione e i permessi di lettura?
Dia priorità agli eventi che proteggono gli account, i privilegi e le operazioni con il maggiore impatto. Poi standardizzi lo schema, limiti i dati e automatizzi test che falliscano se un segreto entra nei log. In questo modo, il logging di sicurezza in PHP fornisce prove utili senza trasformarsi in un secondo database di informazioni sensibili.



