Reach the Internal Service: Internal Network Recon from a Shell
The challenge
You have a shell on web01. Somewhere on the internal network a monitoring service is running that the public internet can't reach - but you can, from inside. Find it, get past its token check, and read what it leaks.
What you'll learn
- Understand why an internal-only service trusts callers that already sit inside the network perimeter
- Use nmap from a foothold to discover hosts and open ports the public internet cannot reach
- Recover hardcoded secrets from a compiled binary with strings when they are absent from config files
- Replay a discovered access token with curl to read what an authenticated endpoint returns
- Connect this internal-trust pattern to how SSRF abuses the same network boundary
Skills tested
Prerequisites
- Comfort with a basic Unix shell (ls, cat, cd)
- Familiarity with HTTP requests and query-string parameters
- Awareness that compiled binaries embed plaintext strings
How it works
Once you have a shell on a host inside a network, you inherit that host's reach. A monitoring or health service that is firewalled off from the public internet is still wide open to anything running on a machine that already lives on the internal subnet. That is the whole point of the exercise: the service was never meant to be exposed, so its designers leaned on the network boundary as the only thing keeping attackers out. The moment you land a foothold, that boundary is behind you.
This is the exact trust that a Server-Side Request Forgery vulnerability abuses from the outside. SSRF tricks a public-facing server into making requests on your behalf, so requests arrive from inside the perimeter and hit services that assume any internal caller is friendly. Here you are simply doing it directly: you are the internal caller. The internal service does ask for a token, but a token check is only as strong as the secrecy of the token - and tokens have a habit of ending up somewhere they can be read.
The second lesson is about where secrets hide. A config file might politely tell you it does not hold the secret, but the agent that talks to the service has to know the token to send it. If that token was compiled into the shipped binary, it sits there in plaintext alongside the URL it gets appended to. A compiled program is not an opaque vault; it is a file full of readable strings.
Common mistakes
- Assuming an internal service is safe because the internet cannot reach it - the firewall does nothing once you are calling from inside the subnet.
- Giving up after reading the config file, which openly states the token is not stored there, instead of looking at the agent binary sitting right next to it.
- Forgetting to scan the internal range at all and trying to guess the service's port instead of letting nmap report the open one.
- Hitting the endpoint without the token and stopping at the 401 response, rather than recovering the credential and replaying the request.
How to defend against it
Treating the network boundary as your only authentication is the root mistake. An internal service should still verify who is calling it, not just where the call came from. Network segmentation is a useful layer, but it must sit on top of real per-caller authentication, not replace it.
- Authenticate every caller with short-lived, per-client credentials issued by a secrets manager - never a single shared static token.
- Keep secrets out of shipped artifacts: inject them at runtime via environment variables or a vault, so a leaked binary leaks nothing. Run
stringson your own builds before release to confirm. - Rotate any token the moment a host is compromised, and scope each token so a leaked one unlocks the minimum.
- Apply zero-trust principles internally: mutual TLS or signed requests between services so an attacker on one host cannot freely query the next.