Headline
CVE-2023-28391: TALOS-2023-1732 || Cisco Talos Intelligence Group
A memory corruption vulnerability exists in the HTTP Server header parsing functionality of Weston Embedded uC-HTTP v3.01.01. Specially crafted network packets can lead to code execution. An attacker can send a malicious packet to trigger this vulnerability.
SUMMARY
A memory corruption vulnerability exists in the HTTP Server header parsing functionality of Weston Embedded uC-HTTP v3.01.01. Specially crafted network packets can lead to code execution. An attacker can send a malicious packet to trigger this vulnerability.
CONFIRMED VULNERABLE VERSIONS
The versions below were either tested or verified to be vulnerable by Talos or confirmed to be vulnerable by the vendor.
Weston Embedded uC-HTTP v3.01.01
Weston Embedded Cesium NET 3.07.01
Silicon Labs Gecko Platform 4.3.1.0
PRODUCT URLS
uC-HTTP - https://weston-embedded.com/micrium/overview Cesium NET - https://www.weston-embedded.com/cesium-cs-net Gecko Platform - https://www.silabs.com/developers/gecko-software-development-kit
CVSSv3 SCORE
9.0 - CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H
CWE
CWE-119 - Improper Restriction of Operations within the Bounds of a Memory Buffer
DETAILS
The uC-HTTP server implementation is designed to be used on embedded systems that are running the µC/OS II or µC/OS III RTOS kernels. This HTTP server supports many features including persistent connections, form processing, chunked transfer encoding, HTTP header fields processing, HTTP query string processing and dynamic content.
The uC-HTTP server has special handling for the following header fields: Content-Type, Content-Length, Host, Connection. All other supported HTTP header fields are processed by the portion of code containing this vulnerability. When a header field is not equal to one of the previously mentioned fields, it is processed by the default case of a switch statement. When processing the header value, the length is calculated [1] and then checked if it is less than or equal to the configured buffer size [2]. This length value is later used to calculate the pointer value used for NULL termination [3]. If the value of length is exactly equal to the configured size, this results in a one-byte buffer overwrite with the NULL byte [4].
As noted in the mitigations section, this user-defined callback function [0] can be used to disable header field processing.
File: http-s_req.c
1759: default:
1760: #if (HTTPs_CFG_HDR_RX_EN == DEF_ENABLED)
1761: if ((p_cfg->HdrRxCfgPtr != DEF_NULL) &&
1762: (p_cfg->HooksPtr != DEF_NULL)) {
1763: keep = p_cfg->HooksPtr->OnReqHdrRxHook(p_instance, /* [0] */
1764: p_conn,
1765: p_cfg->Hooks_CfgPtr,
1766: field);
...
1776: if (keep == DEF_YES) {
...
1789: p_val = HTTPsReq_HdrParseValGet(p_field,
1790: p_field_dict_entry->StrLen,
1791: p_field_end,
1792: &len); /* [1] */
...
1796: if (len > p_cfg->HdrRxCfgPtr->DataLenMax) { /* [2] */
1797: HTTPs_ERR_INC(p_ctr_errs->Req_ErrHdrDataLenInv);
1798: *p_err = HTTPS_ERR_REQ_HDR_INVALID_VAL_LEN;
1799: return;
1800: }
...
1807: p_str = (CPU_CHAR *)p_req_hdr_blk->ValPtr + len; /* [3] */
1808: *p_str = ASCII_CHAR_NULL; /* [4] */
1809: p_req_hdr_blk->ValLen = len + 1;
Because of the memory layout implemented by the uC-LIB Memory Library, this one-byte overwrite results in an arbitrary allocation controlled by the attacker, which could be used to gain code execution as explained below.
When a heap object is freed using uC-LIB Memory Mem_DynPoolBlkFree, the pointer to the next free chunk of memory within that pool is stored in the first 4 bytes of that memory block [0].
File: lib_mem.c
2072: void Mem_DynPoolBlkFree (MEM_DYN_POOL *p_pool,
2073: void *p_blk,
2074: LIB_ERR *p_err)
2075: {
...
2109: *((void **)p_blk) = p_pool->BlkFreePtr; /* [0] */
So, when this NULL byte overwrite occurs and the following heap block has been allocated and freed previously, this will overwrite the least significant byte of the next free pointer address. It is possible for the attacker to influence allocations such that when overwriting the least significant byte, the new pointer address will point to a buffer containing attacker-controlled data. When this happens, on the next allocation of the heap pool which contains the corrupted free pointer, that same corrupt pointer will be dereferenced and stored in the pool object as the next free pointer [1]. This dereferenced value is attacker-controlled, since the corrupted pointer now points to an attacker-controlled buffer as a result of this vulnerability. On the next call to Mem_DynPoolBlkGet, the dereferenced attacker-controlled value will be the pointer which is allocated [0]. The result of this is that the attacker has the ability to allocate memory at an arbitrary address. The impact of an attacker being able to allocate an arbitrary address is that now the attacker can write data anywhere in the program memory space, which could lead to things like overwriting stack data or a function pointer in order to gain code execution.
File: lib_mem.c
1978: void *Mem_DynPoolBlkGet (MEM_DYN_POOL *p_pool,
1979: LIB_ERR *p_err)
1980: {
...
2014: p_blk = p_pool->BlkFreePtr; /* [0] */
2015: p_pool->BlkFreePtr = *((void **)p_blk); /* [1] */
Crash Information
Program received signal SIGSEGV, Segmentation fault.
0x5656942a in Mem_DynPoolBlkGet (p_pool=0x56576578 <Mem_Heap+408>, p_err=0xffffd3bc) at uc-lib/lib_mem.c:2015
2015 p_pool->BlkFreePtr = *((void **)p_blk);
(gdb) i r
eax 0x41414141 1094795585
ecx 0x56577223 1448571427
edx 0x2 2
ebx 0x56575f64 1448566628
esp 0xffffd370 0xffffd370
ebp 0xffffd388 0xffffd388
esi 0xf7f91000 -134672384
edi 0xf7f91000 -134672384
eip 0x5656942a 0x5656942a <Mem_DynPoolBlkGet+124>
eflags 0x10206 [ PF IF RF ]
cs 0x23 35
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x0 0
gs 0x63 99
k0 0x0 0
k1 0x0 0
k2 0x0 0
k3 0x0 0
k4 0x0 0
k5 0x0 0
k6 0x0 0
k7 0x0 0
(gdb) bt
#0 0x5656942a in Mem_DynPoolBlkGet (p_pool=0x56576578 <Mem_Heap+408>, p_err=0xffffd3bc) at uc-lib/lib_mem.c:2015
#1 0x56563f36 in HTTPsMem_ReqHdrGet (p_instance=0x565763fc <Mem_Heap+28>, p_conn=0x56576928 <Mem_Heap+1352>,
hdr_field=HTTP_HDR_FIELD_ACCEPT_ENCODING, val_type=HTTP_HDR_VAL_TYPE_STR_DYN, p_err=0xffffd48c)
at Server/Source/http-s_mem.c:2141
#2 0x5655a1f2 in HTTPsReq_HdrParse (p_instance=0x565763fc <Mem_Heap+28>, p_conn=0x56576928 <Mem_Heap+1352>, p_err=0xffffd48c)
at Server/Source/http-s_req.c:1780
#3 0x56558c49 in HTTPsReq_Handle (p_instance=0x565763fc <Mem_Heap+28>, p_conn=0x56576928 <Mem_Heap+1352>)
at Server/Source/http-s_req.c:325
#4 0x5655c97a in HTTPsConn_Process (p_instance=0x565763fc <Mem_Heap+28>) at Server/Source/http-s_conn.c:166
#5 0x5655ecfc in HTTPsTask_InstanceTaskHandler (p_instance=0x565763fc <Mem_Heap+28>) at Server/Source/http-s_task.c:814
#6 0x5655ea62 in HTTPsTask_InstanceTask (p_data=0x565763fc <Mem_Heap+28>) at Server/Source/http-s_task.c:653
#7 0x5656680d in KAL_TaskCreate (task_handle=..., p_fnct=0x5655ea3d <HTTPsTask_InstanceTask>,
p_task_arg=0x565763fc <Mem_Heap+28>, prio=17 '\021', p_cfg=0x0, p_err=0xffffd5e0) at uc-shims/Source/kal-shim.c:59
#8 0x5655e781 in HTTPsTask_InstanceTaskCreate (p_instance=0x565763fc <Mem_Heap+28>, p_err=0xffffd654)
at Server/Source/http-s_task.c:331
#9 0x5655c179 in HTTPs_InstanceStart (p_instance=0x565763fc <Mem_Heap+28>, p_err=0xffffd654) at Server/Source/http-s.c:812
#10 0x56557e2b in main (argc=1, argv=0xffffd714) at server_app.c:118
(gdb)
Mitigation
This vulnerability could be mitigated by making use of the application-specific callback function OnReqHdrRxHook, which is called HTTPs_ReqHdrRxHook in this example. A user could prevent this vulnerability from being triggered by blocking the processing of any unnecessary header fields by the HTTP server. Example code to mitigate this vulnerability is below:
/*
*********************************************************************************************************
* HTTPs_ReqHdrRxHook()
*
* Description : Called each time a header field is parsed in a request message. Allows to choose which
* additional header field(s) need to be processed by the upper application.
*
* Argument(s) : p_instance Pointer to the HTTPs instance object.
*
* p_conn Pointer to the HTTPs connection object.
*
* p_hook_cfg Pointer to hook configuration object.
*
* hdr_field Type of the header field received.
* See the HTTPs_HDR_FIELD declaration in http-s.h file for all the header types supported.
*
* Return(s) : DEF_YES, If the header field needs to be process.
* DEF_NO, Otherwise.
*
* Caller(s) : HTTPs_ReqHdrParse() via 'p_cfg->HooksPtr->OnReqHdrRxHook()'.
*
* Note(s) : (1) The instance structure is for read-only. It MUST NOT be modified.
*
* (2) The connection structure SHOULD NOT be modified. It should be only read to determine if the header
* type must be stored.
*********************************************************************************************************
*/
static CPU_BOOLEAN HTTPs_ReqHdrRxHook (const HTTPs_INSTANCE *p_instance,
const HTTPs_CONN *p_conn,
const void *p_hook_cfg,
HTTP_HDR_FIELD hdr_field)
{
return (DEF_NO);
}
Another mitigation option is to modify the code within uC-HTTP itself. An example bugfix is below, where the length is not allowed to be equal to the configured size of the buffer. Example bugfix below:
diff --git a/Server/Source/http-s_req.c b/Server/Source/http-s_req.c
index d487160..33ccf57 100644
--- a/Server/Source/http-s_req.c
+++ b/Server/Source/http-s_req.c
@@ -1793,7 +1793,7 @@ static void HTTPsReq_HdrParse (HTTPs_INSTANCE *p_instance,
if (p_val != DEF_NULL) {
len = p_field_end - p_val;
- if (len > p_cfg->HdrRxCfgPtr->DataLenMax) {
+ if (len >= p_cfg->HdrRxCfgPtr->DataLenMax) {
HTTPs_ERR_INC(p_ctr_errs->Req_ErrHdrDataLenInv);
*p_err = HTTPS_ERR_REQ_HDR_INVALID_VAL_LEN;
return;
TIMELINE
2023-03-29 - Vendor Disclosure
2023-06-23 - Vendor Patch Release
2023-11-14 - Public Release
Discovered by Kelly Leuschner of Cisco Talos.
Related news
Adobe recently patched two use-after-free vulnerabilities in its Acrobat PDF reader that Talos discovered, both of which could lead to arbitrary code execution.