venerdì 28 febbraio 2020

Sfide...


Correva il 2004..

Mi chiama un mio conoscente e mi chiede:"Senti, ma te le fai ancora quelle robe lì che cracchi le reti per vedere se sono sicure?" - "Per farlo lo farei anche, ma non gratis" - "Ah, bene..senti: c'è un mio amico che ha il suo capo convinto che gli stiano spiando i server..." - "Ok, ho capito. Lasciami il numero che li richiamo io domani..."
Fu il mio ultimo penetration test da libero professionista.
Da quel 2004 ad oggi non è che non mi sia più capitato di fare ancora attività "hands on", per lavoro o svago, ma si è sempre trattato di qualche rapida analisi "spot" di una applicazione, magari di un po' di sandboxing su qualche malware sample prelevato dal pc di un collega, ma nulla di più.
Son rimasto praticamente 15 anni senza mai provare seriamente a "rootare" un server.
Qualche mese fa, dopo una conferenza a cui ho partecipato ed in cui era presente uno dei più abili redteamers italiani, mi si è ficcato in testa un pensiero: ma io sarei stato ancora in grado?
E' stata la volontà di rispondere a questa domanda a spingermi ad entrare su Hack the Box.
Sono sincero: il challenge d'ingresso iniziale l'ho superato andandomi a cercare la soluzione su Google. E non penso affatto di "aver barato". Non esiste un solo motivo per cui un pentester non dovrebbe andare a cercare ogni possibile soluzione al suo problema, eventualmente anche su youtube. L'abilità di un penetration tester non sta solo nella sua conoscenza di eventuali tecniche "esoteriche". La vera abilità sta nel "pensare fuori dagli schemi" al fine di ottenere il risultato ricercato. Alla fine, anche sapere usare bene Google è una abilità.
Fatto sta che sono entrato e, per la prima volta dopo 15 anni, ho lanciato nmap contro un server ignoto con l'obiettivo di rootarlo.
La faccio breve: il server era facile, le vulnerabilità erano evidenti ed in capo a 3 giorni avevo catturato il flag user. Altri 3 giorni ed avrei rootato la macchina.
Considerato che lavoro, ho una famiglia e quant'altro, mi son potuto dedicare alla cosa solamente la sera dopo cena ed un po' nel pomeriggio di una domenica, credo di essermela cavata bene...
La prima sensazione che ho avuto, dopo tutto questo tempo, è che siano fondamentalmente solo cambiati i tool, per cui tante cose che prima ti dovevi scriptare da solo sono ora già belle e pronte in kali o su github, ma per il resto il processo è esattamente lo stesso di 15 anni fa:
  • initial enumeration - fingerprinting (la prima analisi)
  • exploit (remote command execution - blind shell)
  • low priv shell (foothold)
  • privilege escalation
  • rooting/exfiltration
Ciò che è cambiato davvero tanto è la sicurezza dei sistemi Windows.
Son sincero: fino a 15 anni fa un server Windows da testare era quasi una garanzia di penetrazione.
Oggi i Windows è decisamente molto più robusto "out of the box" rispetto ad una qualsiasi distro linux.
Ma c'è anche un'altra cosa, che è cambiata: la mia "brainspeed". Se fino ad una quindicina di anni fa il mio cervello "macinava" a ritmi vertiginosi e necessitava di ben poco riposo, oggi il confronto con certi "ragazzini terribili" è impietoso.
Io impiego un paio d'ore ad individuare un vettore di attacco promettente, poi magari ancora una per testare un exploit e guadagnare l'accesso...poi ancora due o tre ore per trovare una vulnerabilità che mi apra la "privesc", altre due orette per capire l'exploit e provare a "rootare"...e nel mezzo metteteci pranzi, cene, sonno notturno, pennichelle, lavoro, bambini, moglie...poi vado sulla pagina descrittiva per postare l'hash che certifica il mio successo nella compromissione del sistema e scopro che il "guru" di turno ha guadagnato il "blood" (il primo "hack vincente") in 15 minuti dal rilascio della macchina.
Poi magari vado sui forum di HTB e leggo di gente che la stessa macchina la ripete più e più volte nella stessa giornata per trovare e provare sempre nuovi vettori di attacco...
Detto ciò, posso dire anche che per me la cosa era ampiamente prevedibile, e non mi turba minimamente. Solo un fulminato (o un genio) può pensare a 46 anni di mettersi in competizione con persone di 20 o 30 anni più giovani di lui e sperare di "vincere".
Sono invece rimasto sorpreso del contrario. Alla fine della fiera, le mie "performances" non sono affatto disprezzabili.
Nella classifica di HTB riesco a mantenermi nella top 100 a livello nazionale e comunque "galleggio" tra i primi 1000 a livello mondiale.
Ma non è questo che mi gratifica di più.
Quello che mi gratifica di più è scoprire che ho sempre la stessa passione ed interesse per il "giocattolo", che ancora riesco ad imparare, imparare, imparare.
Che questo mondo, che oggi viene chiamato "cybersecurity", ma che ai miei tempi si chiamava semplicemente "hacking", c'è ancora tanto spazio anche per un nerd un po' "arruginito" come me.
E che, in ogni caso, se quasi ogni giorno nel mio inbox trovo dei messaggi da ragazzini indiani o neozelandesi che mi chiedono consigli su come fare per approcciare una macchina, tutto sommato la mia competenza ha ancora valore.
E tutto ciò forse mi aiuta a capire un po' meglio come relazionarmi con l'effetto Dunning Kruger, perlomeno con la platea degli utenti di HTB...
...anche se per togliermi i dubbi in merito alla platea generale della comunità infosec mondiale ne corre...
E adesso chiudo che ho l'nmap che corre su "book"

martedì 4 febbraio 2014

Your password has expired...


Ieri leggevo sul blog di un noto giornalista, un suo post in cui esprimeva il suo disagio per l'imposizione da parte dei suoi amministratori di sistema, a suo modo di dire illegittima e liberticida, delle regole per il cambio password. 
La sua posizione, sostanzialmente era la seguente: le informazioni che ci sono in quel sistema riguardano me e pertanto sta a me decidere se e come vale la pena di custodirle. Se non voglio usare una password complessa sono affari miei.
Detta così sembra anche una posizione ragionevole, ma non lo è affatto e vi spiego il perchè.
Partiamo da un parallelo comprensibile a chiunque: casa propria. Lascereste entrare chiunque in casa vostra in vostra assenza? No di certo. Casa vostra è il luogo più "intimo" e personale che avete e custodisce la vostra vita privata e le vostre proprietà più personali, pertanto vi adoperate per impedire l'accesso agli sconosciuti. E come fate? Con delle serrature. Ora, va da sè che per casa propria si cerca di adottare gli accorgimenti di sicurezza migliori che ci si può permettere: dal minimo indispensabile come le serrature doppie, sino al massimo disponibile, come i servizi di vigilanza armata, gli allarmi più sofisticati, le blindature ad ogni accesso. E' altrettanto ovvio, però, che per il capanno degli attrezzi da giardino di solito ci si limita ad un chiavistello, al limite con un lucchettino per quando si va via per le ferie...
Tutto questo sembra perfettamente in linea con l'ipotesi iniziale: ho diritto a scegliere io il livello di sicurezza della mia password in funzione di quanto ritengo preziose le informazioni contenute in quel sistema.
Il problema, però, è che di solito non funziona proprio così. Le password sono più simili alla chiave del condominio che non a quella di casa propria. Se io per essere comodo lascio sempre la porta del condominio aperta, è vero che i miei vicini potranno fare affidamento sulle loro porte di casa, ma in ogni caso sto potenzialmente consentendo a persone non autorizzate di accedere ad aree dove non dovrebbero accedere. E quindi gli consento di studiare le porte dei miei vicini di casa con tutta calma. Si capisce meglio ora il senso della questione? Gli amministratori di sistema non sono responsabili SOLO dei vostri dati, epr i quali potete anche sentirvi liberi di non impostare protezione alcuna. Essi sono responsabili ANCHE dei dati degli altri. E per questo non gradiscono che voi usiate password semplici.
Perchè così facendo facilitate moltissimo ai malintenzionati il compito di accedere al sistema per studiare come è fatto e quindi di violarlo per i propri scopi.
Ma veniamo al secondo punto di attenzione: chi accede ai vostri account, siano essi della posta elettronica o siano quelli per scaricarsi il cedolino paga, accede a qualcosa che gli permette di impersonarvi. Importa poco che io del tal giornalista possa sapere quanto guadagna. Quello che importa è che io dal suo cedolino posso ricavare informazioni che mi consentono di ingannare terzi e convincerli di stare interagendo con lui. E questo è molto pericoloso. Tramite il codice fiscale ed una fotocopia falsificata della carta di identità,. io posso comprare una sim card a nome di altri. Il che verrebbe facilmente scoperto, ma nel giro di almeno qualche giorno se non settimana, nel frattempo io potrei telefonare a nome altrui fino al blocco della SIM. Grave? Forse non molto, ma pensate un po': cosa serve per aprire un finanziamento? Credete davvero che un funzionario di una agenzia di periferia che si vede arrivare una ragazza che si presenta come la segretaria del tal famoso giornalista, con una copia della sua busta paga, i dati del conto corrente di accredito e quant'altro necessario, perlomeno non avvii la pratica? Ecco il punto: se anche la cosa non andasse a buon fine, avrete aumentato drammaticamente le probabilità di farlo andare a buon fine. E poi starebbe a voi sostenere le spese per dimostrare che quel finanziamento non lo avevate aperto voi...
Ma non è finita qui: di solito i sistemi per la consultazione delle buste paga danno accesso anche ad altri dati: i dati anagrafici, i dati del coniuge, dei figli, l'eventuale partecipazione a confessioni religiose, partiti politici, eventuali note spese da cui ricavare le abitudini di movimento, ecc..ecc.. Tutte informazioni che si rivelano una fonte preziosa di informazioni per un malintenzionato. Ma voi direte:"si, vabbè, ma molti di noi quelle informazioni le rendono pubbliche sui social networks, capirai che danno può essere".
Nossignori: un cedolino o un CUD originale scaricato dal sistema aziendale vale molto di più della "confessione" online.
Ed infine, veniamo al terzo punto di attenzione: solitamente, chi sceglie password semplici lo fa perchè non vuole intasarsi il cervello con decine di credenziali assurde. Perfetto. Questo fa il paio con la seconda leggerezza caratteristica: quella di usare la stessa password semplice per TUTTI i propri servizi online.
Nella mia esperienza, ho capito che oltre il 70% delle violazioni ad un sistema informatico son partite dall'attacco all'anello più debole della catena: le persone. Bisogna SEMPRE ricordarsi che la debolezza complessiva di un sistema è data dalla debolezza effettiva del suo punto più vulnerabile. E nel caso dei sistemi informatici sono SEMPRE le persone che quei sistemi li usano.

giovedì 19 dicembre 2013

Sandboxed malware analysis

Alert! Malware!!


Che titolone eh? Chiariamo da subito un concetto: il 99% delle piattaforme antivirus/antimalware si basano su due metodi di rilevamento: 
  • le signatures
  • l'analisi euristica.
Con le prime si va banalmente a consultare un database di hash di files o di stringhe caratteristiche per individuare una corrispondenza con un qualche pattern noto. Come funziona il tutto? Semplificando possiamo immaginare l'apparizione di un nuovo malware "in the wild" basato su un singolo eseguibile. Qualche utente sospettoso o qualche team di ricerca invia una copia dell'eseguibile "sospetto" ai centri di analisi e costoro sostanzialmente fanno due cose: calcolano l'hash del file e cercano nell'eseguibile delle stringhe. I risultati vengono ficcati nel file delle definizioni dei nostri antivirus e costituisce la "signature" del malware in questione. L'antivirus in real-time verificherà i files che entrano nel sistema e ne farà l'hashing e la ricerca di stringhe all'interno. Se troverà una corrispondenza, segnalerà l'elemento come infetto.
L'analisi euristica è un po' più sofisticata, ma meno accurata. Si basa sostanzialmente su una analisi del codice da cui cercare di "intuirne" l'esecuzione e definirne pertanto la sua "malevolenza" o meno. Si imposta normalmente una soglia per definirne l'accuratezza o, come alcuni in gergo dicono, il "paranoid level". Se il codice analizzato comporta operazioni quali la scrittura su aree di sistema, l'esecuzione da entry point non sicuri o l'attivazione di sessioni tramite protocolli noti (ad esempio irc), eccetera, allora l'antivirus segnalerà l'attività sospetta.
Fin qui tutto tranquillo, no? Beh, ad essere sinceri manca una "lieve" copertura: chi ci difende da un malware che sfrutta tecniche avanzate di evasione (Advanced Evasion Techniques)? Come fare a capire se un processo che non conosciamo è legittimo o se fa parte di una sofisticata minaccia persistente (Advanced Persistent Threat)?
Non possiamo.
Con gli strumenti di tradizionale endpoint security non è possibile intercettare questo genere di minacce.
Occorre una analisi specializzata basta su tecniche di sandboxing.
Cos'è una sandbox? Avete presente nei parchi giochi quei recinti con la sabbia dove si fanno giocare i bambini? Ecco, il paragone con l'informatica è questo: così come nelle sandbox "fisiche" si lasciano liberi i bambini di fare quello che gli pare essendo sicuri che non faranno danni, così nelle sandbox informatiche si lasciano liberi i malware di fare quello che gli pare, essendo sicuri che non faranno danni e dandoci l'opportunità di analizzarne il comportamento.
Chi dispone di un server VmWare può creare uno switch logico e qui collegare il client "tipo". Chi invece usa VmWare player dovrà configurare le schede di rete delle vm in host mode, in maniera tale da non farle interagire al di fuori del sistema.
Ma mettere in piedi una macchina virtuale da sola e lanciarci un virus mica ci permette di sapere come si comporta la minaccia. Occorre come minimo un altro sistema per l'analisi. Io uso normalmente due distro specifiche per il pentesting e l'analisi forense: REMnux, che è sostanzialmente fatta apposta per il reverse engineering dei malware e la sempre ottima Kali. A queste conviene associare alcuni elementi sulla macchina di test: 
  • Un debugger per poter analizzare il processo in esecuzione (e per questo IDA o OllyDBG andranno benissimo)
  • Degli strumenti per l'analisi dei process trees ed il monitoring di sistema (la suite sysinternals contiene una quantità impressionante di strumenti per la gestione ed il monitoring dei sistemi microsoft)
  • Uno sniffer (e qui, ovviamente, Wireshark la fa da padrone incontrastato)
  • Un buon hex editor fa comodo (Io uso PSPad)
  • Un unpacker può essere utile (Qui ne trovate una buona collezione)
Una delle prime cose che è utile fare per procedere con l'analisi è CREARE UN CLEAN SNAPSHOT DELLA MACCHINA DI TEST!! So che sembra ovvio, ma credetemi: quando si viene messi sotto pressione è facile dimenticarsi di mantenere uno snapshot aggiornato e pulito da usare come base.
Solitamente, la prima cosa che si fa è attivare il Wireshark per tenere sotto controllo il traffico di rete, quindi il process explorer e process monitor di sysinternals per vedere la catena di processi che il malware andrà eventualmente attivare ed i cambiamenti al sistema che effettuerà. Se saremo fortunati, il malware andrà a scrivere qualcosa nel registro o sul filesystem per potersi attivare allo startup. In alcuni casi i malware "creano" dei processi figlio tramite la generazione dinamica di codice batch che richiama altri processi. Il motivo di tale comportamento è presto detto: un antivirus euristico che analizza un binario capisce subito se questo vuole scrivere sul registro. Ma se l'eseguibile crea un batch che a sua volta fa una push nel registro della chiave per l'autostartup, l'antivirus non lo potrà mai intercettare... Altro strumento comodo per tenere sotto controllo il registro è autoruns, sempre della sysinternals suite. Permette di visualizzare tutti i processi che vengono avviati automaticamente dal sistema, assieme agli entry point ed ai triggers. Magari il malware è un bot che fa parte di una botnet. In tal caso wireshark ci mostrerà i tentativi di contatto con il CnC (Command and Control) server. A questo punto può capitare che l'analisi diventi impossibile, perchè alcuni bot e malware capiscono di trovarsi in esecuzione su una sandbox perchè non riescono a contattare il server CnC e pertanto si mettono in "quiet mode" o, addirittura, si autoterminano. Alcuni malware molto avanzati fanno una rapida scansione del sistema prima di qualsiasi altra operazione e, se rilevano di trovarsi in un ambiente virtuale, escono dall'esecuzione immediatamente. Si tratta in ambo i casi di tecniche di evasione fatte per impedire l'analisi. In tal caso, occorrererà per forza creare una sandbox fisica se si vorrà continuare l'analisi...
Quando i malware cominciano a generare traffico di rete, è il momento di mettere in funzione i sistemi di analisi. In primo luogo garantire la name resolution: andremo quindi a configurare come dns sul client l'indirizzo della nostra macchina di analisi, dove attiveremo fakedns (in REMnux) o dnschef (in Kali) per rispondere alle richieste con l'indirizzo della macchina di analisi stessa.
Ad ogni DNS request, le macchine di analisi risponderanno con il proprio indirizzo, così da permettere alle sessioni di rete di avere un terminatore. A questo punto, in funzione dei protocolli che verranno impiegati dal client di test, si potrà cercare di capire il tipo di servizio che viene richiesto: di solito i malware comunicano con l'esterno con IRC, FTP, HTTP, TFTP, SFTP, HTTPS. Ultimamente IRC viene sfruttato sempre di meno perchè la maggior parte dei firewall aziendali bloccano il traffico IRC...Una volta capito il tipo di servizio richiesto, si può cercare di rispondere con un setup..Attivare un server ftp o http per rispondere ci permetterà di scoprire che cosa il client cerca di recuperare dalla rete: a questo punto potremo provare ad andare a recuperare manualmente i componenti in giro sfruttando le richieste stesse per "popolare" il server web o ftp di ciò che il malware richiede, siano essi stringhe di comandi o parti di codice per fare altre e più complesse operazioni. Di recente mi è capitato di analizzare un malware che richiedeva, tramite varie richieste ftp ed http ad alcuni siti di personal storage in Russia, pezzi di eseguibili di altri programmi, principalmente per scattare foto dalla webcam del pc infetto, scaricare archivi di posta, cercare numeri di carte di credito o password, scattare screenshots o generare spam.

!!!ATTENZIONE!!!

La malware analysis su sandbox è una attività che comporta diversi rischi:
  • Può richiedere moltissimo tempo: ci sono dei malware che apparentemente non fanno proprio nulla di nulla per ore prima di attivarsi. Altri addirittura hanno come trigger solo lo scoccare di un momento specifico e poi non vengono più eseguiti. Ecco a cosa serve avere uno snapshot aggiornato: se un malware ha come trigger l'esecuzione solo a mezzanotte del 31/12, bisognerà fare in modo che il nostro client di prova sia configurato in modo tale da avere l'orologio fissato a pochi minuti prima della mezzanotte del 31/12.
  • Spesso occorre recuperare su siti "poco raccomandabili" dei pezzi di codice. Questo espone il pc al rischio di essere infettato da altri malware. E' buona norma pertanto non collegarsi con macchine o browser facilmente attaccabili. Una buona soluzione consiste nel recupero tramite wget di ciò che serve. o, più in generale, ricorrere a client testuali da riga di comando. Meno estensioni si usano meglio è.
  • In alcuni casi i server remoti sono gestiti direttamente dai creatori dei malware. Meglio non attirare troppo la loro attenzione con molteplici contatti, magari anche ripetuti in un periodo di tempo breve...
  • Il fatto che un malware sembri non fare nulla di nocivo non significa che ci si può giocare liberamente o "adattarselo per fare uno scherzo". Se credete di aver scoperto un nuovo malware, segnalatelo tramite le pagine di segnalazione malware dei fornitori di IT Security più noti (e.g.: McAfee Threat Center).
Buon divertimento!

venerdì 19 ottobre 2012

Sticking fingers in the socket...

Una delle primissime cose che mi son sentito ripetere sin da bambino, è stata che non si devono MAI mettere le dita nelle prese di corrente. Il mio problema, però, è che sin da bambino adoravo divertirmi scoprendo dei modi nuovi ed inusuali di utilizzare ciò che mi trovavo per le mani.
Un giorno, mentre stavo ascoltando con il mio fido mangiacassette un nastro con una fiaba, inciampai nel cavo di alimentazione, staccandolo dalla presa. Mi divertì molto sentire la voce del narratore storpiarsi lentamente prima di cascare nel silenzio. Mi divertì talmente tanto, che decisi che il mio passatempo per il resto del pomeriggio sarebbe stato quello di sentire la fiaba storpiata dal mio continuo staccare e riattaccare la spina dalla presa di corrente. Ricordo che mia madre era al telefono in camera sua, quando accadde il fattaccio: le mie ditine di bambino finirono troppo vicine ai contatti della spina mentre la reinserivo nella presa. Vidi un leggero lampo azzurrino e sentii un dolore istantaneo e fortissimo alla mano ed al braccio. Fortunatamente il salvavita intervenne e tutto si concluse solo con un grosso spavento.
Cosa c'entra tutto ciò con l'informatica? Beh, in inglese le prese elettriche si chiamano "socket" ed io oggi metterò le dita dentro le prese elettriche dell'informatica distribuita: i network socket.
Mi servirò dei seguenti strumenti: uno sniffer ed  analizzatore di protocollo (Wireshark), un linguaggio di scripting ad alto livello (Ruby) ed un paio di computer connessi in rete. Tutto può essere simulato anche su un computer singolo, dato che i network socket operano perfettamente anche sull'interfaccia loopback ed anzi, sono usatissimi proprio per gestire la comunicazione IPC.
Cominciamo dalla teoria:

Cos'è un network socket?

Un network socket è uno strumento concettuale di alto livello, che serve ad identificare il punto finale di una comunicazione. Esso in sostanza è una astrazione della struttura e dei processi necessari a trasmettere un pacchetto da un punto ad un altro di una rete. 
Se andiamo ad analizzare un pacchetto dati, scopriremo che esso è in realtà molto più complesso di quanto si possa immaginare. Esso è composto da tutta una serie di headers che, di fatto, "avvolgono" i nostri dati nei vari livelli OSI.
Non intendo mettermi qui a trattare del modello OSI. Se non lo conoscete, qui troverete più di ciò che vi serve sapere. Ad ogni modo, capirne qualcosa è fondamentale per andare avanti a seguire questo post.
Quando io voglio trasmettere qualcosa ad un altro sistema, devo specificare almeno chi sono (sorgente), dove voglio trasmettere (destinazione), a chi voglio trasmettere (porta) ed il contenuto della trasmissione (Dati). Questo è tutto ciò che normalmente mi serve per poter avviare una comunicazione.

Quello che segue è un semplicissimo client scritto in ruby che consente di aprire una connessione TCP, inviare dei dati e ricevere una risposta:

require 'socket'
hostname = (if ARGV.length == 2; ARGV.shift; else "10.136.128.90"; end)
puts hostname
comando = ""
s = TCPSocket.open(hostname, ARGV.shift)
while comando != "chiudi"
 comando = gets.chomp
 s.puts(comando)
 buffer = ""
 while buffer
  if buffer.chomp != ".term"
   buffer = s.gets
   puts buffer
  else
   buffer = nil
  end
 end
end
s.close

Questo qui sotto invece è un semplice server che "emula" in maniera molto rozza un servizio telnet, in quanto riceve i comandi dal client, li esegue in una shell locale e trasmette l'output del comando eseguito al client:

require 'socket' # prende socket dalla libreria

server = TCPServer.open(34444) # apre il socket server in ascolto sulla porta 19000

while true
 Thread.new(server.accept) do |connection|
  puts "connessione in ingresso da: #{connection.peeraddr[2]}"
  begin
   while connection
    c = connection.gets()
    if c != nil
     c = c.chomp
    end
    puts "dati in ingresso: #{c}"
    if c == "chiudi"
     puts "ricevuto: chiudi, connessione terminata"
     connection.close
     break
    else
     if c != ""
      # connection.puts "#{c}"
      uscita = %x(#{c})
      puts uscita
      connection.puts "eseguito: #{c}"
      connection.puts "#{uscita}"
      uscita = nil
      connection.puts ".term"
      connection.flush
     else
      connection.puts "nessun comando eseguito"
      connection.puts ".term"
     end
    end
   end
  rescue Exception => e
   puts "#{ e } (#{ e.class})"
  ensure
   connection.close
   puts "assicura: chiusura!"
  end
 end
end

Prima di far partire il server o il client, ho avviato il mio sniffer per catturare tutti i pacchetti scambiati tra il client ed il server.
A questo punto, lancio lo script server sulla mia macchina linux, quindi mi troverò con il seguente terminale attivo:


Il client lo avvio dalla mia macchina windows, pertanto mi si presenterà il seguente terminale:


Appena avviata la connessione, noto che il mio terminale mi segnala l'avviamento di una connessione in ingresso dal client:


Lo sniffer nel frattempo ha raccolto 3 pacchetti.

Andando a vedere il contenuto di questi pacchetti, scopriamo che non contengono dati. Ed allora perchè sono 3? Qui si deve entrare nella specificità del protocollo Internet e dei socket TCP. I socket TCP sono utili a stabilire delle trasmissioni orientate alla connessione (connection-oriented), pertanto per parlarsi, i due sistemi devono essere reciprocamente certi di poterlo fare. Come lo fanno? Con quello che si chiama normalmente un Three Way Handshacking.
Chi chiama manda un segnale (SYN) al server, come per dire:"Ciao! sei in ascolto?".. Il server risponde con un segnale (SYN, ACK), che dice "Ciao! Si, sono in ascolto.." A questo punto, il client manda un altro segnale (ACK) che "conferma" che adesso lui è al corrente del fatto che il server è effettivamente attivo e che è disposto a ricevere dei dati.
Dato che lo script server che ho creato è un emulatore "molto grezzo" di Telnet, proviamo allora a listare il contenuto della directory con il comando bash

ls -l

Sul teminale server apparirà l'output del comando...


...che verrà quindi trasmesso al client:


Ma cosa è successo sulla rete? Andiamo ad analizzare i pacchetti trasmessi:
Se osserviamo la colonna "Info" della nostra cattura, notiamo che il quarto pacchetto della nostra cattura è flaggato PSH, ACK. PSH sta per "push". I pacchetti PSH sono quei pacchetti che "spingono" i dati verso il server.



Osservando la finestra centrale, vedremo il nostro pacchetto scomposto secondo i vari layer OSI: Fisico (Frame), Data Link (Ethernet), Network (IPV4), Trasporto (TCP) e Sessione. In fondo vediamo anche un campo Data, con l'indicazione che contiene 5 bytes. Nella finestra più in basso, ci viene mostrato il nostro pacchetto per intero, sia in esadecimale che in ASCII. Guardate un po' quali sono gli ultimi 5 caratteri? Il nostro comando: "ls -l", più un terminatore (0x00) che ci viene mostrato in ASCII come un punto (.).
In pratica, per trasmettere 5 bytes di dati, abbiamo messo "sul filo" la bellezza di 60 bytes.
A questo punto, però, ci manca di capire cosa fa il server dopo che ha ricevuto il nostro pacchetto dati contenente la stringa "ls -l".
Lo scopriamo, ovviamente, col pacchetto successivo che, come si può ben vedere, è un ACK. Lascio a chi lo vorrà fare, il gusto di analizzare il resto della sessione.
Ci tengo a parlare però di altri due pacchetti particolari: FIN e RST.
Se per avviare e gestire una comunicazione abbiamo visto che esistono i pacchetti SYN, ACK e PSH, per terminare una sessione occorre un altro segnale. Questo segnale è il FIN, a cui si aggiunge l'ACK per chiedere al server di confermare di aver ricevuto l'intezione di cessare il socket. Il segnale FIN ACK dice al server:"Grazie di tutto, non ho più bisogno di mandarti o di ricevere dati". Ovviamente, il server, risponderà al FIN ACK con un ACK, per dire "Ok, grazie a te, addio!"
Ma cosa succede se a questo punto proviamo ancora a "spingere" un pacchetto dati? Qui entra il segnale RST.
RST sta per Reset e, sostanzialmente è il " 'zzo vuoi?" della comunicazione in rete. Dato che ogni sessione deve cominciare con un SYN, se io mando un pacchetto senza aver avviato educatamente la sessione con SYN, il server risponderà sgarbatamente con un RST, troncando la connessione.
Il pacchetto RST, vedremo prossimamente, è molto prezioso perchè consente di capire se un servizio è attivo senza necessariamente avviare una sessione, evitando così di lasciare una propria "impronta" nei log delle sessioni dei server analizzati.

giovedì 11 ottobre 2012

How to dismantle a Logic Bomb


Anni fa gli U2 pubblicarono un album, dal titolo "How to dismantle an Atomic bomb".
Era il 2004, ed all'epoca io ero molto impegnato a godermi la mia nuova moto...Ma questo non mi impediva certo di continuare a combinare le mie belle marachelle informatiche in casa. A dire il vero, questa che vi racconto oggi è una delle primissime sciocchezze che mi sia mai capitato di fare ed è strettissimamente collegata con il post precedente. Se nel 1982 i loop si facevano in BASIC, a partire dal 1991 cominciai a farli un po' più seri con Ms-DOS.
All'epoca ero fortunato possessore di un brillantissimo (all'epoca) 80386DX40, ovviamente affiancato dal coprocessore FPU 80387. In quegli anni i PC venivano anche chiamati "cloni", in quanto era appena partito alla grande il mercato del personal computing ed era pertanto facile trovare assemblatori ad ogni angolo delle strade. Più o meno chiunque avesse a disposizione quattro mura si metteva a comprare ed a mettere insieme motherboards, schede video, case, alimentatori per poi venderli. Il mio sistema usava un 80386 prodotto da AMD (quando ancora la AMD era una dittarella), saldato sulla scheda madre perchè, all'epoca, l'idea di bruciare una CPU non passava per l'anticamera del cervello di nessuno, ed i produttori di CPU si facevano pagare soldoni per confezionare i chip in voluminosi e complicati package flip chip dotati di centinaia di pin. Come conseguenza di ciò, anche le mainboard dotate di socket costavano betoniere di quattrini! All'epoca i processor socket erano ad incastro "semplice" e sulle mainboard normalmente non ce n'erano. C'era la CPU saldata sulla scheda e basta. Su quelle un po' più "sofisticate" se ne trovava solo uno idoneo al montaggio del famigerato coprocessore 80X87. Fino alla serie 486, infatti, non tutte le CPU erano dotate nativamente di una Floating Point Unit integrata. Effettuavano le operazioni in virgola mobile "emulando" le operazioni con una serie di istruzioni più elementari. Paradossalmente, ciò che all'epoca costava di più, in un computer, non era la CPU, nè la scheda video. Il vero capitale era la RAM. I sistemi impiegavano dei costosissimi moduli SIMM che venivano venduti a tagli da 256KB, 512KB, 1MB, 2MB e 4MB. I primi, ovviamente costavano relativamente poco, ma dato che le mainboard supportavano solo 8 slot (utilizzabili tassativamente a coppie), era logico che venissero usati tipicamente 8 moduli da 256KB per avere la bellezza di 2 MB di RAM. Io ero all'epoca un privilegiato, perchè comprai il computer fornito di 4 moduli da 1MB. pertanto potevo vantare la bellezza di 4 Mega di RAM. E vi lascio immaginare la mia gioia estrema quando un giorno, in ufficio da mio padre, trovai 2 moduli da 2MB che erano stati dismessi da una loro titolatrice CHYRON per far spazio a 2 moduli da 4 MB. Li portai a casa e li montai nel PC con la stessa cura ed attenzione che un neurochirurgo adopera quando ficca le mani in un cranio umano. Ora ero il fortunato possessore di un PC 386DX40 con coprocessore 387, 8 MB di RAM, scheda video VESA, Hard Disk da 40 MB, Ms-DOS 5.0 e Windows 3.0!
Credetemi, all'epoca era davvero un pezzo forte, che suscitava l'invidia di tutti i miei compagni di scuola. Vi basti sapere che ci potevo persino giocare a Wolf3D a tutto schermo!
Al tempo, Windows era per me sostanzialmente inutile. Di fatto non lo caricavo mai, dato che tutto quello che mi serviva fare lo potevo tranquillamente e molto più efficacemente fare rimanendo in DOS mode. L'unico vero limite del DOS mode era il fatto che la memoria "visibile" ai programmi era limitata a 640KB, perchè MS-DOS era un sistema a 16 bit. Era ovviamente disponibile un driver dos extended mode che permetteva di indirizzare la memoria a 32 bit tramite paging, ma dato che di norma nessun programma occupava più di 2MB di RAM, difficilmente si poteva sentirne l'esigenza. Ad ogni modo, in quegli anni io andavo a scuola e stavo imparando a programmare in Turbo Pascal. Il principale problema di MS-DOS era che non era affatto un sistema operativo multitasking, pertanto era impossibile sviluppare software che operasse tramite IPC (Inter Process Communication). Come si poteva ovviare a tutto ciò? Il modo più semplice (ed abusato) era quello di avviare i programmi tramite dei batch script (i famosi file con estensione .bat) e creando per quanto possibile dei moduli indipendenti che, tramite un menù ed il trasferimento dei dati via filesystem, permettesse di alternare l'elaborazione. Concettualmente semplice, praticamente un casino.
Fu proprio in occasione della produzione di un batch file per lanciare un set di 2 programmi che innescai la mia prima bomba logica.
A scuola ci insegnavano la programmazione Top-Down, dal macro al micro, dagli algoritmi in metalinguaggio al codice compilabile...
A casa si apriva l'IDE e si scriveva direttamente il codice, sviluppando per debug incrementale.
Produssi pertanto due exe: il primo, chiamato menu.exe, non faceva altro che disegnare un menù sullo schermo, raccogliere l'input, metterlo in un file ed uscire. Il secondo, chiamato elabora.exe, apriva il file, leggeva cosa c'era scritto, faceva una operazione in funzione di quanto aveva letto, cancellava il contenuto del file ed usciva. Il tutto veniva lanciato da un batch file, chiamato avvio.bat, che conteneva il seguente codice:

:inizio
menu.exe
elabora.exe
goto inizio
:end

Ovviamente il tutto, messo così, non darebbe alcun problema se non fosse che, come è facile immaginare, si tratta di un loop infinito. Manca la condizione di uscita. Certo, sarebbe bastato un semplice IF nel file batch. Il problema è che io volevo che la condizione d'uscita fosse selezionabile nel menù del programma e non dipendente dallo script di avvio.
Introdussi quindi nel codice di elabora.exe una routine che, nella mia mente di programmatore ragazzino, avrebbe dovuto risolvere il problema. Avrei aperto il file batch dall'interno dell'eseguibile ed avrei modificato la riga del goto cambiando la label, da "inizio" a "end". Stavo per addentrarmi nel terreno inesplorato del polimorfismo...
Feci un po' di prove e sembrava che tutto funzionasse bene...decisi quindi di impaccare il tutto e di lanciare il mio batch
_______________________

C:\Programma> Avvio.bat

                                    MENU'
   Digita un numero per selezionare l'opzione desiderata, quindi premi invio:

                              1) Opzione 1
                              2) Esci dal programma

Scelta> 2

Mi aspettavo che il programma sarebbe uscito al prompt, invece tornò al menù...
Mi venne pertanto il dubbio che non avesse modificato come desiderato il file batch, pertanto mi domandai come fosse possibile cambiare il programma durante l'esecuzione.
Ve la faccio breve: non riuscivo a capire che il file batch che chiamava gli eseguibili rimaneva "bloccato" dal sistema, rendendone impossibile la modifica. Cercate di capire una cosa: all'epoca non c'era Internet in casa, pertanto trovare la soluzione al mio problema "online" non era una opzione praticabile. Tutto il supporto che potevo avere era quello fornitomi da un manuale di Ms-DOS.
Lì dentro trovai la fatidica risposta ai miei quesiti: la funzione "CALL".
la funzione Call permette ad un batch di richiamare un altro batch, eseguirlo, quindi ripassare l'esecuzione al batch chiamante.
Ecco allora l'idea: il batch di avvio chiama il programma del menù tramite una call ad un batch che chiama menù.exe
Quindi menù.exe oltre a scrivere il file contenente l'opzione per elabora.exe, scrive anche il batch che lo chiama, in maniera tale che se l'opzione scelta non è quella di uscita, allora il batch conterrà una call al batch che lancia il menù.
Tralascio ogni considerazione sul fatto che, come è evidente, un programmatore motivato è sempre capace di trovare una soluzione che aggira i limiti imposti dal sistema. Sta di fatto che avevo creato un loop potenzialmente devastante.
Ed infatti alla prima esecuzione il sistema non fece una piega, salvo cominciare a dare un po' i numeri dopo una trentina di volte che rieseguivo il ciclo senza uscire dal programma...
Avevo creato una bomba logica che dopo un certo numero di cicli saturava la memoria del computer.
La cosa paradossale è che ancora oggi il problema delle bombe logiche non è affatto risolto.
Se non ci credete, provate voi stessi, con il seguente semplicissimo batch file.

!!!!ATTENZIONE!!!!
Il codice qui sotto è una VERA bomba logica. Se lo lanciate ben difficilmente sarete in grado di fermare il computer dal saturarsi e l'unico modo che avrete per interrompere il loop sarà quello di spegnere fisicamente il computer. Pertanto accertatevi di avere salvato tutto e di aver creato un punto di ripristino, dato che lo spegnimento "brutale" del sistema, per quanto completamente innocuo nel 99.99% dei casi, ha sempre uno 0.01% di probabilità di rovinare il filesystem da qualche parte.

aprite un command prompt e digitate il comando:

echo start bomb.bat > bomb.bat

A questo punto vi è sufficiente lanciare bomb.bat per far partire una cascata di finestre di CMD che in breve tempo renderanno il computer inutilizzabile.


Le bombe logiche, nelle loro più disparate varianti, sono tecnicamente da ascrivere alla categoria dei Denial of Service (DoS).


mercoledì 3 ottobre 2012

Very first

Agli albori della mia vita informatica andava di moda il B.A.S.I.C.
Chiunque iniziava con il suo primissimo programma:

dopo il fatidico RUN, l'output faceva brillare gli occhi di soddisfazione:



Subito dopo, si cominciava a "complicarsi la vita", creando il primo loop:



di nuovo RUN e..


Si premeva continuamente "Y" per continuare a vedere sempre la stessa videata...
Dopo una serie di almeno 10 "Y", finalmente si premeva "N" ed il loop si interrompeva, con grande soddisfazione...
Quello è stato l'inizio, anche per me, nell'ormai lontano 1982, all'età di 8 anni, hands-on su un Sinclair ZX Spectrum 48K.
Molti ragazzini oggi non sanno che 30 anni fa serviva un sacco di ingegno per non saturare la memoria di un computer. 48K, alla fine della fiera, equivalgono a 49152 caratteri. Non si può certo mettere chissà quanto codice, in così poca memoria. Eppure all'epoca pareva pure tanta, dato che lo Spectrum "di serie" montava solo 16K.
Ad ogni modo, da lì in poi tutti gli informatici del mondo si sono distinti in due grandi gruppi: quelli che da subito si sono ingegnati per cercare di far stare tutto il loro lavoro entro quei fatidici 48K e quelli che invece, da subito, hanno voluto provare a vedere cosa succedeva provando a spingersi oltre.
I primi si sono pertanto messi con carta e penna a cercare di capire esattamente quanti caratteri avrebbero potuto memorizzare, tenendo conto dello spazio di memoria già usato dal programma, ecc..ecc..
I secondi invece hanno prodotto immediatamente un codice come questo, o perlomeno mooooooolto simile:


e dopo il RUN...


"Y".."Y"..."Y"..."Y"... e finalmente:



Ecco..quella è la differenza fondamentale. Da lì nasce tutto. Da una "fork filosofica".
I sistemisti più "estremi" sono soliti dire che, dopotutto, anche UNIX è una fork.

Questo blog mi nasce così, dall'idea di parlare di informatica nel modo in cui l'ho conosciuta e la conosco io.
Troverete tutorials, suggerimenti, curiosità o anche solo dei racconti.
Dipende da cosa mi passerà per la testa volta per volta.