TELCOBREAK
Workshop · DEF CON 34
Challenge 1 · NRF Enumeration · MITRE FiGHT FGT5006

CH1 — Service Catalog

The 5G core's service registry is wide open. Enumerate every Network Function on the core — no credentials required.

FGT5006 · NF Discovery 100 pts Easy NRF HTTP/2 OAuth2 Disabled
1

What Is the NRF?

The service directory — every NF registers here

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.

MITRE FiGHT FGT5006 — Network Function Discovery: This technique describes adversaries querying the NRF to enumerate Network Functions in a 5G core. The prerequisite is network access to the SBI (Service-Based Interface). In this CTF, your WireGuard tunnel provides that access.

2

The Vulnerability

OAuth2 disabled — anyone can query the NRF

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

3GPP TS 33.501 compliant
NRF query authOAuth2 token required
Token issuerNRF (per NF type)
TransportMutual TLS (mTLS)
Who can enumerate NFsOnly authorized NFs
Topology leakNot possible externally
🔓

Your Lab (Open5GS)

Development mode — auth disabled
NRF query authNone — open to all
Token issuerNot running
TransportPlain HTTP/2, no TLS
Who can enumerate NFsAnyone with WG access
Topology leakComplete — IPs, ports, types
This is intentional. Open5GS disables OAuth2 by default so operators can test and debug without certificate management overhead. The lab exposes this deliberately so you can see exactly what an attacker can access when authorization is absent.

3

The Attack

Three curl commands — that is all it takes

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.

HTTP/2 is required: All 5G SBA endpoints run HTTP/2. Plain 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.
1

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).

2

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.

3

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.

Step 1 — GET /nnrf-nfm/v1/nf-instancescurl --http2-prior-knowledge \ http://10.100.200.20:7777/nnrf-nfm/v1/nf-instances # Returns JSON array — scan for "nfType": "CHF" # Note each entry's nfInstanceId UUID
Step 2 — GET /nnrf-nfm/v1/nf-instances/<UUID>curl --http2-prior-knowledge \ http://10.100.200.20:7777/nnrf-nfm/v1/nf-instances/<UUID-from-step-1> # Fetch the full CHF profile — look for "fqdn" field
Step 3 — find TWIN{} in the fqdn of the CHF entry# CHF fqdn will look like: TWIN{abc123def456}.chf.5gc.mnc070.mcc999.3gppnetwork.org # Extract the TWIN{} portion and submit it
Tip — pipe to jq for readable output: The NRF returns compact JSON. Add | python3 -m json.tool or | jq . to your command to pretty-print it. To filter only CHF entries: | jq '.[] | select(.nfType=="CHF")'

4

Real World Impact

What unauthenticated NRF access enables in a real carrier network

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.

CH1 is the entry point to every subsequent challenge. Once you know where each NF lives, you can target the UDR for credential theft (CH2), find the NSSF slice flag (CH3), and understand the full attack surface. Real post-compromise lateral movement in 5G starts exactly here.

5

Flag Format

Where to look and what to submit
CH1 Flag Format
TWIN{xxxxxxxxxxxx}
12 lowercase hexadecimal characters inside the braces.

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.org

Extract 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.
Submission tip: Submit the full TWIN{...} string including braces and the 12 hex characters. Do not include the .chf.5gc.mnc070... suffix — that is just the FQDN wrapper.