CVE-2021-41243 - Zip Slip to RCE on Basercms

Introduzione

Ciao a tutti! Oggi nel blog parleremo di una scoperta, da parte di un membro del team di Soter (Daniele ‘sk4’ Scau), del CVE-2021-41243 che riguarda una vulnerabilità correlata ad un tipo di file molto famoso: L’archivio ZIP. Il formato ZIP nasce nel 1989 con una sua prima implementazione all’interno dell’utility PKZIP sviluppata dall’azienda PKWARE Inc. L’archivio ZIP è un particolare tipo di file codificato con un algoritmo di compressione in cui all’interno possono esserne contenuti altri. Lo scopo principale di questo tipo di file è quello di salvare spazio all’interno del disco ed è anche molto utilizzato per conservare più file in un singolo posto. Algoritmi simili sono anche utilizzati nella trasmissione dei dati con l’obiettivo di inviare un certo numero di dati in modo compresso risparmiando banda e evitando la perdita di informazioni.

Un archivio ZIP, by design, può contenere ogni tipo di file mantenendo la struttura del filesystem. Supponiamo ad esempio di avere il seguente albero di directory:

\_ directory1
|      |_ file1
|   
|_ directory2
       |_ subdirectory1
              |_ subdirectory2

è possibile creare un nuovo archivio ZIP a partire da subdirectory2 includendo il file file1 che risiede all’interno della directory directory1 riferendosi ad esso con il path ../../directory1/file1. Quando il programma che effettua la decompressione dell’archivio estrae i file, la struttura delle directory verrà preservata, estraendo correttamente il file file1 all’interno della directory ../../directory1 se esiste.

Recentemente, nel 2018, due differenti team di ricerca: Snyk e Pangu, hanno scoperto che molte librerie che offrono la funzionalità di estrazione dei dati da un archivio, quando usate, non effettuano alcun sanity check sul nome del file estratto, con la conseguenza di avere una vulnerabilità di path traversal che consente ad un attaccante di scrivere file arbitrariamente sul filesystem. Snyk ha dato a questa vulnerabilità il nome di Zip Slip. Il team Pangu ha scoperto che una vulnerabilità simile affligge alcune applicazioni iOS e ha chiamato la vulnerabilità ZipperDown.

Zip Slip on Basercms

L’attività di ricerca svolta rigurda il CMS giapponese basato su CakePHP chiamato Basercms. Una delle prime funzionalità che trovate durante la ricerca è la possibilità, da parte di un amministratore con il privilegio di effettuare operazioni di maintenance, di caricare un archivio ZIP con lo scopo di ripristinare i dati all’interno del database. Ovviamente la prima cosa testata è l’attacco Zip Slip. Per l’exploitation è stato sufficente creare un archivio ZIP con la seguente struttura:

../../../../../../../../var/www/html/basercms/shell.php

Dove il file shell.php contiene una semplice Web Shell per ooter eseguire comandi sul server. Quando l’archivio viene caricato, il CMS estrae tutti i file dall’archivio senza effettuare nessun sanity check sui nomi dei file, infatti il file shell.php viene creato all’interno della webroot del CMS riuscendo così ad ottenere Remote Code Execution.

Vediamo più nel dettaglio il perché è possibile effettuare questa operazione andando ad esaminare la funzione che effettua la decompressione del file caricato. Se cerchiamo all’interno del codice la funzionalità che provvede di effettuare la decompressione di un archivio ZIP, troviamo la classe Simplezip all’interno del file lib/Baser/Vendor/Simplezip.php. All’interno della classe è presente il metodo unzip che salva tutti i file all’interno dell’archivio sul filesystem come è possibile vedere di seguito:

...
function unzip($source, $tareget)
{
  $tareget = preg_replace('/\/$/', '', $tareget);
  $entries = $this->_readFile($source);
  if (!$entries) {
    return false;
  }
  $result = true;
  foreach($entries as $entry) {
    $folder = new Folder($tareget . DS . $entry['Path'], true, 0777);
    $fp = @fopen($tareget . DS . $entry['Path'] . DS . $entry['Name'], 'wb');
    if ($fp) {
      if (!fwrite($fp, $entry['Data'])) {
        $result = false;
      }
    } else {
      $result = false;
      continue;
    }
    fclose($fp);
  }
  return $result;
}
...

Come è possibile osservare, le variabili $entry['Path'] e $entry['Name'] vengono utilizzate per la creazione del file estratto e se all’interno della prima variabile si riesce a iniettare un payload di path traversal ../, è possibile uscire dalla directory principale definita dalla variabile $target e scrivere un file malevolo in un posto arbitrario all’interno del filesystem. La funzione _readFile implementa l’algoritmo di decompressione dei dati e ritorna un array contenente la lista dei file presenti all’interno dell’archivio ZIP con: nome, path e contenuto.

La vulnerabilità è stata riportata a Snyk che ha contattato gli sviluppatori del CMS Basercms che ha poi hanno risolto il problema.

Conclusion

Con questa vulnerabilità è stato possibile approfondire i concetti di Zip Slip e soprattutto, per quanto possa sembrare banale, MAI fidarsi degli input che provengono dagli utenti!

Timeline