
Exploit Python per CVE-2019-5096, una vulnerabilità use-after-free nel gestore di upload del server web GoAhead, che causa denial of service tramite double-free.
python TriggerDOS.py ip

[https://github.com/embedthis/goahead.git] Collegamento GitHub di GoAhead

Nel codice, individuare upload.c:370, si può vedere che in
wp->currentFile=0
prima viene eseguito
typedef struct WebsUpload {
char *filename; /**< Local (temp) name of the file */
char *clientFilename; /**< Client side name of the file */
char *contentType; /**< Content type */
ssize size; /**< Uploaded file size */
} WebsUpload;
...
typedef struct Webs {
...
WebsUpload *currentFile;
...
}Webs;
...
processContentData(Webs *wp){
...
file = wp->currentFile;
...
hashEnter(wp->files, wp->uploadVar, valueSymbol(file), 0);
defineUploadVars(wp);
wp->currentFile=0;
...
}
La funzione hashEnter aggiunge un elemento alla tabella hash, causando qui molteplici riferimenti a wp->currentFile. La struttura WebsUpload nella wp->files (tabella hash) verrà liberata quando viene chiamata termWebs alla fine della sessione HTTP (fine del ciclo di vita di Webs).
static void termWebs(Webs *wp, int reuse)
{
...
#if ME_GOAHEAD_UPLOAD
if (wp->files >= 0) {
websFreeUpload(wp);//attraversa la hashtable, recupera la struttura WebsUpload e la libera.
}
#endif
}
Ora guardiamo un altro punto di free:
...
processUploadHeader(Webs *wp, char *line)
{
while (key && stok(key, ";\r\n", &nextPair)) {// parsing dell'header upload usando ; come delimitatore
...
else if (scaselesscmp(key, "filename") == 0) {
...
freeUploadFile(wp->currentFile);
file = wp->currentFile = walloc(sizeof(WebsUpload));
...
}
}
}
Si scopre che se l'header upload ha un campo filename, allora wp->currentFile viene liberato, e successivamente viene allocato un WebsUpload con walloc.
Poiché sizeof(WebsUpload) rientra nella dimensione di global_max_fast, il chunk heap verrà allocato secondo la politica LIFO (Last In First Out), quindi il chunk appena liberato viene immediatamente riallocato e verrà nuovamente aggiunto alla tabella hash nella successiva funzione processContentData. A questo punto la tabella hash ha già due riferimenti a quel chunk, e quando viene chiamato termWebs si verifica un double free che causa un abort.
Aggiungere due header upload in una singola richiesta:
Invocazione sequenziale dopo processContentData della funzione processUploadHeader. Cioè nell'ordine seguente:
websProcessUploadData (ciclo) # macchina a stati dell'upload, ogni ciclo determina uno stato
->initUpload()
->processContentBoundary()
->processUploadHeader()
->processContentData()
->processContentBoundary()
->processUploadHeader()
->processContentData()
->return;
...