Skip to content

Latest commit

 

History

History
79 lines (64 loc) · 5.33 KB

File metadata and controls

79 lines (64 loc) · 5.33 KB

Combined Vulnerability List

This document outlines a format string vulnerability identified in the error formatting logic of the application.

Vulnerability: Format String Vulnerability in Error Formatting

  • Description: The ListFormatFunc in format.go, the default error formatter for multierror.Error, uses fmt.Sprintf to format each error within the error list. If an error string within a multierror.Error contains format specifiers (e.g., %s, %v, %x), these specifiers are interpreted by fmt.Sprintf. This behavior results in a format string vulnerability, potentially leading to information disclosure or unexpected program behavior. An attacker who can control the error messages added to a multierror.Error could exploit this vulnerability when the error message is displayed or logged.

  • Impact: Information Disclosure. A malicious actor could craft specific error messages containing format specifiers to potentially leak sensitive information from the application's memory or internal state. In less critical scenarios, this could result in malformed error messages or program crashes if invalid format strings are used.

  • Vulnerability Rank: High

  • Currently implemented mitigations: None. The code directly uses fmt.Sprintf within the ListFormatFunc without any input sanitization or escaping of error strings, leaving the system vulnerable to format string injection.

  • Missing mitigations: To mitigate this vulnerability, it is crucial to sanitize or escape error strings before they are processed by fmt.Sprintf in ListFormatFunc. This could involve replacing format specifiers with their escaped equivalents or using a safer formatting approach that does not interpret format specifiers in the error messages. For example, using the %q format specifier in fmt.Sprintf would escape the error strings, preventing the interpretation of format specifiers.

  • Preconditions:

    • An attacker needs the ability to influence or control the content of error messages that are subsequently added to a multierror.Error instance. This could occur when error messages are generated based on user input or external data.
    • The Error() method of the multierror.Error object must be invoked, and the resulting error string must be utilized in a context where the attacker can observe it. Common examples include logging systems, error responses in APIs, or displayed error messages in user interfaces.
    • The application must be using the default ListFormatFunc or a custom ErrorFormatFunc that unsafely employs fmt.Sprintf to format error messages without proper sanitization.
  • Source code analysis:

    • In the file /code/format.go, the ListFormatFunc is defined as follows:
      func ListFormatFunc(es []error) string {
          if len(es) == 1 {
              return fmt.Sprintf("1 error occurred:\n\t* %s\n\n", es[0])
          }
      
          points := make([]string, len(es))
          for i, err := range es {
              points[i] = fmt.Sprintf("* %s", err) // Vulnerable line
          }
      
          return fmt.Sprintf(
              "%d errors occurred:\n\t%s\n\n",
              len(es), strings.Join(points, "\n\t"))
      }
      The line points[i] = fmt.Sprintf("* %s", err) is the source of the vulnerability. It uses the %s format specifier to incorporate the error string err.Error() into the formatted output. If err.Error() itself contains format specifiers, fmt.Sprintf will interpret them, leading to the format string vulnerability.
    • In /code/multierror.go, the Error() method is defined to use ListFormatFunc as the default formatter:
      func (e *Error) Error() string {
          fn := e.ErrorFormat
          if fn == nil {
              fn = ListFormatFunc // Default formatter
          }
      
          return fn(e.Errors)
      }
      This confirms that by default, ListFormatFunc is used to format the error message, and therefore, the format string vulnerability is present by default.
  • Security test case:

    1. Create a Go file named main.go with the following content:
      package main
      
      import (
          "errors"
          "fmt"
          "github.com/hashicorp/go-multierror"
      )
      
      func main() {
          var multiErr *multierror.Error
          payloadErr := errors.New("Format string: %s%s") // Error with format specifiers
          multiErr = multierror.Append(multiErr, payloadErr)
          errorString := multiErr.Error() // Get the formatted error string
          fmt.Println(errorString)       // Print the error string
      }
    2. Open a terminal, navigate to the directory containing main.go, and run the program using go run main.go.
    3. Observe the output in the terminal. If the output is similar to:
      1 error occurred:
      	* Format string: %!s(MISSING)%!s(MISSING)
      
      This indicates that fmt.Sprintf has interpreted %s%s as format specifiers, even though no arguments were provided for them, thus confirming the format string vulnerability. If the output is exactly 1 error occurred:\n\t* Format string: %s%s\n\n, then the vulnerability is not present or the test case is not correctly demonstrating it. However, based on the code analysis, the interpretation of %s%s is expected, confirming the vulnerability.