Modern embedded and IoT devices require compact and efficient solutions to deliver seamless user interfaces and remote management capabilities, often achieved through HTTP servers. Implementing an HTTP server is a challenging task, due to the need to balance multiple factors, including performance, security, and adaptability. These requirements, combined with the need to save costs in development, have led vendors to opt for lightweight standard solutions, like GoAhead by EmbedThis, to avoid reinventing the wheel every time a new product needs to be shipped.
As embedded systems and IoT devices become increasingly prevalent, ensuring their security is essential. Recognizing this, Nozomi Networks Labs has analyzed version 6.0.0 of the GoAhead Web Server, uncovering several vulnerabilities that resulted in three CVEs being issued. Impacts associated with these vulnerabilities could primarily affect web servers’ availability in case the affected features are embedded in specific implementations. A new patch (version 6.0.1) has been released in the past months by EmbedThis to mitigate these threats.
This article details the discovered security vulnerabilities, discusses their potential impacts, and provides suggested mitigation strategies. For a complete overview of affected targets, please refer to the below section “Vulnerability List and Affected Versions.”
Research Scope
GoAhead, developed by EmbedThis, is a compact web server tailored for embedded systems and IoT devices. It is built with a focus on minimizing resource usage while delivering high performance, making it an ideal solution for devices with limited memory and processing power. GoAhead is used in a wide array of products, such as smart home devices, networking equipment and industrial control systems, due to its easy integration, extensibility and flexibility (manifold architectures are supported, such as ARM, MIPS, X86, PPC, and Sparc). Figure 1 illustrates many well-known manufacturers that incorporate it into their products.
Our research targeted GoAhead server’s functionalities, including HTTP request handling, input parsing and session management due to their critical role in mediating interactions between external users and the device, making them potential points of exploitation. By analyzing these areas, we uncovered several memory corruption issues tracked under three CVEs as detailed further in this blog.
What Are the Impacts of These Vulnerabilities?
Before discussing impacts associated with the discovered vulnerabilities, it is important to underline that, since GoAhead is a highly customizable web server, the reported issues might not be present in all adaptations of these web servers and mostly depend on specific functionalities enabled by developers (as detailed in section “Vulnerability List and Affected Versions”). When determining the CVSS scores associated to these vulnerabilities, particular consideration was given to these factors.
With these premises, the most immediate observable effect is a Denial of Service (DoS) condition, which interrupts the normal operation of the web server and may require a device restart to restore functionality. Furthermore, GoAhead operates as a single-threaded web server, which means that in the event of a memory access violation, the entire process will be immediately terminated (in contrast, a multithreaded server could intercept a segmentation fault signal and handle the situation more gracefully). Depending on the specific implementation, such an impact might of course be limited if additional mechanisms, such as watchdogs, are in place to automatically restart the service when a crash is detected. On the other hand, these very same mechanisms sometimes have policies that prevent automatic restart of a process after a specific number of failures, potentially leaving the service down after repeated issues.
Vulnerability List and Affected Versions
The following table lists all vulnerabilities found in GoAhead Web Server version 6.0.0. The ordering has been determined by CVSS v3.1 base score. Please carefully review the specific affected functionalities outlined below the table to more accurately assess the potential impact on web servers.
The vulnerabilities were found in two optional functionalities, described below:
- The first one is the Alternate Allocator implemented by EmbedThis. It is a custom, application-specific dynamic memory allocator designed to replace the standard libc functions (such as malloc and free). It is particularly beneficial when the default operating system allocator experiences high memory fragmentation: the GoAhead allocator is deterministic and performs memory allocation and deallocation in constant time. It is also recommended in those scenarios where embedded systems cannot easily incorporate the standard Glibc library. This custom implementation can be enabled in GoAhead projects by setting the
ME_GOAHEAD_REPLACE_MALLOC=1
compilation flag. - The second one is the Javascript Templates (JST) feature, further explored in the “Vulnerability Spotlight” section below. This feature can be enabled by developers by setting the
ME_GOAHEAD_JAVASCRIPT=1
flag at compilation time.
Vulnerability Spotlight
The majority of the issues reported, tracked under CVE-2024-3187 and CVE-2024-3186, were discovered in the context of the Javascript Templates (JST) functionality.
GoAhead implements Javascript Templates to facilitate the creation of dynamic web pages and applications by utilizing HTML pages that execute embedded Javascript on the server before being rendered back to the client. The JST environment is extensible and allows direct binding of C functions to Javascript, enabling JST web pages to seamlessly access device or system data. A JST document is a textual resource on the filesystem that has a .jst
extension and is processed by a corresponding JST handler. When implementing a web server, developers can enable the JST extension by adding a new entry under the “/etc/goahead/route.txt
” file as displayed in Figure 2.
JST template files are stored under the /var/www/goahead/jst/
directory and their content can be as simple as the one displayed below.
By default, JST only defines one standard function: write
. This function writes data back to the client in place of the JST script. Developers can also implement new JST functions via websDefineJst
to bind a custom operation defined in C to a Javascript function.
For example, below is presented the definition of a new date()
function accessible through JST.
The developer can now leverage the new date()
function to return the corresponding information to the client.
When a user's browser requests a JST document, the JST handler is triggered to process the request. The document is read from the file system in a single pass. Any text before JST delimiters is sent directly to the client. When JST delimiters are encountered, the script within them is executed, and the resulting output is sent to the client. This process repeats until the entire document is processed.
During our analysis, we decided to adopt well-known open-source fuzzing solutions like AFL++ to perform coverage-guided attempts against the JST document processing functionality. To better spot less apparent memory corruptions such as Use-After-Frees (UAFs) and Double Frees, the Address Sanitizer (ASAN) feature available in modern compilers such as Clang and GCC has been enabled over the targets. Finally, to simplify triaging efforts over discovered crashes, symbols were enabled over the final build.
To instrument the target, instead of writing a harness specifically focusing over the parsing functionality, an alternative approach was adopted. Starting from the main goahead.c file, additional code has been inserted to read a payload from STDIN, save the payload to a JST file and trigger the correct server endpoint that is responsible for loading and parsing the template. This additional code was implemented as part of a separate thread and the loading operation is triggered after the server completes its initialization. Although this approach has the clear downside of reducing the amount of fuzz tests per second since more code is involved for one payload, it has two main advantages:
- It guarantees that all discovered crashes (with the exception of duplicates) were legitimate ones, since all the code involved in loading and parsing the template is executed. This prevents those scenarios where, after investing additional time to create a fully working example application to test the entire flow, it is later discovered that some additional checks are in place to prevent malformed inputs.
- It immediately allows us to correctly set up and initialize all complex web server data structures, to provide a good starting point from a memory layout perspective to further investigate obtained crashes and better understand associated impacts.
In Figure 3, readers can observe a snippet of one of the crashes obtained as a consequence of a Double-Free vulnerability, detected by ASAN after running the fuzzing campaign.
Further triaging on this specific crash through GDB led to the result displayed in Figure 4. By inspecting the memory address that is being passed as argument to the wfree
function (1), it is possible to observe that it matches the one of a memory chunk that has been previously freed (2) by another portion of code. Since this chunk was already inserted as part of a 0x20-tcache list for chunks <= 0x18 in size, additional security checks implemented over tcache bins in Glibc versions >= 2.29 prevent the program execution from continuing and raise a Double-Free error violation since the allocator is in an inconsistent state.
Of course, the behavior of the process may vary greatly depending on whether the target is compiled with older versions of Glibc or when alternative libc implementations, such as uClibc, are used. However, for this specific scenario, no easily exploitable conditions have been discovered to immediately take control of the execution flow.
Because this attack requires control over a JST resource stored in the file system, a potential attack vector could involve exploiting another vulnerability that allows arbitrary file uploads to the JST templates folder. This would enable an attacker to inject a malicious JST resource and initiate its loading and parsing by accessing the corresponding route.
Remediations
To fix these vulnerabilities, EmbedThis promptly released version 6.0.1 of GoAhead. Customers are encouraged to ensure that their projects use a version that includes the latest security patches released by the vendor. If immediate updates are not possible, it is advisable to assess the potential presence of these vulnerabilities by verifying whether the ME_GOAHEAD_REPLACE_MALLOC
compilation flag is enabled, or the JavaScript Templates (JST) functionality is in use. For this second condition, we also recommend conducting an in-depth review to determine whether malicious users can tamper with dynamic Javascript templates, as this could lead to unintended behaviors during document loading and parsing.