From d1d3ec6fcbada437bb28d4ab47398e41880d7dde Mon Sep 17 00:00:00 2001 From: Sukchan Lee Date: Sat, 3 Feb 2024 10:37:36 +0900 Subject: [PATCH] [SEC] Several vulnerabilities have been resolved. 1. Reachable assertion in ogs_nas_5gmm_decode Location: lib/nas/5gs/decoder.c:4445 ```c int ogs_nas_5gmm_decode(ogs_nas_5gs_message_t *message, ogs_pkbuf_t *pkbuf) { int size = 0; int decoded = 0; ogs_assert(pkbuf); ogs_assert(pkbuf->data); ogs_assert(pkbuf->len); ``` When a NAS payload is received over `src/amf/context.c:1675`NGAP that has no data, the ogs_assert(pkbuf->len) assertion will be triggered. 2.Reachable assertion in ogs_nas_emm_decode ``` int ogs_nas_emm_decode(ogs_nas_eps_message_t *message, ogs_pkbuf_t *pkbuf) { int size = 0; int decoded = 0; ogs_assert(pkbuf); ogs_assert(pkbuf->data); ogs_assert(pkbuf->len); ``` Nearly identical to (1), but for LTE. 3. Reachable assertion in nas_eps_send_emm_to_esm ``` int nas_eps_send_emm_to_esm(mme_ue_t *mme_ue, ogs_nas_esm_message_container_t *esm_message_container) { int rv; ogs_pkbuf_t *esmbuf = NULL; if (!mme_ue_cycle(mme_ue)) { ogs_error("UE(mme-ue) context has already been removed"); return OGS_NOTFOUND; } ogs_assert(esm_message_container); ogs_assert(esm_message_container->length); ``` The ESM message payload may be 0-length, as the length is determined by a field in the NAS payload (which can be chosen arbitrarily by an attacker). This leads to the length assertion above being triggered. 5. Reachable assertion and incorrect hash calculation in ogs_kdf_hash_mme ``` void ogs_kdf_hash_mme(const uint8_t *message, uint8_t message_len, uint8_t *hash_mme) { uint8_t key[32]; uint8_t output[OGS_SHA256_DIGEST_SIZE]; ogs_assert(message); ogs_assert(message_len); ogs_assert(hash_mme); memset(key, 0, 32); ogs_hmac_sha256(key, 32, message, message_len, output, OGS_SHA256_DIGEST_SIZE); memcpy(hash_mme, output+24, OGS_HASH_MME_LEN); } ``` When handling NAS attach requests or TAU requests, the ogs_kdf_hash_mme function is passed the NAS payload. However, the length field is represented as an unsigned 8-bit integer, which the passed length of the packet may overflow. This leads to the passed value being truncated. When the passed value is a multiple of 256, the above assertion (ogs_assert(message_len)) is triggered. Otherwise, the hash is computed on only the first n bits of the message (where n = actual_message_len % 256). --- lib/crypt/ogs-kdf.c | 3 ++- lib/crypt/ogs-kdf.h | 3 ++- lib/nas/5gs/decoder.c | 12 +++++------- lib/nas/5gs/encoder.c | 2 +- lib/nas/5gs/ies.c | 2 +- lib/nas/5gs/ies.h | 2 +- lib/nas/5gs/message.h | 2 +- lib/nas/5gs/support/nas-message.py | 10 ++++------ lib/nas/eps/decoder.c | 12 +++++------- lib/nas/eps/encoder.c | 2 +- lib/nas/eps/ies.c | 2 +- lib/nas/eps/ies.h | 2 +- lib/nas/eps/message.h | 2 +- lib/nas/eps/support/nas-message.py | 10 ++++------ src/mme/nas-path.c | 9 ++++++--- 15 files changed, 36 insertions(+), 39 deletions(-) diff --git a/lib/crypt/ogs-kdf.c b/lib/crypt/ogs-kdf.c index 17ee7c7e3..fd670cb10 100644 --- a/lib/crypt/ogs-kdf.c +++ b/lib/crypt/ogs-kdf.c @@ -463,7 +463,8 @@ void ogs_kdf_ck_ik_idle_mobility( * TS33.401 Annex I Hash Functions * Use the KDF given in TS33.220 */ -void ogs_kdf_hash_mme(const uint8_t *message, uint8_t message_len, uint8_t *hash_mme) +void ogs_kdf_hash_mme( + const uint8_t *message, uint32_t message_len, uint8_t *hash_mme) { uint8_t key[32]; uint8_t output[OGS_SHA256_DIGEST_SIZE]; diff --git a/lib/crypt/ogs-kdf.h b/lib/crypt/ogs-kdf.h index 8bc260582..b87c3ae26 100644 --- a/lib/crypt/ogs-kdf.h +++ b/lib/crypt/ogs-kdf.h @@ -121,7 +121,8 @@ void ogs_kdf_ck_ik_idle_mobility( * TS33.401 Annex I Hash Functions * Use the KDF given in TS33.220 */ -void ogs_kdf_hash_mme(const uint8_t *message, uint8_t message_len, uint8_t *hash_mme); +void ogs_kdf_hash_mme( + const uint8_t *message, uint32_t message_len, uint8_t *hash_mme); /* * TS33.102 diff --git a/lib/nas/5gs/decoder.c b/lib/nas/5gs/decoder.c index c03e529ec..096dd5d73 100644 --- a/lib/nas/5gs/decoder.c +++ b/lib/nas/5gs/decoder.c @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.2.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-04 20:50:00.889117 by acetcom + * Created on: 2024-01-21 18:47:47.827076 by acetcom * from 24501-h90.docx ******************************************************************************/ @@ -4449,15 +4449,14 @@ int ogs_nas_5gmm_decode(ogs_nas_5gs_message_t *message, ogs_pkbuf_t *pkbuf) ogs_assert(pkbuf); ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_5gs_message_t)); size = sizeof(ogs_nas_5gmm_header_t); if (ogs_pkbuf_pull(pkbuf, size) == NULL) { ogs_error("ogs_pkbuf_pull() failed [size:%d]", (int)size); return OGS_ERROR; } + + memset(message, 0, sizeof(ogs_nas_5gs_message_t)); memcpy(&message->gmm.h, pkbuf->data - size, size); decoded += size; @@ -4710,15 +4709,14 @@ int ogs_nas_5gsm_decode(ogs_nas_5gs_message_t *message, ogs_pkbuf_t *pkbuf) ogs_assert(pkbuf); ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_5gs_message_t)); size = sizeof(ogs_nas_5gsm_header_t); if (ogs_pkbuf_pull(pkbuf, size) == NULL) { ogs_error("ogs_pkbuf_pull() failed [size:%d]", (int)size); return OGS_ERROR; } + + memset(message, 0, sizeof(ogs_nas_5gs_message_t)); memcpy(&message->gsm.h, pkbuf->data - size, size); decoded += size; diff --git a/lib/nas/5gs/encoder.c b/lib/nas/5gs/encoder.c index 000ca7136..4383c3592 100644 --- a/lib/nas/5gs/encoder.c +++ b/lib/nas/5gs/encoder.c @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.2.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-04 20:50:00.898995 by acetcom + * Created on: 2024-01-21 18:47:47.837341 by acetcom * from 24501-h90.docx ******************************************************************************/ diff --git a/lib/nas/5gs/ies.c b/lib/nas/5gs/ies.c index ce04d556f..79d78117e 100644 --- a/lib/nas/5gs/ies.c +++ b/lib/nas/5gs/ies.c @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.2.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-04 20:50:00.874596 by acetcom + * Created on: 2024-01-21 18:47:47.812038 by acetcom * from 24501-h90.docx ******************************************************************************/ diff --git a/lib/nas/5gs/ies.h b/lib/nas/5gs/ies.h index 9073223a9..08f87555d 100644 --- a/lib/nas/5gs/ies.h +++ b/lib/nas/5gs/ies.h @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.2.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-04 20:50:00.872007 by acetcom + * Created on: 2024-01-21 18:47:47.809393 by acetcom * from 24501-h90.docx ******************************************************************************/ diff --git a/lib/nas/5gs/message.h b/lib/nas/5gs/message.h index fe4607d5e..ae3932b6a 100644 --- a/lib/nas/5gs/message.h +++ b/lib/nas/5gs/message.h @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.2.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-04 20:50:00.882958 by acetcom + * Created on: 2024-01-21 18:47:47.820801 by acetcom * from 24501-h90.docx ******************************************************************************/ diff --git a/lib/nas/5gs/support/nas-message.py b/lib/nas/5gs/support/nas-message.py index c0ea0d9dc..cc279fa9b 100644 --- a/lib/nas/5gs/support/nas-message.py +++ b/lib/nas/5gs/support/nas-message.py @@ -732,15 +732,14 @@ f.write("""int ogs_nas_5gmm_decode(ogs_nas_5gs_message_t *message, ogs_pkbuf_t * ogs_assert(pkbuf); ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_5gs_message_t)); size = sizeof(ogs_nas_5gmm_header_t); if (ogs_pkbuf_pull(pkbuf, size) == NULL) { ogs_error("ogs_pkbuf_pull() failed [size:%d]", (int)size); return OGS_ERROR; } + + memset(message, 0, sizeof(ogs_nas_5gs_message_t)); memcpy(&message->gmm.h, pkbuf->data - size, size); decoded += size; @@ -779,15 +778,14 @@ f.write("""int ogs_nas_5gsm_decode(ogs_nas_5gs_message_t *message, ogs_pkbuf_t * ogs_assert(pkbuf); ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_5gs_message_t)); size = sizeof(ogs_nas_5gsm_header_t); if (ogs_pkbuf_pull(pkbuf, size) == NULL) { ogs_error("ogs_pkbuf_pull() failed [size:%d]", (int)size); return OGS_ERROR; } + + memset(message, 0, sizeof(ogs_nas_5gs_message_t)); memcpy(&message->gsm.h, pkbuf->data - size, size); decoded += size; diff --git a/lib/nas/eps/decoder.c b/lib/nas/eps/decoder.c index 4cd4bf1d0..f455ff2a0 100644 --- a/lib/nas/eps/decoder.c +++ b/lib/nas/eps/decoder.c @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-02 22:57:51.860294 by acetcom + * Created on: 2024-01-21 18:50:03.417367 by acetcom * from 24301-h90.docx ******************************************************************************/ @@ -4691,15 +4691,14 @@ int ogs_nas_emm_decode(ogs_nas_eps_message_t *message, ogs_pkbuf_t *pkbuf) ogs_assert(pkbuf); ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_eps_message_t)); size = sizeof(ogs_nas_emm_header_t); if (ogs_pkbuf_pull(pkbuf, size) == NULL) { ogs_error("ogs_pkbuf_pull() failed [size:%d]", (int)size); return OGS_ERROR; } + + memset(message, 0, sizeof(ogs_nas_eps_message_t)); memcpy(&message->emm.h, pkbuf->data - size, size); decoded += size; @@ -4975,15 +4974,14 @@ int ogs_nas_esm_decode(ogs_nas_eps_message_t *message, ogs_pkbuf_t *pkbuf) ogs_assert(pkbuf); ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_eps_message_t)); size = sizeof(ogs_nas_esm_header_t); if (ogs_pkbuf_pull(pkbuf, size) == NULL) { ogs_error("ogs_pkbuf_pull() failed [size:%d]", (int)size); return OGS_ERROR; } + + memset(message, 0, sizeof(ogs_nas_eps_message_t)); memcpy(&message->esm.h, pkbuf->data - size, size); decoded += size; diff --git a/lib/nas/eps/encoder.c b/lib/nas/eps/encoder.c index ed39e82d6..2fdefcd64 100644 --- a/lib/nas/eps/encoder.c +++ b/lib/nas/eps/encoder.c @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-02 22:57:51.871237 by acetcom + * Created on: 2024-01-21 18:50:03.428897 by acetcom * from 24301-h90.docx ******************************************************************************/ diff --git a/lib/nas/eps/ies.c b/lib/nas/eps/ies.c index f36fc71b1..8144341b8 100644 --- a/lib/nas/eps/ies.c +++ b/lib/nas/eps/ies.c @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-02 22:57:51.846548 by acetcom + * Created on: 2024-01-21 18:50:03.402793 by acetcom * from 24301-h90.docx ******************************************************************************/ diff --git a/lib/nas/eps/ies.h b/lib/nas/eps/ies.h index 5235f3a8d..4e4b797ec 100644 --- a/lib/nas/eps/ies.h +++ b/lib/nas/eps/ies.h @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-02 22:57:51.844510 by acetcom + * Created on: 2024-01-21 18:50:03.400537 by acetcom * from 24301-h90.docx ******************************************************************************/ diff --git a/lib/nas/eps/message.h b/lib/nas/eps/message.h index 058f3b997..424f174d1 100644 --- a/lib/nas/eps/message.h +++ b/lib/nas/eps/message.h @@ -28,7 +28,7 @@ /******************************************************************************* * This file had been created by nas-message.py script v0.1.0 * Please do not modify this file but regenerate it via script. - * Created on: 2023-03-02 22:57:51.852650 by acetcom + * Created on: 2024-01-21 18:50:03.409367 by acetcom * from 24301-h90.docx ******************************************************************************/ diff --git a/lib/nas/eps/support/nas-message.py b/lib/nas/eps/support/nas-message.py index 421238888..1bfd6efaa 100644 --- a/lib/nas/eps/support/nas-message.py +++ b/lib/nas/eps/support/nas-message.py @@ -747,15 +747,14 @@ f.write("""int ogs_nas_emm_decode(ogs_nas_eps_message_t *message, ogs_pkbuf_t *p ogs_assert(pkbuf); ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_eps_message_t)); size = sizeof(ogs_nas_emm_header_t); if (ogs_pkbuf_pull(pkbuf, size) == NULL) { ogs_error("ogs_pkbuf_pull() failed [size:%d]", (int)size); return OGS_ERROR; } + + memset(message, 0, sizeof(ogs_nas_eps_message_t)); memcpy(&message->emm.h, pkbuf->data - size, size); decoded += size; @@ -806,15 +805,14 @@ f.write("""int ogs_nas_esm_decode(ogs_nas_eps_message_t *message, ogs_pkbuf_t *p ogs_assert(pkbuf); ogs_assert(pkbuf->data); - ogs_assert(pkbuf->len); - - memset(message, 0, sizeof(ogs_nas_eps_message_t)); size = sizeof(ogs_nas_esm_header_t); if (ogs_pkbuf_pull(pkbuf, size) == NULL) { ogs_error("ogs_pkbuf_pull() failed [size:%d]", (int)size); return OGS_ERROR; } + + memset(message, 0, sizeof(ogs_nas_eps_message_t)); memcpy(&message->esm.h, pkbuf->data - size, size); decoded += size; diff --git a/src/mme/nas-path.c b/src/mme/nas-path.c index 36836e0e4..c31e41f1c 100644 --- a/src/mme/nas-path.c +++ b/src/mme/nas-path.c @@ -50,14 +50,17 @@ int nas_eps_send_emm_to_esm(mme_ue_t *mme_ue, int rv; ogs_pkbuf_t *esmbuf = NULL; + ogs_assert(esm_message_container); + if (!esm_message_container->length) { + ogs_error("Invalid ESM Message Container"); + return OGS_ERROR; + } + if (!mme_ue_cycle(mme_ue)) { ogs_error("UE(mme-ue) context has already been removed"); return OGS_NOTFOUND; } - ogs_assert(esm_message_container); - ogs_assert(esm_message_container->length); - /* The Packet Buffer(pkbuf_t) for NAS message MUST make a HEADROOM. * When calculating AES_CMAC, we need to use the headroom of the packet. */ esmbuf = ogs_pkbuf_alloc(NULL,