Skip to content

Latest commit

 

History

History
199 lines (165 loc) · 13.1 KB

File metadata and controls

199 lines (165 loc) · 13.1 KB

Combined Vulnerability List for MongoDB Go Driver Project

This document combines two discovered vulnerabilities in the MongoDB Go Driver project into a single list, removing any potential duplicates and maintaining the detailed description for each.

  • Vulnerability Name: RawValue Type Confusion Vulnerability in BSON Decoding

    • Description:

      1. An attacker crafts a BSON document where a RawValue element has an invalid Type field (e.g., 0x00 - invalid type).
      2. The attacker sends this crafted BSON document to an application that uses the MongoDB Go Driver and decodes BSON data into Go structs or interfaces that include bson.RawValue fields.
      3. During decoding, the rawValueEncodeValue function in primitive_codecs.go checks if the RawValue.Type is valid using rawvalue.Type.IsValid().
      4. However, if RawValue.Type is invalid (e.g., 0x00), the condition !rawvalue.Type.IsValid() becomes true.
      5. The function incorrectly returns an error: fmt.Errorf("the RawValue Type specifies an invalid BSON type: %#x", byte(rawvalue.Type)).
      6. Crucially, this error is returned during encoding (rawValueEncodeValue), not during decoding (rawValueDecodeValue). The rawValueDecodeValue function, responsible for decoding, does not validate the RawValue.Type after reading it from the BSON stream.
      7. When decoding a BSON document containing this invalid RawValue, the rawValueDecodeValue function in primitive_codecs.go will successfully decode the raw bytes without validating the type.
      8. This allows an attacker to inject arbitrary bytes into a RawValue field, potentially leading to type confusion or unexpected behavior in application code that processes the decoded RawValue.
      9. The vulnerability lies in the inconsistent validation of RawValue.Type - it is validated during encoding but not during decoding, allowing invalid types to be deserialized.
    • Impact:

      • High: Type confusion vulnerability. An attacker can inject arbitrary BSON data, including potentially malicious payloads, into bson.RawValue fields. This could lead to unexpected behavior, data corruption, or potentially escalate to more severe vulnerabilities depending on how the application processes bson.RawValue data.
      • If the application directly uses the RawValue.Value without proper type checking after decoding, it might misinterpret the data, leading to logical errors or security bypasses.
    • Vulnerability Rank: high

    • Currently Implemented Mitigations:

      • None in the rawValueDecodeValue function itself.
      • The rawValueEncodeValue function performs validation, but this is irrelevant for decoding vulnerabilities.
    • Missing Mitigations:

      • Input Validation in rawValueDecodeValue: The rawValueDecodeValue function should validate the RawValue.Type after reading it from the BSON stream, similar to how rawValueEncodeValue does during encoding. If an invalid type is encountered, rawValueDecodeValue should return an error, preventing deserialization of malformed RawValue elements.
    • Preconditions:

      • Application must be using bson.RawValue type in Go structs to represent raw BSON values.
      • Application must be decoding BSON data from untrusted sources (e.g., external input, network requests).
    • Source Code Analysis:

      // code/bson/primitive_codecs.go
      
      // rawValueEncodeValue is the ValueEncoderFunc for RawValue.
      //
      // If the RawValue's Type is "invalid" and the RawValue's Value is not empty or
      // nil, then this method will return an error.
      func rawValueEncodeValue(_ EncodeContext, vw ValueWriter, val reflect.Value) error {
          // ... (validation and encoding logic)
      
          if !rawvalue.Type.IsValid() { // VALIDATION DURING ENCODING
              return fmt.Errorf("the RawValue Type specifies an invalid BSON type: %#x", byte(rawvalue.Type))
          }
      
          return copyValueFromBytes(vw, rawvalue.Type, rawvalue.Value)
      }
      
      // rawValueDecodeValue is the ValueDecoderFunc for RawValue.
      func rawValueDecodeValue(_ DecodeContext, vr ValueReader, val reflect.Value) error {
          // ... (decoding logic)
      
          t, value, err := copyValueToBytes(vr) // READS TYPE FROM BSON STREAM
          if err != nil {
              return err
          }
      
          val.Set(reflect.ValueOf(RawValue{Type: t, Value: value})) // NO VALIDATION OF 't' AFTER DECODING
          return nil
      }

      Visualization:

      graph LR
          A[Crafted BSON with invalid RawValue Type] --> B(Application decodes BSON);
          B --> C{rawValueDecodeValue (primitive_codecs.go)};
          C --> D{Reads Type 't' and Value from BSON stream};
          D --> E{Sets RawValue{Type: t, Value: value}};
          E -- No validation of 't' --> F[RawValue with invalid Type in Go struct];
          F --> G(Application processes RawValue.Value);
          G -- Type confusion/Unexpected behavior --> H[Potential Vulnerability Exploitation];
      
      Loading
    • Security Test Case:

      1. Setup: Create a simple Go application that:

        • Defines a struct containing a bson.RawValue field.
        • Accepts BSON data as input (e.g., from standard input or HTTP request).
        • Unmarshals the BSON data into the struct.
        • Prints the RawValue.Type and RawValue.Value to standard output.
      2. Craft Malicious BSON: Create a hex-encoded BSON document with a RawValue element that has an invalid type byte (0x00) and arbitrary value bytes. For example, a minimal document structure could be:

        \x13\x00\x00\x00  // Document length: 19 bytes
        \xFF            // Invalid Type (0xFF is just an example, 0x00 also works)
        \x00            // ElementName: "" (empty string)
        \x04\x00\x00\x00\x01\x02\x03\x00 // String value: "0x04 0x00 0x00 0x00 0x01 0x02 0x03 0x00" (just example bytes)
        \x00            // Document end
        

        Hex representation of the above BSON: 13000000ff00040000000102030000

      3. Execute Test:

        • Run the Go application.
        • Provide the crafted hex-encoded BSON document as input to the application (e.g., using echo -ne '\x13\x00\x00\x00\xff\x00\x04\x00\x00\x00\x01\x02\x03\x00\x00' | go run your_app.go).
      4. Verification:

        • Observe the output of the Go application.
        • Vulnerability Confirmation: If the application successfully decodes the BSON document without errors and prints the RawValue.Type as invalid (or a similar unexpected type) and the RawValue.Value contains the arbitrary bytes (\x01\x02\x03 in this example), then the vulnerability is confirmed. This indicates that the invalid RawValue.Type was not rejected during decoding.
        • Expected Behavior (Mitigation): If the application throws an error during unmarshaling indicating an invalid BSON type or if the RawValue field is not populated due to a decoding error, then the vulnerability is likely mitigated.
  • Vulnerability Name: Truncated Multi-byte UTF-8 Characters in StringN

    • Description: The StringN function in bsoncore/value.go truncates strings to a specified byte length (n). When truncating multi-byte UTF-8 strings, the truncation might occur in the middle of a multi-byte character, leading to an invalid UTF-8 sequence. This can cause issues when the truncated string is used in contexts where valid UTF-8 is expected, such as display in user interfaces, logging systems, or other downstream systems that rely on valid UTF-8.

      Steps to trigger vulnerability:

      1. Create a BSON string value containing multi-byte UTF-8 characters (e.g., "你好世界").
      2. Call the StringN function on this value with a byte length that truncates a multi-byte character (e.g., length of 4 for "你好世界").
      3. Observe the output string, which will contain an invalid UTF-8 sequence.
    • Impact: The impact of this vulnerability is categorized as high because it can lead to data corruption or misrepresentation when handling UTF-8 strings. Specifically:

      • Data corruption: Truncating a string in the middle of a multi-byte character can result in invalid UTF-8 data. If this corrupted data is persisted or transmitted, it can lead to data corruption issues in downstream systems that expect valid UTF-8.
      • Misrepresentation of data: When displaying or logging the truncated string, the invalid UTF-8 sequence might be rendered incorrectly, leading to misrepresentation of the intended data. This could have security implications if the misrepresented data is used for security decisions or auditing.
    • Vulnerability Rank: high

    • Currently implemented mitigations: There are no mitigations implemented in the StringN function to handle multi-byte character truncation. The function directly truncates the byte slice without considering UTF-8 encoding.

    • Missing mitigations: The StringN function should be updated to truncate strings correctly at UTF-8 character boundaries instead of byte boundaries. This can be achieved by iterating over the string's runes and truncating after a complete rune, ensuring that the resulting string is always valid UTF-8.

    • Preconditions: The following preconditions are necessary to trigger this vulnerability:

      • The application must use the bsoncore library to handle BSON data.
      • The application must use the StringN function to truncate BSON string values.
      • The BSON string values being truncated must contain multi-byte UTF-8 characters.
      • The truncation length must be such that it cuts a multi-byte UTF-8 character in the middle.
    • Source code analysis: The vulnerability exists in the StringN function in /code/x/bsonx/bsoncore/value.go.

      func (v Value) StringN(n int) string {
          if n <= 0 {
              return ""
          }
      
          switch v.Type {
          case TypeString:
              str, ok := v.StringValueOK()
              if !ok {
                  return ""
              }
              str = escapeString(str)
              if len(str) > n {
                  truncatedStr := bsoncoreutil.Truncate(str, n) // Vulnerability is here, byte-based truncation
                  return truncatedStr
              }
              return str
          ...
      }

      The bsoncoreutil.Truncate(str, n) function performs byte-based truncation, which is problematic for UTF-8 strings.

      // Truncate truncates a given string for a certain width
      func Truncate(str string, width int) string {
          if width == 0 {
              return ""
          }
      
          if len(str) <= width {
              return str
          }
      
          // Truncate the byte slice of the string to the given width.
          newStr := str[:width] // Byte-based truncation
      
          ...
      }

      The file /code/internal/integration/clam_prose_test.go includes tests for command logging and monitoring, and it uses a similar truncation function logger.Truncate for logging messages. While this file contains tests to check for multi-byte character handling in logging, the underlying logger.Truncate function, like bsoncoreutil.Truncate, is also byte-based and could potentially lead to invalid UTF-8 sequences in logs if not carefully handled. Although the test clamMultiByteTruncLogs attempts to mitigate this by ensuring the last bytes are part of a multi-byte character, this is not a general solution and might not cover all cases where logging truncation could occur.

    • Security test case:

      1. Create a Go test file (e.g., stringn_vulnerability_test.go) in the same directory as /code/x/bsonx/bsoncore/value.go.
      2. Add a test function TestStringNTruncationVulnerability to this file.
      3. Inside the test function, construct a BSON Value of type string containing multi-byte UTF-8 characters, for example "你好世界".
      4. Call StringN with a truncation length that will split a multi-byte character, e.g., length 4.
      5. Assert that the resulting string is not a valid UTF-8 string, indicating the vulnerability. You can use utf8.ValidString to check for UTF-8 validity.
      package bsoncore
      
      import (
          "testing"
          "unicode/utf8"
      )
      
      func TestStringNTruncationVulnerability(t *testing.T) {
          testString := "你好世界" // Multi-byte UTF-8 string
          val := Value{Type: TypeString, Data: AppendString(nil, testString)}
          truncatedString := val.StringN(4) // Truncate in the middle of multi-byte character
      
          if utf8.ValidString(truncatedString) {
              t.Errorf("Expected invalid UTF-8 string, but got valid UTF-8: %q", truncatedString)
          }
      }

      Run this test case to confirm the vulnerability.