All articles

Footprinting — Infrastructure and Service Enumeration (HTB)

This is a study summary built from the Footprinting module of the HTB Academy Penetration Tester path (the one that leads to the HTB Certified Penetration Testing Specialist — CPTS exam). It is written as revision material: every tool and command from the module is kept, each with a short explanation and a worked example, plus the config files and misconfigurations that turn each service into a source of information. The original module, its exercises and its lab targets live on HTB Academy — this is my own recap, not a copy of their text.

Enumeration is the engine of a penetration test. Scanning tells you a port is open; footprinting tells you what is actually running behind it, how it is configured, and where the keys are kept. The module's guiding principle, repeated throughout: there are always more keys than we see at first glance — so enumerate exhaustively, re-feed every finding back into the process, and never dismiss a service as "boring". Everything below uses real tooling against real services; the only way to internalise it is to stand up a VM, configure each service yourself, and scan it until the output makes sense.

1. The enumeration methodology

Three principles frame everything you do:

  1. Is there something we can see? (open ports, banners, pages)
  2. Is there something we can access? (null sessions, anonymous logins, readable shares)
  3. What is the extent of what we found? (how far does that access reach)

The methodology is split into three levels — infrastructure-based, host-based and OS-based enumeration — organised into six layers you work through from the outside in. You finish an outer layer before diving into the next.

1 · Internet Presence domains, subdomains, netblocks, cloud, staff 2 · Gateway how the host is protected and exposed 3 · Accessible Services open ports, service + version, purpose 4 · Processes what runs, its data flow and dependencies 5 · Privileges users, groups, permissions, access rights 6 · OS Setup internal config — how admins run the box
The six layers of the footprinting methodology. Work from the outside in: understand the host's exposure before you start pulling at individual services.
Layer Goal Information categories
1. Internet Presence Identify externally reachable infrastructure. Domains, subdomains, vHosts, ASN, netblocks, IPs, cloud instances, security measures
2. Gateway Understand how the target is protected and where it sits. Firewalls, DMZ, IPS/IDS, EDR, proxies, NAC, segmentation, VPN, Cloudflare
3. Accessible Services Identify every reachable interface and service. Service type, functionality, config, port, version, interface
4. Processes Identify the internal processes and their data flow. PID, processed data, tasks, source, destination
5. Privileges Identify permissions and privileges on the services. Groups, users, permissions, restrictions, environment
6. OS Setup Identify the internal system setup. OS type, patch level, network config, configuration files, sensitive private files

This module lives mostly in Layer 3. Enumeration is a loop, not a step: every credential, hostname or share you find re-opens an earlier layer. The loop only ends when new findings stop appearing.

2. Infrastructure — domain information (passive)

Everything in this section is passive: you behave like a customer or visitor and never send active scans at the target. You start on the company's main website, learn what technologies its services imply, then mine public sources.

SSL certificates often list more than one subdomain in their DNS names field — each is probably still live.

crt.sh + jq — Certificate Transparency logs (RFC 6962) record every issued certificate; querying them hands you subdomains for free:

# Full JSON of every logged certificate for the domain
curl -s https://crt.sh/\?q\=inlanefreight.com\&output\=json | jq .

# Reduce to a clean, unique list of subdomains
curl -s https://crt.sh/\?q\=inlanefreight.com\&output\=json \
  | jq . | grep name | cut -d":" -f2 | grep -v "CN=" \
  | cut -d'"' -f2 | awk '{gsub(/\\n/,"\n");}1;' | sort -u

host — resolve that subdomain list and keep only the hosts the company runs itself (you may not test third-party providers):

# name + IP of company-hosted servers
for i in $(cat subdomainlist); do host $i | grep "has address" | grep inlanefreight.com | cut -d" " -f1,4; done
# build a plain IP list for the next tool
for i in $(cat subdomainlist); do host $i | grep "has address" | grep inlanefreight.com | cut -d" " -f4 >> ip-addresses.txt; done

Shodan — passively report what each IP already exposes (open ports, software, SSL) without you scanning it:

for i in $(cat ip-addresses.txt); do shodan host $i; done

dig any — pull every DNS record for the apex domain and read it:

dig any inlanefreight.com

What the records tell you: A → more IPs; MX → mail provider (Google = skip); NS → hosting provider; SOA → admin contact; TXT → the gold — SPF/DMARC/DKIM plus verification strings that reveal third-party providers (Atlassian, Google, LogMeIn, Mailgun, Outlook/Office 365, the registrar). Each provider is a lead: Office 365 → OneDrive/Azure blobs (SMB-based), Mailgun → APIs to test for IDOR/SSRF, LogMeIn → centralised remote access worth a password-reuse attempt.

3. Infrastructure — cloud resources

Misconfigured S3 buckets (AWS), blobs (Azure) and cloud storage (GCP) are frequently world-readable. Cloud hosts often show up in the DNS/IP list already (e.g. s3-website-us-west-2.amazonaws.com). To hunt the rest:

  • Google Dorks — intext:<company> inurl:amazonaws.com for S3, intext:<company> inurl:blob.core.windows.net for Azure. Results are usually PDFs, docs, presentations and code.
  • Page source — images, JS and CSS are often loaded from blob.core.windows.net/CDN URLs embedded in the HTML.
  • domain.glass — maps a company's infrastructure and even reports its Cloudflare security status (a Layer-2 finding).
  • GrayHatWarfare — searchable index of public AWS/Azure/GCP buckets, filterable by file type. This is where leaked id_rsa private keys turn up — download one and you log in without a password.

4. Infrastructure — staff (OSINT)

People leak the tech stack. LinkedIn and Xing profiles, plus job postings, reveal languages, databases, frameworks and tooling the company uses — a job ad listing "PostgreSQL, MySQL, Oracle / Flask, Django, ASP.NET / Git, SVN, Perforce / Atlassian suite" is a map of your attack surface. Employees' GitHub repos are worse: personal emails, hardcoded JWT tokens and config files that follow framework defaults (so you know where to look). Prioritise technical staff in development and security — the security team's focus tells you what defences to expect.

5. FTP (ports 21 / 20, TFTP 69/UDP)

FTP opens a control channel on TCP 21 and a data channel on TCP 20; it is clear-text. anonymous login (no password) is the classic quick win. TFTP is the stripped-down UDP cousin: no authentication, no directory listing, usable only in trusted networks.

Config — /etc/vsftpd.conf (one of the most common Linux FTP servers, vsFTPd):

sudo apt install vsftpd
cat /etc/vsftpd.conf | grep -v "#"      # see only the active settings
cat /etc/ftpusers                        # users explicitly DENIED FTP access

Dangerous settings that enable anonymous abuse: anonymous_enable=YES, anon_upload_enable=YES, anon_mkdir_write_enable=YES, no_anon_password=YES, write_enable=YES (enables STOR/DELE/MKD…). hide_ids=YES masks UIDs as ftp; ls_recurse_enable=YES lets you dump the whole tree at once.

Interacting with the ftp client:

ftp 10.129.14.136            # log in as "anonymous", blank password
# inside the session:
status                       # current connection settings
debug ; trace                # verbose protocol output
ls ; ls -R                   # list; recursive list (whole tree)
get "Important Notes.txt"    # download a file
put testupload.txt           # upload a file (tests write access)

Mirror everything non-interactively with wget (creates a folder named after the IP):

wget -m --no-passive ftp://anonymous:anonymous@10.129.14.136

Footprinting with nmap:

sudo nmap --script-updatedb                      # refresh the NSE script database
find / -type f -name ftp* 2>/dev/null | grep scripts   # list installed ftp NSE scripts
sudo nmap -sV -p21 -sC -A 10.129.14.136          # version + default scripts: ftp-anon, ftp-syst
sudo nmap -sV -p21 -sC -A 10.129.14.136 --script-trace   # watch the NSE commands on the wire

ftp-anon confirms anonymous access and lists the root; ftp-syst runs STAT to dump server status and version. For raw interaction or a TLS-wrapped FTPS server:

nc -nv 10.129.14.136 21
telnet 10.129.14.136 21
openssl s_client -connect 10.129.14.136:21 -starttls ftp   # also reveals the SSL cert (hostname, email)

6. SMB (ports 139 / 445)

Server Message Block shares files, printers and more. On Linux it's implemented by Samba (CIFS = the SMB1 dialect). NetBIOS/SMB1 uses ports 137/138/139; modern CIFS uses TCP 445. It's the richest target on Windows networks — shares, users, groups and password policy, often via an unauthenticated null session.

Config — /etc/samba/smb.conf:

cat /etc/samba/smb.conf | grep -v "#\|\;"   # active settings only

Key / dangerous per-share settings: browseable = yes (list shares), read only = no / writable = yes (create & modify), guest ok = yes (no password), map to guest = bad user (makes null sessions work), enable privileges = yes, create mask = 0777, and script hooks logon script / magic script.

smbclient — list shares with a null session (-N = no password, -L = list), then connect:

smbclient -N -L //10.129.14.128           # enumerate shares anonymously
smbclient //10.129.14.128/notes           # connect to a share
# inside: help | ls | get <file> | !<cmd>  (run a local command without dropping the session)

rpcclient — the deepest unauthenticated well; performs MS-RPC calls:

rpcclient -U "" 10.129.14.128
# > srvinfo              OS / version
# > enumdomains          deployed domains
# > querydominfo         domain, server, users, password policy
# > netshareenumall      all shares (incl. hidden) with paths
# > netsharegetinfo <s>  ACLs/permissions on one share
# > enumdomusers         every user + RID  → feeds brute-force/spray lists
# > queryuser <RID>      full detail on one user
# > querygroup <RID>     group detail

When commands are restricted, brute-force the RIDs (queryuser by RID is usually still allowed):

for i in $(seq 500 1100); do \
  rpcclient -N -U "" 10.129.14.128 -c "queryuser 0x$(printf '%x\n' $i)" \
  | grep "User Name\|user_rid\|group_rid" && echo ""; done

Other SMB tools — each may return something the others miss, so run more than one:

samrdump.py 10.129.14.128                           # Impacket: user enumeration
smbmap -H 10.129.14.128                              # shares + your access level per share
crackmapexec smb 10.129.14.128 --shares -u '' -p ''  # shares via a null session
# enum4linux-ng: automates most of the above
git clone https://github.com/cddmp/enum4linux-ng.git && cd enum4linux-ng && pip3 install -r requirements.txt
./enum4linux-ng.py 10.129.14.128 -A                  # users, groups, shares, OS, password policy

nmap -sV -sC -p139,445 <IP> gives version + smb2-security-mode/smb2-time, but manual tools reveal far more. On the server side, smbstatus shows who is connected.

7. NFS (ports 111 / 2049)

Network File System (Linux/Unix) exposes directories over the network. It relies on ONC-RPC / portmapper on TCP+UDP 111; NFSv4 uses only TCP 2049. NFSv3 authenticates the client machine (by UID/GID), not the user — a trust that is easy to abuse.

Config — /etc/exports (options table): rw/ro, sync/async, secure/insecure (ports >1024), no_subtree_check, root_squash. Dangerous: rw, insecure, nohide, and above all no_root_squash (files created by root keep UID/GID 0 → drop a SUID binary or read anything).

echo '/mnt/nfs 10.129.14.0/24(sync,no_subtree_check)' >> /etc/exports   # example export
systemctl restart nfs-kernel-server ; exportfs

Footprinting with nmap + mount:

sudo nmap 10.129.14.128 -p111,2049 -sV -sC          # rpcinfo: enumerates all RPC services/ports
sudo nmap --script nfs* 10.129.14.128 -sV -p111,2049 # nfs-ls, nfs-showmount, nfs-statfs

showmount -e 10.129.14.128                            # list exported shares
mkdir target-NFS
sudo mount -t nfs 10.129.14.128:/ ./target-NFS/ -o nolock
ls -l  target-NFS/mnt/nfs/     # files with usernames/groups
ls -n  target-NFS/mnt/nfs/     # same, but raw UIDs/GIDs (recreate them locally to read/edit)
sudo umount ./target-NFS

Escalation idea: with SSH access, upload a SUID shell to a writable NFS share as the target user, then execute it. With root_squash set you can't edit root-owned files even as root.

8. DNS (port 53)

DNS resolves names to IPs and stores service metadata. Server roles: root, authoritative, non-authoritative, caching, forwarding, resolver. Records: A/AAAA (IPv4/IPv6), MX (mail), NS (name servers), TXT (verification/SPF/DMARC/DKIM), CNAME (alias), PTR (reverse), SOA (zone admin). Config lives in Bind9 files named.conf.local, zone files (/etc/bind/db.*) and reverse files.

Dangerous settings: allow-query, allow-recursion, allow-transfer (who may pull the full zone), zone-statistics. A loose allow-transfer is the big one.

Footprinting with dig:

dig soa www.inlanefreight.com                   # SOA → admin email (dot becomes @)
dig ns   inlanefreight.htb @10.129.14.128        # which name servers exist
dig CH TXT version.bind 10.129.120.85            # server version (CHAOS class query)
dig any  inlanefreight.htb @10.129.14.128        # all records the server will disclose
dig axfr inlanefreight.htb @10.129.14.128         # ZONE TRANSFER — full zone dump (the jackpot)
dig axfr internal.inlanefreight.htb @10.129.14.128 # try discovered internal zones too

A successful AXFR hands you every record, often including internal hosts (dc1, vpn, ws1, wsus). When AXFR is refused, brute-force subdomains:

# Bash loop over a wordlist
for sub in $(cat /opt/useful/seclists/Discovery/DNS/subdomains-top1million-110000.txt); do \
  dig $sub.inlanefreight.htb @10.129.14.128 | grep -v ';\|SOA' | sed -r '/^\s*$/d' | grep $sub | tee -a subdomains.txt; done

# or let DNSenum do it (-f = wordlist, -o = output file)
dnsenum --dnsserver 10.129.14.128 --enum -p 0 -s 0 -o found.txt \
  -f /opt/useful/seclists/Discovery/DNS/subdomains-top1million-110000.txt inlanefreight.htb

9. SMTP (ports 25 / 587 / 465)

SMTP sends mail. Port 25 (server-to-server), 587 (authenticated submission, STARTTLS), 465 (SMTPS). The chain is MUA → MSA → MTA (relay) → MDA → mailbox. Misconfigured relays can be abused to spoof mail (Open Relay).

Config — /etc/postfix/main.cf. Commands worth knowing: AUTH PLAIN, HELO/EHLO, MAIL FROM, RCPT TO, DATA, RSET, VRFY, EXPN, NOOP, QUIT. Dangerous: mynetworks = 0.0.0.0/0 turns the server into an open relay.

Manual interaction with telnet — enumerate users with VRFY, and send mail by hand:

telnet 10.129.14.128 25
# HELO mail1.inlanefreight.htb      → 250
# EHLO mail1                        → capabilities list
# VRFY root                         → 252 confirms a user may exist
# MAIL FROM: <a@b.htb> / RCPT TO: <c@d.htb> / DATA … .  → queue a message

A web proxy can be bounced at the SMTP server with CONNECT 10.129.14.128:25 HTTP/1.0.

Footprinting with nmap:

sudo nmap 10.129.14.128 -sC -sV -p25                        # smtp-commands (uses EHLO)
sudo nmap 10.129.14.128 -p25 --script smtp-open-relay -v     # 16 open-relay tests

10. IMAP / POP3 (ports 143 / 993, 110 / 995)

IMAP (143, TLS 993) manages mail on the server with folders and multi-client sync; POP3 (110, TLS 995) only lists/retrieves/deletes. Both are clear-text without TLS. Mailbox access means password resets, internal docs and more usernames.

IMAP commands: 1 LOGIN user pass, 1 LIST "" *, 1 SELECT INBOX, 1 FETCH <ID> all, 1 CLOSE, 1 LOGOUT. POP3 commands: USER, PASS, STAT, LIST, RETR <id>, DELE <id>, CAPA, QUIT. Dangerous Dovecot settings: auth_debug, auth_debug_passwords, auth_verbose, auth_anonymous_username.

Footprinting with nmap, curl and openssl:

sudo nmap 10.129.14.128 -sV -p110,143,993,995 -sC   # pop3-/imap-capabilities + ssl-cert (CN, org, location)

curl -k 'imaps://10.129.14.128' --user user:p4ssw0rd        # log in, list folders
curl -k 'imaps://10.129.14.128' --user cry0l1t3:1234 -v      # -v shows TLS, cert and banner/version

openssl s_client -connect 10.129.14.128:pop3s       # raw POP3S session
openssl s_client -connect 10.129.14.128:imaps       # raw IMAPS session

11. SNMP (ports 161 / 162 UDP)

SNMP monitors and configures network devices over UDP 161 (162 for traps). Data is addressed by OIDs described in the MIB tree. Security hinges on the community string (a password): v1/v2c send it in clear text and public is the eternal default; v3 adds auth + encryption.

Config — /etc/snmp/snmpd.conf. Dangerous: rwuser noauth (full OID tree, no auth), rwcommunity <string> <IPv4> and rwcommunity6 (full tree from anywhere).

Footprinting — snmpwalk, onesixtyone, braa:

snmpwalk -v2c -c public 10.129.14.128              # walk the whole MIB tree with a known community string

sudo apt install onesixtyone
onesixtyone -c /opt/useful/seclists/Discovery/SNMP/snmp.txt 10.129.14.128   # brute community strings

sudo apt install braa
braa public@10.129.14.128:.1.3.6.*                 # fast OID brute/query once you know the string

snmpwalk output leaks kernel version, contact email, running processes and installed packages. crunch can build custom community-string wordlists when they follow a naming pattern.

12. MySQL (port 3306)

MySQL (and its fork MariaDB) is an open-source RDBMS, usually on TCP 3306, central to LAMP/LEMP stacks (WordPress, etc.). Exposed to the network it means reachable data and sometimes a path to the OS.

Config — /etc/mysql/mysql.conf.d/mysqld.cnf. Dangerous / security-relevant: user, password, admin_address (stored in plain text), debug, sql_warnings (verbose errors), secure_file_priv (limits file import/export).

Footprinting with nmap + client:

sudo nmap 10.129.14.128 -sV -sC -p3306 --script mysql*
# scripts: mysql-info, mysql-empty-password, mysql-enum, mysql-brute, mysql-users, mysql-databases…
# (confirm findings manually — the empty-password script throws false positives)

mysql -u root -h 10.129.14.128                 # try without a password
mysql -u root -pP4SSw0rd -h 10.129.14.128       # NB: no space between -p and the password

Once in, the key commands:

show databases;                       -- information_schema, mysql, performance_schema, sys are built-in
use <database>;
show tables;
show columns from <table>;
select * from <table>;
select * from <table> where <column> = "<string>";

13. MSSQL (port 1433)

Microsoft SQL Server (closed-source, Windows-first) listens on TCP 1433. Clients include SSMS, mssql-cli, sqsh and — the pentester's favourite — Impacket's mssqlclient.py. Default system DBs: master, model, msdb, tempdb, resource. Windows Authentication means a compromised account can pivot across the domain. Dangerous: no connection encryption, spoofable self-signed certs, named pipes, weak/default sa credentials.

locate mssqlclient                          # find Impacket's client (/usr/bin/impacket-mssqlclient)

# Nmap default MSSQL scripts against port 1433
sudo nmap --script ms-sql-info,ms-sql-empty-password,ms-sql-xp-cmdshell,ms-sql-config,\
ms-sql-ntlm-info,ms-sql-tables,ms-sql-hasdbaccess,ms-sql-dac,ms-sql-dump-hashes \
  --script-args mssql.instance-port=1433,mssql.username=sa,mssql.password=,mssql.instance-name=MSSQLSERVER \
  -sV -p 1433 10.129.201.248
# reveals hostname, instance name, version, named-pipe status

Metasploit ping scanner, then connect with Windows auth and list databases:

# msf6 > use auxiliary/scanner/mssql/mssql_ping ; set rhosts <IP> ; run

python3 mssqlclient.py Administrator@10.129.201.248 -windows-auth
# SQL> select name from sys.databases

14. Oracle TNS (port 1521)

Oracle Transparent Network Substrate brokers connections to Oracle DBs on TCP 1521. Config files tnsnames.ora (client-side name→address resolution) and listener.ora (server-side listener) live in $ORACLE_HOME/network/admin. Connections are identified by a SID (System Identifier) or service name. Watch for default creds: Oracle 9 CHANGE_ON_INSTALL, the DBSNMP service dbsnmp.

Setup + enumeration with ODAT (Oracle Database Attacking Tool):

# install prerequisites, then clone ODAT
git clone https://github.com/quentinhardy/odat.git && cd odat/
./odat.py -h

sudo nmap -p1521 -sV 10.129.204.235 --open                         # confirm the TNS listener
sudo nmap -p1521 -sV 10.129.204.235 --open --script oracle-sid-brute # brute the SID (e.g. XE)
./odat.py all -s 10.129.204.235                                     # run every module: SIDs, creds, privs…
# → e.g. "Valid credentials found: scott/tiger"

Log in and enumerate with sqlplus:

sqlplus scott/tiger@10.129.204.235/XE              # connect to the XE instance
sqlplus scott/tiger@10.129.204.235/XE as sysdba     # try to escalate to SYSDBA
select table_name from all_tables;        -- list tables
select * from user_role_privs;            -- current user's roles
select name, password from sys.user$;     -- extract password hashes (crack offline)

File upload to the webroot (path to RCE) with ODAT's utlfile:

echo "Oracle File Upload Test" > testing.txt
./odat.py utlfile -s 10.129.204.235 -d XE -U scott -P tiger --sysdba \
  --putFile C:\\inetpub\\wwwroot testing.txt ./testing.txt
curl -X GET http://10.129.204.235/testing.txt      # verify (Linux webroot: /var/www/html)

15. IPMI (port 623/UDP)

IPMI manages server BMCs (HP iLO, Dell iDRAC, Supermicro) over UDP 623, independently of the host OS — access to a BMC is "nearly equivalent to physical access". Its headline flaw: the RAKP protocol in IPMI 2.0 returns a salted SHA1/MD5 password hash for any valid username before authentication — crack it offline.

sudo nmap -sU --script ipmi-version -p 623 ilo.inlanfreight.local   # fingerprint version 1.5/2.0

# Metasploit: version detection and the hash dump
# msf6 > use auxiliary/scanner/ipmi/ipmi_version ; set rhosts <IP> ; run
# msf6 > use auxiliary/scanner/ipmi/ipmi_dumphashes ; set rhosts <IP> ; run

Crack the dumped hash with Hashcat mode 7300; for a factory HP iLO password (8 chars, upper+digits) use a mask attack:

hashcat -m 7300 ipmi.txt -a 3 ?1?1?1?1?1?1?1?1 -1 ?d?u

Default creds to always try: Dell iDRAC root:calvin, Supermicro ADMIN:ADMIN, HP iLO Administrator:<random 8-char>.

16. SSH (port 22)

SSH (OpenSSH) gives an encrypted shell on TCP 22. Prefer SSH-2 (SSH-1 is MITM-vulnerable). Six auth methods exist; password and public-key are the ones you meet. Config is /etc/ssh/sshd_config.

Dangerous settings: PasswordAuthentication yes (brute-forceable), PermitEmptyPasswords yes, PermitRootLogin yes, Protocol 1, X11Forwarding yes, AllowTcpForwarding yes, PermitTunnel, DebianBanner yes.

Footprinting with ssh-audit:

git clone https://github.com/jtesta/ssh-audit.git && cd ssh-audit
./ssh-audit.py 10.129.14.132        # banner/version + which key-exchange/host-key/MAC algos are weak

ssh -v cry0l1t3@10.129.14.132                                   # -v reveals the accepted auth methods
ssh -v cry0l1t3@10.129.14.132 -o PreferredAuthentications=password   # force password auth (for brute-forcing)

The banner encodes both protocol and version: SSH-1.99-OpenSSH_3.9p1 accepts SSH-1 and SSH-2; SSH-2.0-OpenSSH_8.2p1 accepts only SSH-2.

17. Rsync (port 873)

Rsync copies files efficiently over TCP 873 (or tunnelled through SSH). Listing a shared "module" and pulling files can often be done unauthenticated.

sudo nmap -sV -p 873 127.0.0.1        # detect rsync (protocol version 31)

nc -nv 127.0.0.1 873                   # probe: send "#list" to see modules
# @RSYNCD: 31.0  →  #list  →  "dev   Dev Tools"

rsync -av --list-only rsync://127.0.0.1/dev     # list a module's contents (look for secrets.yaml, .ssh)
rsync -av rsync://127.0.0.1/dev                 # pull everything
rsync -av -e ssh rsync://127.0.0.1/dev          # when rsync rides over SSH (-e "ssh -p2222" for odd ports)

Always check for password re-use with any credentials found elsewhere.

18. R-services (ports 512 / 513 / 514)

The Berkeley r-services (rcp, rsh, rexec, rlogin, rwho, rusers) are clear-text Unix remote-access daemons across TCP 512/513/514, superseded by SSH but still seen. They can bypass authentication via trusted entries in /etc/hosts.equiv (global) and .rhosts (per-user); a + wildcard in those files trusts anyone.

sudo nmap -sV -p 512,513,514 10.0.17.2     # exec / login / shell daemons

rlogin 10.0.17.2 -l htb-student            # log in (works if .rhosts trusts you — no password)
rwho                                        # interactive sessions on the local network (UDP 513 broadcast)
rusers -al 10.0.17.5                        # detailed logged-in users (name, host, tty, login time)

Trusted-host misconfigurations here let you authenticate as another user without credentials — note the usernames rwho/rusers reveal for later attacks.

19. RDP (port 3389)

Remote Desktop Protocol (TCP 3389) gives GUI access to Windows. Certificates are self-signed by default; many hosts accept weak encryption. Scanning reveals NLA status, version and hostname.

nmap -sV -sC 10.129.201.248 -p3389 --script rdp*
# rdp-ntlm-info → hostname, NetBIOS/DNS domain, product version; rdp-enum-encryption → NLA/TLS support

Nmap's RDP probe sends a mstshash=nmap cookie that EDR can flag — add --packet-trace --disable-arp-ping -n to see it. A dedicated checker and a Linux client:

# rdp-sec-check.pl (Perl) — unauthenticated audit of the RDP security settings
git clone https://github.com/CiscoCXSecurity/rdp-sec-check.git && cd rdp-sec-check
./rdp-sec-check.pl 10.129.201.248

xfreerdp /u:cry0l1t3 /p:"P455w0rd!" /v:10.129.201.248   # connect from Linux (also: rdesktop, Remmina)

20. WinRM (5985 / 5986) and WMI (135)

Windows Remote Management uses SOAP over TCP 5985 (HTTP) / 5986 (HTTPS) — in practice you mostly see 5985. It backs PowerShell remoting. Windows Management Instrumentation initialises on TCP 135 then moves to a random port, giving read/write access to almost every Windows setting.

nmap -sV -sC 10.129.201.248 -p5985,5986 --disable-arp-ping -n   # Microsoft HTTPAPI httpd → WinRM
# PowerShell check from Windows: Test-WsMan <host>

# evil-winrm — interactive WinRM shell with a valid credential
evil-winrm -i 10.129.201.248 -u Cry0l1t3 -p P455w0rD!

# wmiexec.py (Impacket) — command execution over WMI (port 135)
/usr/share/doc/python3-impacket/examples/wmiexec.py Cry0l1t3:"P455w0rD!"@10.129.201.248 "hostname"

21. What to carry into the CPTS exam

  • Methodology over tool-spamming. Know which of the six layers you are filling in and why. The lab targets reward thoroughness, not speed.
  • Free access first. Null sessions (smbclient -N, rpcclient -U ""), anonymous FTP, showmount, snmpwalk -c public, default BMC creds — always the first thing to try.
  • Versions map to CVEs. Run -sV on everything; every banner is a lead.
  • Read the config. /etc/vsftpd.conf, /etc/samba/smb.conf, /etc/exports, /etc/snmp/snmpd.conf, sshd_config — the dangerous settings are the vulnerabilities.
  • Never trust one tool. Run rpcclient, enum4linux-ng, smbmap and crackmapexec against the same SMB host; confirm Nmap findings manually (the MySQL empty-password script lies).
  • Everything loops back. Each username, hostname, share, hash or credential re-opens an earlier layer and is worth a password-reuse attempt elsewhere. Re-enumerate until nothing new appears.
  • Reproduce every example. The module ends with three hands-on Footprinting Labs (Easy/Medium/Hard); the only way through them (and the exam) is to have actually run these commands.

Cheatsheet — Footprinting

Infrastructure / OSINT (passive)

curl -s https://crt.sh/\?q\=DOMAIN\&output\=json | jq .                      # cert transparency
curl -s https://crt.sh/\?q\=DOMAIN\&output\=json | jq . | grep name | cut -d":" -f2 | grep -v "CN=" | cut -d'"' -f2 | awk '{gsub(/\\n/,"\n");}1;' | sort -u
for i in $(cat subs);do host $i | grep "has address" | cut -d" " -f4 >> ips.txt;done
for i in $(cat ips.txt);do shodan host $i;done
dig any DOMAIN
# Google: intext:COMPANY inurl:amazonaws.com | inurl:blob.core.windows.net
# domain.glass ; buckets.grayhatwarfare.com ; LinkedIn/Xing ; GitHub

FTP (21)

ftp <IP>                                              # anonymous / blank
wget -m --no-passive ftp://anonymous:anonymous@<IP>
sudo nmap -sV -p21 -sC -A <IP>                         # ftp-anon, ftp-syst
nc -nv <IP> 21 ; telnet <IP> 21
openssl s_client -connect <IP>:21 -starttls ftp

SMB (139/445)

smbclient -N -L //<IP>                                 # null-session share list
smbclient //<IP>/<share>
smbmap -H <IP>
crackmapexec smb <IP> --shares -u '' -p ''
rpcclient -U "" <IP>    # srvinfo / enumdomusers / querydominfo / netshareenumall / queryuser <RID>
for i in $(seq 500 1100);do rpcclient -N -U "" <IP> -c "queryuser 0x$(printf '%x\n' $i)" | grep "User Name\|user_rid\|group_rid" && echo "";done
samrdump.py <IP>
./enum4linux-ng.py <IP> -A

NFS (111/2049)

sudo nmap --script nfs* <IP> -sV -p111,2049
showmount -e <IP>
sudo mount -t nfs <IP>:/ ./target-NFS/ -o nolock ; ls -n ./target-NFS ; sudo umount ./target-NFS

DNS (53)

dig ns DOMAIN @<NS> ; dig any DOMAIN @<NS> ; dig axfr DOMAIN @<NS>
dig CH TXT version.bind <NS>
dnsenum --dnsserver <NS> --enum -p 0 -s 0 -o found.txt -f wordlist.txt DOMAIN   # -f=wordlist -o=output

SMTP (25) / IMAP-POP3 (110,143,993,995)

telnet <IP> 25           # HELO/EHLO ; VRFY user ; MAIL FROM/RCPT TO/DATA
sudo nmap <IP> -sC -sV -p25 --script smtp-open-relay
sudo nmap <IP> -sV -p110,143,993,995 -sC
curl -k 'imaps://<IP>' --user user:pass -v
openssl s_client -connect <IP>:pop3s   # or :imaps

SNMP (161)

onesixtyone -c snmp.txt <IP>           # find the community string
snmpwalk -v2c -c public <IP>
braa public@<IP>:.1.3.6.*

Databases

mysql -u root -p<password> -h <IP>                              # MySQL 3306 (no space after -p)
sudo nmap <IP> -sV -sC -p3306 --script mysql*
mssqlclient.py <user>@<IP> -windows-auth                         # MSSQL 1433
sudo nmap --script ms-sql-info,ms-sql-ntlm-info -p1433 <IP>
./odat.py all -s <IP>                                            # Oracle TNS 1521
sudo nmap -p1521 -sV <IP> --script oracle-sid-brute
sqlplus <user>/<pass>@<IP>/<SID>

IPMI (623) & remote management

sudo nmap -sU --script ipmi-version -p623 <IP>                   # msf ipmi_dumphashes → hashcat -m 7300
ssh-audit.py <IP> ; ssh <user>@<IP> -o PreferredAuthentications=password   # SSH 22
rsync -av --list-only rsync://<IP>/<module>                      # Rsync 873
rlogin <IP> -l <user> ; rusers -al <IP>                          # R-services 512/513/514
nmap --script rdp* -p3389 <IP> ; xfreerdp /u:<user> /p:"<pass>" /v:<IP>   # RDP 3389
evil-winrm -i <IP> -u <user> -p <pass>                           # WinRM 5985
wmiexec.py <user>:"<pass>"@<IP> "<command>"                      # WMI 135

Built from HTB Academy's Footprinting module — if you want the labs, the full lessons and the exam, they're on HTB Academy.