CH1 — Service Catalog
The 5G core's service registry is wide open. Enumerate every Network Function on the core — no credentials required.
What Is the NRF?
The Network Repository Function (NRF) is the Yellow Pages for the entire 5G core network. When any Network Function starts up — AMF, SMF, UDR, CHF, AUSF — the first thing it does is register itself with the NRF: "I am here, this is my IP and port, these are the APIs I offer." When another NF needs to make a call, it first asks the NRF: "Where is the UDR right now?" and receives back the address. Without the NRF, the core cannot function.
In a production deployment, querying the NRF requires an OAuth2 bearer token — issued by the NRF itself, with specific NF-type claims. This prevents an unauthorized client from learning the network's internal topology. In this lab, OAuth2 is disabled. Anyone with network access can query the NRF and get a complete map of every NF running on the core.
The Vulnerability
The 3GPP specification (TS 33.501) defines a full OAuth2 authorization framework for the SBI. The NRF acts as both registry and token issuer. Every NF must present a valid access token when calling another NF. The NRF itself checks these tokens before returning service profiles. Open5GS in development mode disables all of this.
Production 5G Core
Your Lab (Open5GS)
The Attack
The NRF exposes a standard 3GPP-defined REST endpoint at /nnrf-nfm/v1/nf-instances.
This returns a JSON array of every registered Network Function — their UUIDs, types, IPs, and metadata.
One of those NF entries has something unusual in its fqdn field.
curl defaults to HTTP/1.1 and will
get no response or a connection error. You must pass --http2-prior-knowledge to every
curl command in this CTF. This is the single most common mistake when probing 5G core APIs for the first time.
Enumerate all registered NF instances
Query the NRF's NF Management interface. Returns a JSON array of every NF currently registered — ~11 entries in this lab (10 real NFs + 1 planted decoy).
Walk each NF profile by UUID
Fetch individual NF profiles using the nfInstanceId UUID from step 1. The full profile includes more fields than the list response — including the fqdn field where flags are hidden.
Find the CHF with TWIN{} in its fqdn
One of the NF entries is a fake CHF (Charging Function). Its fqdn field contains the flag encoded as a subdomain: TWIN{abc123def456}.chf.5gc.mnc070.mcc999.3gppnetwork.org. That 12-hex-char portion is what you submit.
| python3 -m json.tool or | jq . to your command to pretty-print it.
To filter only CHF entries: | jq '.[] | select(.nfType=="CHF")'
Real World Impact
In a real carrier 5G core, an adversary who gains internal network access and finds an NRF with OAuth2 disabled can do far more than read a list. The NRF is the entry point to every other attack.
-
Map the entire core network topology Every NF's IP address, port, software version, and capabilities — all returned from a single API call. An attacker immediately knows where the UDR, AUSF, AMF, and SMF live.
-
Register rogue NFs to intercept traffic Because there is no authorization, an attacker can POST a fake NF registration to the NRF. Other NFs will then route traffic through the attacker's system — a man-in-the-middle position inside the core.
-
Target specific NFs for follow-on attacks CH1 gives you the UDR's address. That is all you need for CH2 — query the UDR directly to steal subscriber K keys. The NRF is the reconnaissance step that enables every subsequent exploit.
-
Enumerate network slices The NRF holds NSSF (Network Slice Selection Function) registrations. Filtering by
?nf-type=NSSFreveals internal slice configuration — restricted government or enterprise slices that should not be visible externally. That is exactly what CH3 exploits.
Flag Format
The flag is embedded in the
fqdn field of the CHF NF profile returned by the NRF.
The full fqdn string looks like a valid 3GPP FQDN:
TWIN{xxxxxxxxxxxx}.chf.5gc.mnc070.mcc999.3gppnetwork.orgExtract only the
TWIN{xxxxxxxxxxxx} prefix and submit that as your flag.
The CHF NF type is not a standard NF you would expect to see with an FQDN — that is your hint it is the planted decoy entry.
TWIN{...} string including braces and the 12 hex characters.
Do not include the .chf.5gc.mnc070... suffix — that is just the FQDN wrapper.