Vai al contenuto principale
Informazioni sulle minacce

Cacciare o essere cacciati: ogni servizio era unico, ed era proprio questo il problema

L'impilamento non funziona più quando i GUID specifici per utente e i percorsi dei profili rendono ogni riga unica nel suo genere. Ecco in che modo HuntIQ ha riscritto le stringhe per consentire l’individuazione dei valori anomali e quali sono i limiti di tale approccio.

La pila che è tornata vuota

L’impilamento è solitamente la prima cosa a cui ricorriamo durante una caccia alla persistenza. Individuare tutti i servizi, le operazioni ad avvio automatico o le attività pianificate presenti nell’intero ambiente, contare il numero di endpoint associati a ciascuno di essi e ordinarli in ordine crescente. Le voci in fondo alla lista, quelle che compaiono su uno o due computer, sono il punto da cui iniziare a indagare.

Nell’ambiente di Tanium un cliente, ciò non ha funzionato affatto. Ciascuna restituiva endpoint un numero di righe compreso tra cento e cinquecento, e quasi tutte erano uniche per quella endpoint. Quando abbiamo raggruppato i risultati, quasi tutti presentavano un valore pari a uno. Non c'era alcuna coda da analizzare, poiché l'intero insieme dei risultati costituiva la coda.

I dati erano corretti. Il problema erano le corde. Windows aggiunge un suffisso univoco al nome di ogni servizio specifico per utente, pertanto lo stesso servizio su due macchine viene visualizzato con due nomi diversi. I programmi a esecuzione automatica e le attività pianificate presenti all’interno di un profilo utente riportano il nome utente nel proprio percorso. Inoltre, alcuni nomi di attività e voci di avvio automatico recano i propri ID univoci. Ciascuno di essi fa apparire raro ciò che è comune, e uno stack non ha modo di distinguere la differenza.

Una volta riscritte quelle stringhe, in modo che lo stesso contenuto apparisse identico su ogni macchina, il set di risultati si è ridotto a circa l’uno per cento della sua dimensione originale. Non abbiamo tralasciato nemmeno una riga per arrivare a questo risultato.

Perché non ci siamo limitati a filtrarlo

Il filtraggio è la mossa più ovvia, ed è da lì che la maggior parte delle persone inizia: escludere i percorsi rumorosi, escludere i servizi di cui si ha già fiducia, raggruppare ciò che rimane.

Il problema è che il filtraggio elimina alcune righe, mentre ciò di cui avevamo bisogno era unirle. Se si escludono tutte le operazioni di avvio automatico associate a un profilo utente, si ottiene un elenco più breve, ma si perde anche la possibilità di constatare che quattrocento computer condividono una stessa operazione di avvio automatico e che un singolo computer presenta un elemento che nessun altro possiede. È proprio quel confronto il motivo per cui si ricorre allo stack, in primo luogo.

Anche nella pratica è una situazione davvero penosa. A parte una manciata di esclusioni, gestirle nella console diventa ben presto complicato, e ogni esclusione rappresenta un ulteriore elemento che qualcuno deve tenere aggiornato.

Avevamo altre due opzioni, ma nessuna delle due si è rivelata utile. Esiste un altro sensore di servizi che si integra perfettamente, ma non fornisce lo stesso livello di dettaglio, ed era proprio il dettaglio il motivo per cui stavamo conducendo questa ricerca. Anche l'invio dei dati grezzi al e SIEM l'esecuzione del lavoro in quella sede era fuori discussione. Il volume lo escludeva, quindi non l’abbiamo mai provato.

Riscriva la stringa, mantenendo la riga

La soluzione consiste nel normalizzare le stringhe prima endpoint che vengano restituite, in modo che la stessa operazione produca la stessa stringa ovunque. Si tratta, in sostanza, di quattro regole:

  1. Individui la parte della stringa che varia a seconda dell’utente o del computer, ma che non fornisce alcuna indicazione su cosa sia effettivamente l’oggetto in questione. Di solito si tratta di un percorso di profilo, di un GUID, o di un suffisso aggiunto al momento dell'installazione.
  2. Lo sostituisca con un segnaposto fisso. Un percorso di esecuzione automatica in C:\Users\jsmith\ diventa C:\Users\USER\. Durante l’impilamento, non ci importava in quale profilo fosse contenuto. Ci interessava sapere cosa contenesse.
  3. Elimini il suffisso o l'ID univoco dal nome.
  4. Lasci tutto il resto esattamente com’era e non salti mai una riga.

L'ultima regola è quella più importante. Il numero di righe in uscita deve corrispondere al numero di righe in entrata. Se la normalizzazione si limita esclusivamente a riscrivere il testo, nulla può andare perso nei risultati. Il peggio che possa accadere è che una riga venga raggruppata con altre che ora le appaiono identiche; e se risulta identica ad altre quattrocento righe, non si trattava comunque del valore anomalo che stavate cercando.

Nulla di tutto ciò dipende dalla nostra piattaforma. Se l'elemento con cui si effettua lo stack consente di riscrivere una stringa prima di conteggiarla, è possibile procedere allo stesso modo.

Come si è svolta la partita sulle tre superfici

  • Autoruns: i percorsi delle directory utente sono stati sostituiti con un segnaposto, inoltre sono stati rimossi gli ID univoci presenti in alcuni nomi delle voci.
  • Attività pianificate: lo stesso trattamento. I percorsi degli utenti rimandano a un segnaposto, mentre gli ID univoci derivano dai nomi delle attività.
  • Servizi: la maggior parte dei nomi dei servizi specifici per utente termina con una stringa univoca che identifica l’istanza specifica per utente. Rimuovendolo, ciò che in realtà è un unico servizio viene ricomposto in un’unica riga.

Tutti e tre sono stati costruiti allo stesso modo. Ciascuno di essi richiama il sensore nativo tramite Taniumla propria libreria di sensori, esegue un ciclo sui risultati e riscrive le stringhe prima di restituirle. È proprio per via di quella progettazione che la parte più complessa è stata quella relativa alle prestazioni, aspetto che verrà nuovamente affrontato più avanti.

Come sappiamo che non ha nascosto nulla

La prova più evidente risiede nel modo in cui è costruito. Le righe vengono riscritte, mai eliminate; pertanto, una voce dannosa può finire per essere raggruppata con altre, ma non può scomparire dall’output.

La fase di collaudo rappresenta la parte più debole. I sensori sono stati utilizzati in diversi ambienti di sviluppo e di test durante la loro realizzazione e riteniamo che i risultati notoriamente errati riscontrati in tali ambienti siano stati impiegati per confermare che i sensori continuassero a individuarli. A distanza di un anno, non ricordiamo i dettagli, non abbiamo tenuto un conteggio dei dati prima e dopo e nessuno al di fuori del gruppo di sviluppo ha esaminato le regole.

Se lo realizzate autonomamente, eseguite la convalida in modo corretto: sottoponete un artefatto di test appositamente inserito all’output normalizzato, verificate che continui a risaltare e annotate il numero di stringhe distinte prima e dopo.

Dove si rompe

La normalizzazione comporta l’eliminazione intenzionale di alcune informazioni, e ciò comporta delle conseguenze di cui è opportuno essere a conoscenza prima di procedere alla sua implementazione.

  • Un malintenzionato potrebbe nascondersi nel suffisso. Se qualcuno assegnasse a un servizio dannoso un nome che sembrasse terminare con il suffisso specifico per utente che noi eliminiamo, una parte del nome verrebbe troncata. Continuerà comunque a comparire, poiché non eliminiamo mai le righe, e un nome di servizio alterato che esiste solo su una macchina risulterà strano a chiunque legga lo stack.
  • L'implementazione su larga scala è la soluzione migliore. Se un malintenzionato invia lo stesso servizio o la stessa attività a tutti i destinatari endpoint, si tratta di una pratica comune e il sistema di controllo non la segnalerà. Lo Stacking è stato progettato per individuare i valori anomali, e un elemento installato su ogni dispositivo non rientra in questa categoria.
  • Performance era il problema principale. L'esecuzione del sensore nativo seguita da un ciclo su ogni risultato comporta endpoint un costo maggiore rispetto all'esecuzione del solo sensore nativo. Su macchine con risorse limitate, tale sovraccarico può determinare se sia possibile eseguirlo o meno.
  • Le regole necessitano di un responsabile. Ogni regola si basa su un presupposto relativo al modo in cui un software assegna i nomi agli elementi e al luogo in cui li installa. I fornitori modificano entrambi e, quando lo fanno, la regola smette silenziosamente di essere applicabile.
  • Salti questo passaggio quando l’identificatore è proprio ciò che sta cercando. Se ciò che Le interessa è proprio l’istanza specifica per ciascun utente, nascondendola eliminerà il segnale che stava cercando.

Copertura del modello ATT&CK

TecnicaPerché tale proprietà è ad alta cardinalità

T1547 Esecuzione automatica all’avvio o all’accesso

Le voci di avvio automatico si trovano nei profili utente, pertanto il percorso varia a seconda dell’utente su ogni endpoint.

T1543,003 Windows Assistenza

Le istanze di servizio per utente presentano un suffisso univoco nel nome del servizio, pertanto un singolo servizio viene conteggiato più volte.

T1053,005 Attività pianificata

I nomi delle attività contengono ID specifici del computer o dell’utente, mentre i percorsi delle attività presentano lo stesso problema di profilo delle operazioni di avvio automatico.

Queste sono le tre superfici di persistenza in cui l’elevata cardinalità incide maggiormente; pertanto, sono quelle che abbiamo realizzato per prime. Questo approccio non si limita a loro.

Verifichi se questo è il Suo problema

Non esiste una sola domanda alla quale si possa rispondere con un sì o un no. Il metodo di verifica più rapido che conosciamo consiste nel calcolo di un rapporto. Applichi una delle sue proprietà native di esecuzione automatica o di servizio all'intero ambiente e confronti il numero di righe ottenute con il suo endpoint conteggio. Se il numero di righe è pari a tre volte quello degli endpoint o superiore, la proprietà garantisce l’unicità aendpoint livello di singolo elemento e il vostro stack è costituito prevalentemente da dati irrilevanti. È più o meno a quel punto che la normalizzazione comincia a ripagarsi.

Perché non rendiamo pubblici i dati dei sensori

I sensori non sono ancora pronti per essere distribuiti. I costi legati alle prestazioni devono essere valutati e considerati con attenzione per ogni singola implementazione. I “Threat Hunters” di HuntIQ operano nell’ambiente dei propri clienti per garantire che i sensori Tanium non incidano sull’attività aziendale del cliente. La logica sopra descritta è quella che si applica anche ad altre piattaforme, consentendo a tutti i nostri clienti di trarne vantaggio indipendentemente dalla piattaforma che utilizzano.

Scoprite in che modo TaniumSecurity Operations e HuntIQ vi aiutano a individuare preventivamente la prossima minaccia. Guardate una demo per vedere come Tanium Atlas mette in pratica questa strategia di individuazione in tutto il vostro parco veicoli.