
Exploit Python pour CVE-2019-5096, une vulnérabilité d'utilisation après libération dans le gestionnaire de téléchargement du serveur web GoAhead, provoquant un déni de service via une double libération.
python TriggerDOS.py ip

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

Dans le code, localisez upload.c:370, on peut voir que dans
wp->currentFile=0
avant l'exécution de
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 fonction hashEnter ajoute un élément à la table de hachage, ce qui provoque de multiples références à wp->currentFile. La structure WebsUpload dans wp->files (table de hachage) sera libérée lors de l'appel à termWebs à la fin de la session http (fin du cycle de vie de Webs).
static void termWebs(Webs *wp, int reuse)
{
...
#if ME_GOAHEAD_UPLOAD
if (wp->files >= 0) {
websFreeUpload(wp);//parcourt la table de hachage, récupère la structure WebsUpload et la libère.
}
#endif
}
Ensuite, regardons un autre point de libération :
...
processUploadHeader(Webs *wp, char *line)
{
while (key && stok(key, ";\r\n", &nextPair)) {// Ceci analyse l'en-tête upload avec ; comme délimiteur
...
else if (scaselesscmp(key, "filename") == 0) {
...
freeUploadFile(wp->currentFile);
file = wp->currentFile = walloc(sizeof(WebsUpload));
...
}
}
}
On constate que si l'en-tête de téléchargement contient un champ filename, wp->currentFile est libéré, puis un WebsUpload est alloué avec walloc.
Comme sizeof(WebsUpload) est inférieur à global_max_fast, le tas rapide alloue selon le principe LIFO, donc le bloc fraîchement libéré est immédiatement réalloué, et il est à nouveau ajouté à la table de hachage dans la fonction processContentData suivante. La table de hachage contient alors deux références à ce chunk, ce qui provoque un double free et un abort lors de termWebs.
Ajouter deux en-têtes upload dans une seule requête :
Après la fonction processContentData, on entre à nouveau dans processUploadHeader. Soit la séquence d'appels suivante :
websProcessUploadData (boucle) # machine à états de téléchargement, chaque boucle détermine un état
->initUpload()
->processContentBoundary()
->processUploadHeader()
->processContentData()
->processContentBoundary()
->processUploadHeader()
->processContentData()
->return;
...