Skip to content

Fluent Bit Memory Corruption via Trace API

Critical
edsiper published GHSA-5rjf-prwh-pp7q May 22, 2024

Package

No package listed

Affected versions

< 3.0.3

Patched versions

None

Description

A researcher associated with Tenable has discovered a memory corruption vulnerability in Fluent Bit v3.0.3 and prior. This issue lies in the embedded http server’s parsing of trace requests and may result in remote code execution. We have reserved CVE-2024-4323 for this issue and will be assigning a CVSSv3.1 vector of AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H with a base score of 9.8.

During the parsing of incoming requests for the “trace” api endpoint, types of input names are not properly validated before being parsed. They are incorrectly assumed to be valid MSGPACK_OBJECT_STRs. This can be seen here: https://github.com/fluent/fluent-bit/blob/master/src/http_server/api/v1/trace.c#L527

By passing non-string values in the “inputs” array of requests, such as integer values, it is possible to cause a variety of memory corruption issues that could lead to RCE. During the flb_sds_create_len() function that assigns the input_name variable, the values passed when an int is supplied happen to be a pointer to the beginning of the inputs array and the integer itself as the “size” of the value.

For some examples, passing …

  • … large integer values (or a negative value) can cause a crash due to a “wild copy” in a later call to memcpy() when it attempts to write to protect memory.
  • … negative values between 1 and 16 can cause heap overwrites of adjacent memory.
  • … integer values not large enough to crash can cause disclosure of adjacent memory to the client making the request.
  • … a value of “-17” will cause a crash due to a null pointer dereference after a failed malloc() of zero later in the code.
  • … smaller and more targeted integer values can trigger a variety of stack corruption and other memory corruption issues, such as corrupted chunks and broken links in the heap management mechanisms.

Sample proof of concept:

Request to trace endpoint:

# python3 -c 'print("{\"output\":\"stdout\", \"params\": {\"format\": \"json\"},\"inputs\":[\"" + "A"*8 + "\"," + str(0xffffffff) + ", \"" + "B"*500 + "\"]}")' > test
# curl -v http://<target>:2020/api/v1/traces/ -H "Content-Type: application/json" -H "Expect: " --data "@test"

Crashed instance:
flbcrash

While we are not intimately familiar with the fluent-bit codebase, we believe that a possible solution to this issue would be to move lines 527 and 528 (https://github.com/fluent/fluent-bit/blob/master/src/http_server/api/v1/trace.c#L527) into the else block that follows them. An alternative could also be to add an additional type check prior to parsing the input_name.

Sample patch:

@@ -524,8 +524,6 @@ static void cb_traces(mk_request_t *request, void *data)
     msgpack_pack_map(&mp_pck, inputs->size);

     for (i = 0; i < inputs->size; i++) {
-        input_name = flb_sds_create_len(inputs->ptr[i].via.str.ptr, inputs->ptr[i].via.str.size);
-        msgpack_pack_str_with_body(&mp_pck, input_name, flb_sds_len(input_name));

         if (inputs->ptr[i].type != MSGPACK_OBJECT_STR) {
             msgpack_pack_map(&mp_pck, 1);
@@ -533,6 +531,9 @@ static void cb_traces(mk_request_t *request, void *data)
             msgpack_pack_str_with_body(&mp_pck, "error", strlen("error"));
         }
         else {
+            input_name = flb_sds_create_len(inputs->ptr[i].via.str.ptr, inputs->ptr[i].via.str.size);
+            msgpack_pack_str_with_body(&mp_pck, input_name, flb_sds_len(input_name));
+
             if (request->method == MK_METHOD_POST || request->method == MK_METHOD_GET) {
                 ret = msgpack_params_enable_trace((struct flb_hs *)data, &result, input_name);
                 if (ret != 0) {

This issue appears to have been introduced in version 2.0.7 in the following commit: 60bd877

Tenable follows a 90-day vulnerability disclosure policy. That means, even though we prefer coordinated disclosure, we’ll issue an advisory on July 29, 2024 with or without a patch. Alternatively, any uncoordinated vendor release of a patch or advisory to any customers before the 90-day deadline will be considered public disclosure, and Tenable may release an advisory prior to the coordinated disclosure date. Please read the full details of our policy here: https://static.tenable.com/research/tenable-vulnerability-disclosure-policy.pdf

Thank you for taking the time to read this. We'd greatly appreciate it if you'd acknowledge receipt of this report. If you have any questions we'd be happy to address them.

Severity

Critical

CVSS overall score

This score calculates overall vulnerability severity from 0 to 10 and is based on the Common Vulnerability Scoring System (CVSS).
/ 10

CVSS v3 base metrics

Attack vector
Network
Attack complexity
Low
Privileges required
None
User interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

CVSS v3 base metrics

Attack vector: More severe the more the remote (logically and physically) an attacker can be in order to exploit the vulnerability.
Attack complexity: More severe for the least complex attacks.
Privileges required: More severe if no privileges are required.
User interaction: More severe when no user interaction is required.
Scope: More severe when a scope change occurs, e.g. one vulnerable component impacts resources in components beyond its security scope.
Confidentiality: More severe when loss of data confidentiality is highest, measuring the level of data access available to an unauthorized user.
Integrity: More severe when loss of data integrity is the highest, measuring the consequence of data modification possible by an unauthorized user.
Availability: More severe when the loss of impacted component availability is highest.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H

CVE ID

No known CVE

Weaknesses

No CWEs

Credits