open5gs icon indicating copy to clipboard operation
open5gs copied to clipboard

[Bug]: Heap overflow in open5gs-mmed over s6a interface, in Update-Location-Answer and Insert-Subscriber-Data

Open p1-gte opened this issue 1 year ago • 1 comments

Open5GS Release, Revision, or Tag

c0a520f32a3c70aefc393f74ced365004fe8be75

Steps to reproduce

  1. Start open5gs using build/tests/app/epc -c build/configs/volte.yaml, and allow an additional Diameter peer to connect to the MME
  2. Make sure a subscriber with IMSI 999700000000001 exists
  3. Attach subscriber with IMSI 999700000000001 to the network
  4. Send an s6a IDR with an offending MSISDN AVP to the MME. The attached capture capture.pcap.gz contains the malicious message in frame.number == 96

Logs

No response

Expected behaviour

An assert shall be triggered

Observed Behaviour

No assert is triggered. The vulnerable code path is in src/mme/mme-fd-path.c:

/* s6a process Subscription-Data from avp */
static int mme_s6a_subscription_data_from_avp(struct avp *avp,
    ogs_subscription_data_t *subscription_data,
    mme_ue_t *mme_ue, uint32_t *subdatamask)
{
...
    /* AVP: 'MSISDN'( 701 )
     * The MSISDN AVP is of type OctetString. This AVP contains an MSISDN,
     * in international number format as described in ITU-T Rec E.164 [8],
     * encoded as a TBCD-string, i.e. digits from 0 through 9 are encoded
     * 0000 to 1001; 1111 is used as a filler when there is an odd number
     * of digits; bits 8 to 5 of octet n encode digit 2n; bits 4 to 1 of
     * octet n encode digit 2(n-1)+1.
     * Reference: 3GPP TS 29.329
     */
    ret = fd_avp_search_avp(avp, ogs_diam_s6a_msisdn, &avpch1);
    ogs_assert(ret == 0);
    if (avpch1) {
        ret = fd_msg_avp_hdr(avpch1, &hdr);
        ogs_assert(ret == 0);
        if (hdr->avp_value->os.data && hdr->avp_value->os.len) {
            mme_ue->msisdn_len = hdr->avp_value->os.len;                /* 1 */
            memcpy(mme_ue->msisdn, hdr->avp_value->os.data,
                    ogs_min(mme_ue->msisdn_len, OGS_MAX_MSISDN_LEN));   /* 2 */
            ogs_buffer_to_bcd(mme_ue->msisdn,
                    mme_ue->msisdn_len, mme_ue->msisdn_bcd);            /* 3 */
            *subdatamask = (*subdatamask | OGS_DIAM_S6A_SUBDATA_MSISDN);
        }
    }
  1. The tainted length copied is mme_ue->msisdn_len
  2. The data copied to mme_ue->msisdn is capped by the maximum length of the target buffer mme_ue->msisdn, which is OGS_MAX_MSISDN_LEN: this is correct
  3. ogs_buffer_to_bcd will convert BCD to binary, but uses the tainted length rather than the capped length, resulting in an overflow of mme_ue->msisdn: this is wrong, and the destination may be overflown when mme_ue->msisdn_len > OGS_MAX_MSISDN_LEN

The same holds for AVP: 'A-MSISDN'(1643).

This function looks reachable from two tainted paths:

  • static void mme_s6a_ula_cb(void *data, struct msg **msg): called when mme receives an ULA from HSS
  • static int mme_ogs_diam_s6a_idr_cb( struct msg **msg, struct avp *avp, struct session *session, void *opaque, enum disp_action *act): called when mme receives an ISD

eNodeB/gNodeB

No response

UE Models and versions

No response

p1-gte avatar Apr 21 '24 09:04 p1-gte

@p1-gte

I've fixed it in the main branch.

Thanks a lot! Sukchan

acetcom avatar May 01 '24 05:05 acetcom

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.

github-actions[bot] avatar May 31 '24 22:05 github-actions[bot]