From 048a74005bf524d2bf186000e85876540d8868f9 Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Tue, 30 Apr 2024 22:09:18 +0900 Subject: [PATCH] [SEC] Heap overflow in parse PLMN-ID (#3154) An assert shall be triggered if sepp_node is corrupted. ``` pwndbg> p *sepp_node $5 = { lnode = { prev = 0x0, next = 0xaaaac920c638 }, receiver = 0xaaaac9230990 "sepp2.localdomain", negotiated_security_scheme = OpenAPI_security_capability_TLS, target_apiroot_supported = true, plmn_id = {{ mcc1 = 6 '\006', mcc2 = 6 '\006', mcc3 = 6 '\006', mnc1 = 6 '\006', mnc2 = 6 '\006', mnc3 = 6 '\006' } }, num_of_plmn_id = 6710887, target_plmn_id_presence = false, target_plmn_id = { mcc1 = 0 '\000', mcc2 = 0 '\000', mcc3 = 0 '\000', mnc1 = 0 '\000', mnc2 = 0 '\000', mnc3 = 0 '\000' }, supported_features = 1, sm = { init = 0xaaaaada181fc , fini = 0xaaaaada18390 , state = 0xaaaaada194b4 }, t_establish_interval = 0xffffa7d6c4e0, client = 0xaaaac91af010, n32f = { client = 0xaaaac91af090 } } pwndbg> p/x sepp_node.num_of_plmn_id $6 = 0x666667 ``` --- .github/workflows/meson-ci.yml | 2 +- lib/sbi/nnrf-handler.c | 38 +++++++++++++++++++++++++++++++--- src/sepp/n32c-handler.c | 16 ++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/.github/workflows/meson-ci.yml b/.github/workflows/meson-ci.yml index 971850c5b..13e0c4fe2 100644 --- a/.github/workflows/meson-ci.yml +++ b/.github/workflows/meson-ci.yml @@ -35,7 +35,7 @@ jobs: sudo ifconfig lo0 alias 127.0.0.20 netmask 255.255.255.255 sudo ifconfig lo0 alias 127.0.1.10 netmask 255.255.255.255 - name: Install the dependencies for building the source code. - run: brew install mongo-c-driver libidn libmicrohttpd nghttp2 bison libusrsctp libtins talloc meson + run: brew install mongo-c-driver libgcrypt libidn libmicrohttpd nghttp2 bison libusrsctp libtins talloc meson - name: Check out repository code uses: actions/checkout@main - name: Setup Meson Build diff --git a/lib/sbi/nnrf-handler.c b/lib/sbi/nnrf-handler.c index cd94fd395..8be207994 100644 --- a/lib/sbi/nnrf-handler.c +++ b/lib/sbi/nnrf-handler.c @@ -54,6 +54,15 @@ void ogs_nnrf_nfm_handle_nf_register( OpenAPI_list_for_each(NFProfile->plmn_list, node) { OpenAPI_plmn_id_t *PlmnId = node->data; if (PlmnId) { + if (ogs_local_conf()->num_of_serving_plmn_id >= + OGS_ARRAY_SIZE(ogs_local_conf()->serving_plmn_id)) { + ogs_error("OVERFLOW NFProfile->plmn_list [%d:%d:%d]", + ogs_local_conf()->num_of_serving_plmn_id, + OGS_MAX_NUM_OF_PLMN, + (int)OGS_ARRAY_SIZE( + ogs_local_conf()->serving_plmn_id)); + break; + } ogs_sbi_parse_plmn_id( &ogs_local_conf()->serving_plmn_id[ ogs_local_conf()->num_of_serving_plmn_id], PlmnId); @@ -96,6 +105,13 @@ void ogs_nnrf_nfm_handle_nf_profile( OpenAPI_list_for_each(NFProfile->plmn_list, node) { OpenAPI_plmn_id_t *PlmnId = node->data; if (PlmnId) { + if (nf_instance->num_of_plmn_id >= + OGS_ARRAY_SIZE(nf_instance->plmn_id)) { + ogs_error("OVERFLOW NFProfile->plmn_list [%d:%d:%d]", + nf_instance->num_of_plmn_id, OGS_MAX_NUM_OF_PLMN, + (int)OGS_ARRAY_SIZE(nf_instance->plmn_id)); + break; + } ogs_sbi_parse_plmn_id( &nf_instance->plmn_id[nf_instance->num_of_plmn_id], PlmnId); nf_instance->num_of_plmn_id++; @@ -467,8 +483,12 @@ static void handle_smf_info( TaiRangeItem = node->data; if (TaiRangeItem && TaiRangeItem->plmn_id && TaiRangeItem->tac_range_list) { - ogs_assert(nf_info->smf.num_of_nr_tai_range < - OGS_MAX_NUM_OF_TAI); + + if (nf_info->smf.num_of_nr_tai_range >= OGS_MAX_NUM_OF_TAI) { + ogs_error("OVERFLOW TaiRangeItem [%d:%d]", + nf_info->smf.num_of_nr_tai_range, OGS_MAX_NUM_OF_TAI); + break; + } ogs_sbi_parse_plmn_id( &nf_info->smf.nr_tai_range @@ -709,7 +729,13 @@ static void handle_amf_info( TaiItem = node->data; if (TaiItem && TaiItem->plmn_id && TaiItem->tac) { ogs_5gs_tai_t *nr_tai = NULL; - ogs_assert(nf_info->amf.num_of_nr_tai < OGS_MAX_NUM_OF_TAI); + + if (nf_info->amf.num_of_nr_tai >= OGS_MAX_NUM_OF_TAI) { + ogs_error("OVERFLOW TaiItem [%d:%d]", + nf_info->amf.num_of_nr_tai, OGS_MAX_NUM_OF_TAI); + break; + } + nr_tai = &nf_info->amf.nr_tai[nf_info->amf.num_of_nr_tai]; ogs_assert(nr_tai); ogs_sbi_parse_plmn_id(&nr_tai->plmn_id, TaiItem->plmn_id); @@ -726,6 +752,12 @@ static void handle_amf_info( ogs_assert(nf_info->amf.num_of_nr_tai_range < OGS_MAX_NUM_OF_TAI); + if (nf_info->amf.num_of_nr_tai_range >= OGS_MAX_NUM_OF_TAI) { + ogs_error("OVERFLOW TaiRangeItem [%d:%d]", + nf_info->amf.num_of_nr_tai_range, OGS_MAX_NUM_OF_TAI); + break; + } + ogs_sbi_parse_plmn_id( &nf_info->amf.nr_tai_range [nf_info->amf.num_of_nr_tai_range].plmn_id, diff --git a/src/sepp/n32c-handler.c b/src/sepp/n32c-handler.c index 7c4a9a8a5..0a091eaf0 100644 --- a/src/sepp/n32c-handler.c +++ b/src/sepp/n32c-handler.c @@ -118,6 +118,14 @@ bool sepp_n32c_handshake_handle_security_capability_request( OpenAPI_list_for_each(SecNegotiateReqData->plmn_id_list, node) { OpenAPI_plmn_id_t *PlmnId = node->data; if (PlmnId) { + if (sepp_node->num_of_plmn_id >= + OGS_ARRAY_SIZE(sepp_node->plmn_id)) { + ogs_error("OVERFLOW SecNegotiateReqData->plmn_id_list " + "[%d:%d:%d]", + sepp_node->num_of_plmn_id, OGS_MAX_NUM_OF_PLMN, + (int)OGS_ARRAY_SIZE(sepp_node->plmn_id)); + break; + } ogs_sbi_parse_plmn_id( &sepp_node->plmn_id[sepp_node->num_of_plmn_id], PlmnId); sepp_node->num_of_plmn_id++; @@ -185,6 +193,14 @@ bool sepp_n32c_handshake_handle_security_capability_response( OpenAPI_list_for_each(SecNegotiateRspData->plmn_id_list, node) { OpenAPI_plmn_id_t *PlmnId = node->data; if (PlmnId) { + if (sepp_node->num_of_plmn_id >= + OGS_ARRAY_SIZE(sepp_node->plmn_id)) { + ogs_error("OVERFLOW SecNegotiateRspData->plmn_id_list " + "[%d:%d:%d]", + sepp_node->num_of_plmn_id, OGS_MAX_NUM_OF_PLMN, + (int)OGS_ARRAY_SIZE(sepp_node->plmn_id)); + break; + } ogs_sbi_parse_plmn_id( &sepp_node->plmn_id[sepp_node->num_of_plmn_id], PlmnId); sepp_node->num_of_plmn_id++;