Skip to content

Commit

Permalink
[AMF/MME] NAS message in an invaild state (open5gs#3131)
Browse files Browse the repository at this point in the history
In InitialUEMessage, send a NAS message with a message type
other than Registration Request, Deregistration Request, or Service Request,
the following messages from UE will not be accepted.

We found this issue in not only the initial state but multiple states.
We believe if an attacker has the ability to inject a NAS message to the core,
it can perform a DoS attack on the victim UE.

So, I've fixed that The MME/AMF deletes MME_UE_S1AP_ID/AMF_UE_NGAP_ID,
and will not accept any following messages from the UE.
  • Loading branch information
acetcom committed Apr 13, 2024
1 parent cd76dc6 commit 3cfa8ba
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 8 deletions.
31 changes: 31 additions & 0 deletions src/amf/ngap-path.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,19 +200,47 @@ int ngap_send_to_nas(ran_ue_t *ran_ue,
default:
ogs_error("Not implemented(security header type:0x%x)",
sh->security_header_type);
ran_ue_remove(ran_ue);
return OGS_ERROR;
}

if (ran_ue->amf_ue) {
if (nas_5gs_security_decode(ran_ue->amf_ue,
security_header_type, nasbuf) != OGS_OK) {
ogs_error("nas_eps_security_decode failed()");
ran_ue_remove(ran_ue);
return OGS_ERROR;
}
}

h = (ogs_nas_5gmm_header_t *)nasbuf->data;
ogs_assert(h);
if (procedureCode == NGAP_ProcedureCode_id_InitialUEMessage) {
if (h->extended_protocol_discriminator !=
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GMM) {

ogs_error("Invalid extended_protocol_discriminator [%d]",
h->extended_protocol_discriminator);

ogs_pkbuf_free(nasbuf);
ran_ue_remove(ran_ue);

return OGS_ERROR;
}

if (h->message_type != OGS_NAS_5GS_REGISTRATION_REQUEST &&
h->message_type != OGS_NAS_5GS_SERVICE_REQUEST &&
h->message_type != OGS_NAS_5GS_DEREGISTRATION_REQUEST_FROM_UE) {

ogs_error("Invalid 5GMM message type [%d]", h->message_type);

ogs_pkbuf_free(nasbuf);
ran_ue_remove(ran_ue);

return OGS_ERROR;
}
}

if (h->extended_protocol_discriminator ==
OGS_NAS_EXTENDED_PROTOCOL_DISCRIMINATOR_5GMM) {
e = amf_event_new(AMF_EVENT_5GMM_MESSAGE);
Expand Down Expand Up @@ -247,7 +275,10 @@ int ngap_send_to_nas(ran_ue_t *ran_ue,
} else {
ogs_error("Unknown NAS Protocol discriminator 0x%02x",
h->extended_protocol_discriminator);

ogs_pkbuf_free(nasbuf);
ran_ue_remove(ran_ue);

return OGS_ERROR;
}
}
Expand Down
12 changes: 4 additions & 8 deletions src/mme/s1ap-handler.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,10 +586,8 @@ void s1ap_handle_initial_ue_message(mme_enb_t *enb, ogs_s1ap_message_t *message)
enb_ue->enb_ue_s1ap_id, enb_ue->mme_ue_s1ap_id,
enb_ue->saved.tai.tac, enb_ue->saved.e_cgi.cell_id);

r = s1ap_send_to_nas(enb_ue,
S1AP_ProcedureCode_id_initialUEMessage, NAS_PDU);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
ogs_expect(OGS_OK == s1ap_send_to_nas(
enb_ue, S1AP_ProcedureCode_id_initialUEMessage, NAS_PDU));
}

void s1ap_handle_uplink_nas_transport(
Expand Down Expand Up @@ -777,10 +775,8 @@ void s1ap_handle_uplink_nas_transport(
ogs_error("No UE Context in UplinkNASTransport");
}

r = s1ap_send_to_nas(enb_ue,
S1AP_ProcedureCode_id_uplinkNASTransport, NAS_PDU);
ogs_expect(r == OGS_OK);
ogs_assert(r != OGS_ERROR);
ogs_expect(OGS_OK == s1ap_send_to_nas(
enb_ue, S1AP_ProcedureCode_id_uplinkNASTransport, NAS_PDU));
}

void s1ap_handle_ue_capability_info_indication(
Expand Down
34 changes: 34 additions & 0 deletions src/mme/s1ap-path.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,50 @@ int s1ap_send_to_nas(enb_ue_t *enb_ue,
default:
ogs_error("Not implemented(security header type:0x%x)",
sh->security_header_type);
enb_ue_remove(enb_ue);
return OGS_ERROR;
}

if (enb_ue->mme_ue) {
if (nas_eps_security_decode(enb_ue->mme_ue,
security_header_type, nasbuf) != OGS_OK) {
ogs_error("nas_eps_security_decode failed()");
enb_ue_remove(enb_ue);
return OGS_ERROR;
}
}

h = (ogs_nas_emm_header_t *)nasbuf->data;
ogs_assert(h);

if (procedureCode == S1AP_ProcedureCode_id_initialUEMessage) {
if (h->protocol_discriminator != OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM) {

ogs_error("Invalid protocol_discriminator [%d]",
h->protocol_discriminator);

ogs_pkbuf_free(nasbuf);
enb_ue_remove(enb_ue);

return OGS_ERROR;
}

if (h->security_header_type !=
OGS_NAS_SECURITY_HEADER_FOR_SERVICE_REQUEST_MESSAGE &&
h->message_type != OGS_NAS_EPS_ATTACH_REQUEST &&
h->message_type != OGS_NAS_EPS_TRACKING_AREA_UPDATE_REQUEST &&
h->message_type != OGS_NAS_EPS_EXTENDED_SERVICE_REQUEST &&
h->message_type != OGS_NAS_EPS_DETACH_REQUEST) {

ogs_error("Invalid EMM message type [%d]", h->message_type);

ogs_pkbuf_free(nasbuf);
enb_ue_remove(enb_ue);

return OGS_ERROR;
}
}

if (h->protocol_discriminator == OGS_NAS_PROTOCOL_DISCRIMINATOR_EMM) {
int rv;
e = mme_event_new(MME_EVENT_EMM_MESSAGE);
Expand Down Expand Up @@ -255,7 +286,10 @@ int s1ap_send_to_nas(enb_ue_t *enb_ue,
} else {
ogs_error("Unknown/Unimplemented NAS Protocol discriminator 0x%02x",
h->protocol_discriminator);

ogs_pkbuf_free(nasbuf);
enb_ue_remove(enb_ue);

return OGS_ERROR;
}
}
Expand Down
4 changes: 4 additions & 0 deletions tests/attach/issues-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -1862,6 +1862,7 @@ static void issues_2287_v264_func(abts_case *tc, void *data)
test_ue_remove_all();
}

#if 0 /* Deprecated to resolve issue #3131 */
static void pull_3122_v270_func(abts_case *tc, void *data)
{
int rv;
Expand Down Expand Up @@ -1973,6 +1974,7 @@ static void pull_3122_v270_func(abts_case *tc, void *data)

test_ue_remove(test_ue);
}
#endif

abts_suite *test_issues(abts_suite *suite)
{
Expand All @@ -1981,7 +1983,9 @@ abts_suite *test_issues(abts_suite *suite)
abts_run_test(suite, issues_1431_func, NULL);
abts_run_test(suite, issues_2287_v263_func, NULL);
abts_run_test(suite, issues_2287_v264_func, NULL);
#if 0 /* Deprecated to resolve issue #3131 */
abts_run_test(suite, pull_3122_v270_func, NULL);
#endif

return suite;
}
4 changes: 4 additions & 0 deletions tests/registration/identity-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ static void test1_func(abts_case *tc, void *data)
test_ue_remove(test_ue);
}

#if 0 /* Deprecated to resolve issue #3131 */
static void pull_3122_v270_func(abts_case *tc, void *data)
{
int rv;
Expand Down Expand Up @@ -469,13 +470,16 @@ static void pull_3122_v270_func(abts_case *tc, void *data)
/* Clear Test UE Context */
test_ue_remove(test_ue);
}
#endif

abts_suite *test_identity(abts_suite *suite)
{
suite = ADD_SUITE(suite)

abts_run_test(suite, test1_func, NULL);
#if 0 /* Deprecated to resolve issue #3131 */
abts_run_test(suite, pull_3122_v270_func, NULL);
#endif

return suite;
}

0 comments on commit 3cfa8ba

Please sign in to comment.