open5gs / open5gs

Open5GS is a C-language Open Source implementation for 5G Core and EPC, i.e. the core network of LTE/NR network (Release-17)
https://open5gs.org
GNU Affero General Public License v3.0
1.69k stars 712 forks source link

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

Closed p1-gte closed 1 month ago

p1-gte commented 2 months ago

Open5GS Release, Revision, or Tag

c0a520f32a3c70aefc393f74ced365004fe8be75

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):

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

p1-gte commented 2 months ago

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

acetcom commented 2 months ago

@p1-gte

I've fixed it.

Thank s a lot! Sukchan

github-actions[bot] commented 1 month ago

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.