open5gs
open5gs copied to clipboard
[Bug]: Heap overflow in open5gs-mmed over s6a interface, in Update-Location-Answer and Insert-Subscriber-Data
Open5GS Release, Revision, or Tag
c0a520f32a3c70aefc393f74ced365004fe8be75
Steps to reproduce
- Start open5gs using
build/tests/app/epc -c build/configs/volte.yaml, and allow an additional Diameter peer to connect to the MME - Make sure a subscriber with IMSI
999700000000001exists - Attach subscriber with IMSI
999700000000001to the network - Send an s6a IDR with an offending
MSISDNAVP to the MME. The attached capture capture.pcap.gz contains the malicious message inframe.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);
}
}
- The tainted length copied is
mme_ue->msisdn_len - The data copied to
mme_ue->msisdnis capped by the maximum length of the target buffermme_ue->msisdn, which isOGS_MAX_MSISDN_LEN: this is correct -
ogs_buffer_to_bcdwill convert BCD to binary, but uses the tainted length rather than the capped length, resulting in an overflow ofmme_ue->msisdn: this is wrong, and the destination may be overflown whenmme_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
I've fixed it in the main branch.
Thanks a lot! Sukchan
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.