Lab 3.1 - Network Discovery
Ran Nmap against a /24 lab network: identified 7 live hosts, enumerated services (OpenSSH, MySQL, nginx, php-fpm), attempted OS fingerprinting, baselined results to XML, and used ndiff to catch a newly exposed Python WSGI server on port 8000. Confirmed the finding by SSHing in and reviewing netstat, iptables, and the served page.
Commands
1. Lab environment startup
Launched the lab stack from /sec401/labs/3.1. The start script brought up seven Docker containers: webapp, docs, database, old-database, php-fpm, php-nginx, and a student container used as the scanning host.
cd /sec401/labs/3.1/ && ./start_3.1.sh
2. Ping sweep: discover live hosts
Ran a host-discovery-only scan against the /24. Nmap reported 7 hosts up in 1.38 seconds, each with a 172.28.14.x address, matching the containers launched by the start script.
nmap -sn 172.28.14.0/24
3. Greppable port sweeps
Demonstrated two greppable-output scans: --top-ports 100 and the -F fast scan. Both ran against the default target (none supplied on the CLI), so they returned zero hosts. The point was to capture the exact port list each scan covers in the header comment for documentation.
nmap -v --top-ports 100 -oG - nmap -v -F -oG -
4. Service and version detection
Enumerated services on every live host: OpenSSH 8.9p1 on the docs host, MySQL 5.7.41/5.7.44 on the two database hosts, nginx 1.14.2 on php-nginx, an unknown cslistener on php-fpm:9000, and http/https on the webapp. CPE entries (cpe:/o:linux:linux_kernel) confirm a Linux target fleet.
nmap -sV 172.28.14.0/24
5. OS detection: strict match
Ran a strict OS fingerprint. Nmap collected a full TCP/IP signature for each host but reported 'No exact OS matches' because containers don't present a clean kernel fingerprint over the network.
nmap -O 172.28.14.0/24
6. OS detection: aggressive guess
Re-ran with --osscan-guess. Nmap returned probability-weighted matches: Linux 2.6.32 (96%), Linux 3.2-4.9 (96%), with odd long-tail guesses like AXIS 210A network camera and Synology DiskStation. Useful reminder that OS detection degrades badly against virtualized or containerized hosts.
nmap -O --osscan-guess 172.28.14.0/24
7. Baseline scan saved to XML
Saved a second version scan to new_network.xml. XML output is the format ndiff consumes and the format most asset-management pipelines ingest.
nmap -sV -oX new_network.xml 172.28.14.0/24
8. ndiff: detect scan-over-scan change
Compared an older baseline (network.xml, Nov 2023) to new_network.xml (Apr 2026). ndiff surfaced a new listener on the docs host: 8000/tcp open http WSGIServer 0.2 (Python 3.10.12). This is the exact signal an asset inventory wants, a service that wasn't there before, on a host you thought you understood.
ndiff network.xml new_network.xml
9. SSH on a non-standard port
The docs host was advertising SSH on port 80, not 22. Connected with ssh -p 80 and authenticated into the Ubuntu 22.04 container. Non-standard service ports defeat naive scanners that only check well-known ports, which is exactly why -sV matters.
ssh -p 80 root@172.28.14.23
10. Post-compromise: netstat on target
From inside the docs host, listed listening sockets. Confirmed python3 listening on 0.0.0.0:8000, sshd on :80, a loopback resolver on 127.0.0.11:39563, and an established SSH session from the scanning host (172.28.14.1).
netstat -anp
11. iptables rules for the new service
Reviewed the INPUT chain. Port 8000 is only reachable from 172.28.14.23 (self) and loopback; every other source gets REJECT tcp-reset. That explains why the WSGI service only became visible once the scan originated from inside the lab subnet, it was firewalled from external sources.
iptables -n -L
12. Retrieve the served page
curled localhost:8000 from the docs host. Response was the 'Alpha Developers' internal documentation portal built with mkdocs-material 9.4.14. Confirms what the port, the process, and the ndiff finding all hinted at: an internal docs site that should never have been exposed beyond loopback.
curl localhost:8000
Key Findings
- 7 live hosts on 172.28.14.0/24 mapped to the lab's container stack
- SSH running on TCP/80 on the docs host, a classic port-obfuscation pattern
- php-fpm:9000 exposed as cslistener, a service usually kept internal
- ndiff surfaced a new WSGIServer on docs:8000 between scans
- iptables restricted 8000/tcp to the host itself, firewall-layer control working as intended
Security Controls
- Asset inventory and CMDB accuracy
- Host-based firewalls (iptables / nftables) restricting service exposure
- Change-detection pipelines (ndiff, diff-based alerting)
- Service hardening: don't expose dev/docs sites on 0.0.0.0
- Non-standard port hygiene: document, don't rely on, port obscurity