
استغلال CVE-2019-5096 (UAF في معالج الرفع) يسبب رفض الخدمة
python TriggerDOS.py ip

[https://github.com/embedthis/goahead.git] GoAhead رابط GitHub

في الكود، نحدد الموقع 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. سيتم تحرير بنية WebsUpload الموجودة في wp->files (جدول التجزئة) عند انتهاء جلسة http (انتهاء دورة حياة Webs) بواسطة استدعاء termWebs
static void termWebs(Webs *wp, int reuse)
{
...
#if ME_GOAHEAD_UPLOAD
if (wp->files >= 0) {
websFreeUpload(wp);// traverses hashtable and frees each WebsUpload structure.
}
#endif
}
الآن ننظر إلى نقطة تحرير أخرى:
...
processUploadHeader(Webs *wp, char *line)
{
while (key && stok(key, ";\r\n", &nextPair)) {// this splits by ; to parse upload header
...
else if (scaselesscmp(key, "filename") == 0) {
...
freeUploadFile(wp->currentFile);
file = wp->currentFile = walloc(sizeof(WebsUpload));
...
}
}
}
نجد أنه إذا كان حقل الرأس filename موجودًا في رأس الرفع، يتم تحرير wp->currentFile، ثم تخصيص WebsUpload جديد باستخدام walloc.
نظرًا لأن sizeof(WebsUpload) يقع ضمن حجم global_max_fast، فسيتم تخصيص الكومة وفقًا لمبدأ آخر ما يدخل أول ما يخرج، وبالتالي يتم تخصيص الكتلة المحررة حديثًا على الفور، ثم يتم إضافتها مرة أخرى إلى جدول التجزئة في دالة processContentData. الآن جدول التجزئة يحتوي على مرجعين لنفس الكتلة، مما يؤدي إلى تحرير مزدوج (double free) وتعطل البرنامج عند استدعاء termWebs.
إضافة رأسين upload في طلب واحد:
بعد دالة processContentData، يتم الدخول مرة أخرى إلى دالة processUploadHeader. أي الترتيب التالي للاستدعاء:
websProcessUploadData (حلقة) #آلة حالة الرفع، تحدد كل حلقة حالة واحدة
->initUpload()
->processContentBoundary()
->processUploadHeader()
->processContentData()
->processContentBoundary()
->processUploadHeader()
->processContentData()
->return;
...