backport of: From a76d9c2b105a335cc1ad538ac041f619c4bb1f79 Mon Sep 17 00:00:00 2001 From: Gerald Combs <gerald@wireshark.org> Date: Wed, 12 Jul 2023 16:02:52 -0700 Subject: [PATCH] CBOR: Add a recursion check Fixes #19144 (cherry picked from commit 76719d21eb1aff3ae8d2d4536d9dc118107631b4) --- epan/dissectors/packet-cbor.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/epan/dissectors/packet-cbor.c b/epan/dissectors/packet-cbor.c index 9c03716fd28..99407983f05 100644 --- a/epan/dissectors/packet-cbor.c +++ b/epan/dissectors/packet-cbor.c @@ -18,6 +18,7 @@ #include <epan/packet.h> #include <epan/expert.h> +#include <epan/proto_data.h> void proto_register_cbor(void); void proto_reg_handoff_cbor(void); @@ -58,6 +59,7 @@ static gint ett_cbor_float_simple = -1; static expert_field ei_cbor_invalid_minor_type = EI_INIT; static expert_field ei_cbor_invalid_element = EI_INIT; static expert_field ei_cbor_too_long_length = EI_INIT; +static expert_field ei_cbor_max_recursion_depth_reached = EI_INIT; static dissector_handle_t cbor_handle; @@ -237,6 +239,7 @@ dissect_cbor_negative_integer(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbo } } +#define CBOR_MAX_RECURSION_DEPTH 10 // Arbitrary static proto_item * dissect_cbor_byte_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tree, gint *offset, guint8 type_minor) { @@ -288,7 +291,15 @@ dissect_cbor_byte_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tre return NULL; } + unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor); + if (++recursion_depth >= CBOR_MAX_RECURSION_DEPTH) { + proto_tree_add_expert(subtree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0); + return FALSE; + } + p_set_proto_depth(pinfo, proto_cbor, recursion_depth); + elem = dissect_cbor_byte_string(tvb, pinfo, subtree, offset, eof_type & 0x1f); + p_set_proto_depth(pinfo, proto_cbor, recursion_depth - 1); if (!elem) return NULL; } @@ -361,7 +372,15 @@ dissect_cbor_text_string(tvbuff_t *tvb, packet_info *pinfo, proto_tree *cbor_tre return NULL; } + unsigned recursion_depth = p_get_proto_depth(pinfo, proto_cbor); + if (++recursion_depth >= CBOR_MAX_RECURSION_DEPTH) { + proto_tree_add_expert(subtree, pinfo, &ei_cbor_max_recursion_depth_reached, tvb, 0, 0); + return FALSE; + } + + p_set_proto_depth(pinfo, proto_cbor, recursion_depth); elem = dissect_cbor_text_string(tvb, pinfo, subtree, offset, eof_type & 0x1f); + p_set_proto_depth(pinfo, proto_cbor, recursion_depth - 1); if (!elem) return NULL; } @@ -1065,6 +1088,8 @@ proto_register_cbor(void) { "cbor.invalid_element", PI_MALFORMED, PI_WARN, "Invalid element", EXPFILL }}, { &ei_cbor_too_long_length, { "cbor.too_long_length", PI_MALFORMED, PI_WARN, "Too long length", EXPFILL }}, + { &ei_cbor_max_recursion_depth_reached, + { "cbor.max_recursion_depth_reached", PI_PROTOCOL, PI_WARN, "Maximum allowed recursion depth reached. Dissection stopped.", EXPFILL }}, }; expert_module_t *expert_cbor; -- GitLab