
Mautic < 5.2.3 RCE autenticata
La scarsa sanificazione del contenuto, del tipo e dell'estensione dei file caricati nella funzionalità Asset Edition consente a un attaccante autenticato di scrivere codice PHP arbitrario all'interno della directory web e di individuare dove viene scritto tale file. Questo comporta l'esecuzione remota di codice (RCE).
Un path traversal consente inoltre di sfruttare questa funzionalità per eliminare ricorsivamente qualsiasi directory del filesystem che l'utente web ha il permesso di modificare.

Quando si modifica un Asset tramite la rotta /assets/view/{assetID}, viene data la possibilità di cambiare il file dell'asset.
Il caricamento di un nuovo file richiama infine la seguente funzione all'interno di app/Bundles/AssetBundle/Controller/AssetController.php:
public function editAction(Request $request, UploaderHelper $uploaderHelper, AssetModel $model, $objectId, $ignorePost = false)
La logica di caricamento si trova qui:
if (!$ignorePost && 'POST' == $method) {
$valid = false;
if (!$cancelled = $this->isFormCancelled($form)) {
if ($valid = $this->isFormValid($form)) {
$entity->setUploadDir($this->coreParametersHelper->get('upload_dir'));
$entity->preUpload();
$entity->upload();
Più precisamente, siamo interessati ai metodi preUpload() e upload(), poiché gestiscono la scrittura effettiva del file su disco.
Il primo difetto risiede in preUpload() in app/Bundles/AssetBundle/Entity/Asset.php, in quanto l'implementazione consente di specificare un'estensione di file arbitraria (aggirando così la protezione normalmente fornita dall'array allowed_extensions):
$filename = sha1(uniqid(mt_rand(), true));
$extension = $this->getFile()->guessExtension();
if (empty($extension)) {
// get it from the original name
$extension = pathinfo($this->originalFileName, PATHINFO_EXTENSION);
}
$this->path = $filename.'.'.$extension;
La riga $extension = $this->getFile()->guessExtension(); restituirà NULL se forniamo un nome file che termina con .php e contenuto che inizia con il tag <?php. Il controllo empty($extension) risulterà quindi vero e l'estensione del file verrà poi estratta tramite la chiamata pathinfo(), consentendoci così di caricare file temporanei con contenuto ed estensione arbitrari. Non possiamo controllare il nome effettivo del file poiché viene generato con sha1().
Successivamente, all'interno del successivo metodo upload(), il file verrà effettivamente scritto su disco nella directory web tramite la seguente chiamata:
$this->getFile()->move($this->getUploadDir(), $this->path);
Utilizza la nostra estensione arbitraria (contenuta nella variabile $this->path). Il nome del file può quindi essere recuperato aggiornando la pagina dei dettagli dell'Asset (/assets/view/{assetId}), alla voce della tabella Local filename.
NB: Questo funziona anche alterando le richieste inviate durante la creazione di un nuovo Asset. Ciò richiamerà la funzione newAction(), ma la logica è identica e i difetti risiedono ancora nei metodi preUpload() e upload().
Il PoC non sarà pubblicato per circa un altro mese.
Questo per dare tempo alle organizzazioni che fanno affidamento su questo software di applicare la patch senza temere che script kiddies distruggano i loro sistemi.
Dopodiché, questo repository verrà aggiornato con lo script di sfruttamento completo e le prove. C'è già abbastanza informazioni in questa pagina comunque.
Durante la convalida di un upload temporaneo (tramite /s/assets/new o /s/assets/edit/{assetId}), la directory che memorizza il file temporaneo viene eliminata ricorsivamente alla fine della richiesta.
Il parametro responsabile di contenere il nome della directory temporanea è suscettibile ad attacchi di path traversal, consentendo a un attaccante autenticato di eliminare qualsiasi directory sul sistema, a condizione che l'utente web abbia il permesso di farlo.
Ciò può comportare perdita di dati o addirittura la distruzione dell'intero filesystem se il server viene eseguito dall'utente root.
Specificare qualsiasi file presente sul sistema tramite l'endpoint utilizzato di seguito. Se il file esiste, il server tenterà di eliminare la directory in cui è archiviato.

Compromissione del server Negazione del servizio Perdita di dati