Bug 1218292 (CVE-2023-2794)

Summary: VUL-0: CVE-2023-2794: ofono: SMS Decoder Stack-based Buffer Overflow Remote Code Execution Vulnerability within the decode_deliver() function
Product: [openSUSE] openSUSE Distribution Reporter: SMASH SMASH <smash_bz>
Component: SecurityAssignee: Martin Pluskal <mpluskal>
Status: NEW --- QA Contact: Security Team bot <security-team>
Severity: Major    
Priority: P3 - Medium CC: carlos.lopez
Version: Leap 15.6   
Target Milestone: ---   
Hardware: Other   
OS: Other   
URL: https://smash.suse.de/issue/388807/
Whiteboard:
Found By: Security Response Team Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---

Description SMASH SMASH 2023-12-21 08:32:39 UTC
ofono is a Open Source Telephony on Linux
stack overflow bug is triggered within the decode_deliver() function during SMS decoding
here assumed that the attack scenario is accessible from a compromised modem or possibily accessible from a malicious base station or just SMS

there is a bound check for this memcpy length in decode_submit(), but they forgot it in decode_deliver()
partial code path is here
    - at_cmt_notify()
    - ofono_sms_deliver_notify()
    - sms_decode()
    - decode_deliver()
```

~~~C++
static gboolean decode_deliver(const unsigned char *pdu, int len,
                                struct sms *out)
{
        int offset = 0;
        int expected;
        unsigned char octet;

        out->type = SMS_TYPE_DELIVER;

        if (!next_octet(pdu, len, &offset, &octet))
                return FALSE;

        out->deliver.mms = !is_bit_set(octet, 2);
        out->deliver.sri = is_bit_set(octet, 5);
        out->deliver.udhi = is_bit_set(octet, 6);
        out->deliver.rp = is_bit_set(octet, 7);

        if (!sms_decode_address_field(pdu, len, &offset,
                                        FALSE, &out->deliver.oaddr))
                return FALSE;

        if (!next_octet(pdu, len, &offset, &out->deliver.pid))
                return FALSE;

        if (!next_octet(pdu, len, &offset, &out->deliver.dcs))
                return FALSE;

        if (!sms_decode_scts(pdu, len, &offset, &out->deliver.scts))
                return FALSE;

        if (!next_octet(pdu, len, &offset, &out->deliver.udl))
                return FALSE;

        expected = sms_udl_in_bytes(out->deliver.udl, out->deliver.dcs);

        if ((len - offset) < expected)
                return FALSE;

        memcpy(out->deliver.ud, pdu + offset, expected); 				// overflow here, expected is from SMS PDU

        return TRUE;
}
~~~

ASAN report
```
=================================================================
==116975==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffcf34201bc at pc 0x7f027e049846 bp 0x7ffcf341fea0 sp 0x7ffcf341f648
WRITE of size 203 at 0x7ffcf34201bc thread T0
    #0 0x7f027e049845 in __interceptor_memcpy ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827
    #1 0x556caadab9e3 in decode_deliver src/smsutil.c:782
    #2 0x556caadb14bf in sms_decode src/smsutil.c:1574
    #3 0x556caad4d08d in main src/main.c:225
    #4 0x7f027da2350f in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #5 0x7f027da235c8 in __libc_start_main_impl ../csu/libc-start.c:381
    #6 0x556caaaec274 in _start (/root/ofono/src/ofonod+0x12b274)

Address 0x7ffcf34201bc is located in stack of thread T0 at offset 316 in frame
    #0 0x556caad4cedd in main src/main.c:205

  This frame has 1 object(s):
    [48, 316) 'sms1' (line 212) <== Memory access at offset 316 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ../../../../src/libsanitizer/sanitizer_common/sanitizer_common_interceptors.inc:827 in __interceptor_memcpy
Shadow bytes around the buggy address:
  0x10001e67bfe0: f1 f1 01 f2 04 f3 f3 f3 00 00 00 00 00 00 00 00
  0x10001e67bff0: 00 00 00 00 00 00 00 00 f1 f1 f1 f1 04 f3 f3 f3
  0x10001e67c000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001e67c010: f1 f1 f1 f1 f1 f1 00 00 00 00 00 00 00 00 00 00
  0x10001e67c020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10001e67c030: 00 00 00 00 00 00 00[04]f3 f3 f3 f3 f3 f3 f3 f3
  0x10001e67c040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001e67c050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001e67c060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001e67c070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x10001e67c080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==116975==ABORTING
```

References:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2023-2794
https://bugzilla.redhat.com/show_bug.cgi?id=2255387
https://www.zerodayinitiative.com/advisories/ZDI-23-1861/