Talos Vulnerability Report

TALOS-2019-0888

EmbedThis GoAhead web server code execution vulnerability

December 2, 2019
CVE Number

CVE-2019-5096

Summary

An exploitable code execution vulnerability exists in the processing of multi-part/form-data requests within the base GoAhead web server application in versions v5.0.1, v.4.1.1 and v3.6.5. A specially crafted HTTP request can lead to a use-after-free condition during the processing of this request that can be used to corrupt heap structures that could lead to full code execution. The request can be unauthenticated in the form of GET or POST requests, and does not require the requested resource to exist on the server.

Tested Versions

EmbedThis GoAhead Web Server v5.0.1 EmbedThis GoAhead Web Server v4.1.1 EmbedThis GoAhead Web Server v3.6.5

Product URLs

https://www.embedthis.com/goahead/

CVSSv3 Score

9.8 - CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CWE

CWE-416: Use After Free

Details

GoAhead Web Server is a popular embedded web server designed to be a fully customizable web application framework and server for embedded devices. It provides all the base HTTP server functionality and provides a highly customizable platform for developers of embedded web applications.

When processing a multi-part/form-data HTTP request with multiple Content-Disposition headers in the same request, a use-after-free condition can occur while cleaning up the heap structures used for storing the different parts of the request.

Both HTTP GET and POST methods allow access to the vulnerable condition but are restricted by the methods defined in the route configuration. In the default build configuration, it is not required that the page requested exist as it seems to inherit permissions from the parent path. During testing on additional devices, it has been observed that there may be other route restrictions that affect access to the vulnerability.

/* src/upload.c */
66 static void freeUploadFile(WebsUpload *up)
67 {
68     if (up) {
69         if (up->filename) {             // BUG: First UAF here
70             unlink(up->filename);       // BUG: UAF/unlink - probably not a good idea
71             wfree(up->filename);        // BUG: Double free here
72         }
73
74         wfree(up->clientFilename);
75         wfree(up->contentType);
76         wfree(up);
77     }
78 }

Crash Information

double free or corruption (fasttop)

[#0] 0x7ffff6dc1e97 → __GI_raise(sig=0x6)
[#1] 0x7ffff6dc3801 → __GI_abort()
[#2] 0x7ffff6e0c897 → __libc_message(action=do_abort, fmt=0x7ffff6f39b9a "%s\n")
[#3] 0x7ffff6e1390a → malloc_printerr(str=0x7ffff6f3b828 "double free or corruption (fasttop)")
[#4] 0x7ffff6e1b004 → _int_free(have_lock=0x0, p=0x611a00, av=0x7ffff716ec40 <main_arena>)
[#5] 0x7ffff6e1b004 → __GI___libc_free(mem=0x611a10)
[#6] 0x7ffff7b6e897 → freeUploadFile(up=0x611a50)
[#7] 0x7ffff7b6e7fc → websFreeUpload(wp=0x60d680)
[#8] 0x7ffff7b62274 → reuseConn(wp=0x60d680)
[#9] 0x7ffff7b5e438 → complete(wp=0x60d680, reuse=0x1)

Mitigation

Given the the wide distribution of architectures and operating systems GoAhead Web Server supports, exploitability will more than likely be heavily dependent on the specific target. Given the customizations available for the project, this vulnerability may not be reachable on all builds. We have observed that the ME_GOAHEAD_UPLOAD compile time flag be enabled as well as the existence of path specified in ME_GOAHEAD_UPLOAD_DIR. By default, these are set so the vulnerability should be reachable. Additionally, pages that require authentication do not allow access to the vulnerability without authentication as the authentication is handled before reaching the upload handler.

GoAhead Web Server does provide a compilation option to replace malloc/free with their own internal allocator using the option ME_GOAHEAD_REPLACE_MALLOC. This does catch the most UAF example but in testing, but we have been able to show corruption is still possible with minimal modifications. This replacement doesn’t seem to be the default for any of the provided projects currently.

grep ME_GOAHEAD_REPLACE_MALLOC projects/*
projects/goahead-freebsd-default-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-freebsd-default-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-freebsd-static-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-freebsd-static-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-linux-default-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-linux-default-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-linux-static-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-linux-static-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-macosx-default-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-macosx-default-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-macosx-openssl-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-macosx-openssl-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-macosx-static-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-macosx-static-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-vxworks-default-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-vxworks-default-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-vxworks-static-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-vxworks-static-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-windows-default-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-windows-default-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-windows-openssl_10-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-windows-openssl_10-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-windows-openssl_11-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-windows-openssl_11-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0
projects/goahead-windows-static-me.h:#ifndef ME_GOAHEAD_REPLACE_MALLOC
projects/goahead-windows-static-me.h:    #define ME_GOAHEAD_REPLACE_MALLOC 0

Timeline

2019-08-28 - Vendor Disclosure
2019-11-21 - Vendor patched
2019-12-02 - Public Release

Credit

Discovered by a member of Cisco Talos.