
CVE-2019-5096(UAF in upload handler) exploit cause Denial of Service
python TriggerDOS.py ip

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

कोड में upload.c:370 पर जाएं, देख सकते हैं कि
wp->currentFile=0
से पहले निम्नलिखित निष्पादित होता है
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;
...
}
यहाँ hashEnter फ़ंक्शन हैश टेबल में एक एलिमेंट जोड़ता है, जिससे wp-currentFile के कई संदर्भ (multiple references) होते हैं। wp->files (हैश टेबल) में स्थित WebsUpload संरचना को http सत्र समाप्ति (Webs जीवनचक्र समाप्ति) पर termWebs कॉल करने पर free कर दिया जाता है
static void termWebs(Webs *wp, int reuse)
{
...
#if ME_GOAHEAD_UPLOAD
if (wp->files >= 0) {
websFreeUpload(wp);//हैश टेबल से WebsUpload संरचना निकालकर free करें।
}
#endif
}
अब एक और free बिंदु देखते हैं:
...
processUploadHeader(Webs *wp, char *line)
{
while (key && stok(key, ";\r\n", &nextPair)) {// यह ; से upload हेडर पार्स करता है
...
else if (scaselesscmp(key, "filename") == 0) {
...
freeUploadFile(wp->currentFile);
file = wp->currentFile = walloc(sizeof(WebsUpload));
...
}
}
}
पता चलता है कि यदि अपलोड हेडर में filename फ़ील्ड है, तो wp->currentFile को free कर दिया जाता है, और फिर walloc द्वारा एक नया WebsUpload आवंटित किया जाता है।
चूंकि sizeof(WebsUpload) global_max_fast से छोटा है, हीप फास्टबिन LIFO (Last-In-First-Out) आवंटन का अनुसरण करेगा, इसलिए अभी free किया गया हीप खंड तुरंत पुनः आवंटित हो जाता है, और बाद में processContentData फ़ंक्शन में इसे फिर से हैश टेबल में जोड़ा जाता है। तब हैश टेबल में उस chunk के दो संदर्भ (references) होते हैं, और termWebs पर double free होकर abort होता है।
एक ही अनुरोध में दो अपलोड हेडर जोड़ें:
processContentData फ़ंक्शन के बाद फिर से processUploadHeader फ़ंक्शन में प्रवेश करें। अर्थात निम्नलिखित क्रम में कॉल:
websProcessUploadData (लूप) #अपलोड स्टेट मशीन, प्रत्येक लूप एक स्थिति निर्धारित करता है
->initUpload()
->processContentBoundary()
->processUploadHeader()
->processContentData()
->processContentBoundary()
->processUploadHeader()
->processContentData()
->return;
...