Skip to main contentSkip to main content
Room Banner
Back to all walkthroughs
Room Icon

Linux Privilege Escalation: Enumeration

Gather information about the target host to understand the system for privilege escalation.

easy

60 min

1,609

User profile photo.
User profile photo.

To access material, start machines and answer questions login.

Privilege escalation is a journey. There are no silver bullets, and much depends on the specific configuration of the target system. The kernel version, installed applications, supported programming languages, and other users' passwords are a few key elements that will affect your road to the root shell. This room covers many privilege escalation techniques, and it's designed such that each technique is self-contained in its own task. You can study each task independently, but we recommend doing it in order.

What Does “Privilege Escalation” Mean?

At its core, privilege escalation usually involves going from a lower permission account to a higher permission one. More technically, it's the exploitation of a vulnerability, design flaw, or configuration oversight in an operating system or application to gain unauthorized access to resources that are usually restricted to users.

Why Is It Important?

It's rare when performing a real-world penetration test to be able to gain a foothold (initial access) that gives you direct administrative access. Generally, you'd first gain access to systems as a low-privileged user. Privilege escalation is crucial because it lets you gain system administrator levels of access, which allows you to perform actions such as:

  • Resetting passwords
  • Bypassing access controls to compromise protected data
  • Editing software configurations
  • Enabling
  • Changing the privilege of existing (or new) users
  • Execute any administrative command

This room is designed to cover the main privilege escalation vectors and give you a better understanding of the process. This new skill will be an essential part of your arsenal, whether you are participating in CTFs, taking certification exams, or working as a penetration tester.

Prerequisites

Learning Objectives

  • Understand the purpose and importance of enumeration in privilege escalation
  • Identify key information using manual enumeration commands
  • Find hidden files
  • Enumerate users, groups, and permissions on a system
  • Enumerate basic network information
  • Discover potential privilege escalation vectors through manual enumeration
Answer the questions below

Ready for some enumeration!

To complete the of this room, you will need to start the target machine by clicking the button below, which will open the machine in split view. If you want to connect to the target from your own -connected machine, you can use the credentials provided below. In this room, you will have to use the attached to gather information about various properties.

Target Machine card placeholder

Credentials

Only needed if you are using your own machine.

Username
 
john
 
Password
 
john
 
 
Connection via
 
john@MACHINE_IP
 

Enumeration is arguably the most critical phase when it comes to privilege escalation. Before you can exploit anything, you need to understand the environment you're working in; what's running, who's running it, and what misconfigurations might exist. This is where manual enumeration comes in. By gathering key information about the system, such as the kernel version, installed applications, user permissions, scheduled tasks, and network configuration, you can start to build a picture of potential attack vectors. Without thorough enumeration, you're essentially working blind, and any exploitation attempts would be guesswork at best. The more you understand about the target system, the more efficiently you can identify and exploit weaknesses to escalate your privileges.

This task will focus on various commands and techniques to enumerate operating system properties, like:

  • hostname
  • uname
  • /proc/version
  • /etc/issue
  • ps
  • cron
  • dpkg

The hostname Command

The hostname command will return the hostname of the target machine. Although this value can easily be changed or have a relatively meaningless string (e.g., Ubuntu-3487340239), in some cases, it can provide information about the target system's role within the corporate network (e.g., SQL-PROD-01 for a production server).

The uname Command

The command uname -a will print system information, giving you additional details about the kernel used by the system. This is useful when searching for any potential kernel vulnerabilities that could lead to privilege escalation.

uname -a
           john@home:~$ uname -a
Linux home 6.8.0-41-generic
        

In the example above, the output is as follows:

  • : Operating system
  • home: Hostname
  • 6.8.0-41-generic: Kernel version

The /proc/version File

The proc filesystem (procfs) provides information about the target system processes. You will find proc on many different Linux flavors, making it an essential tool to have in your arsenal. Looking at /proc/version may give you information on the kernel version or what compiler was used to create it.

cat /proc/version
           john@home:~$ cat /proc/version
Linux version 6.8.0-41-generic (buildd@lcy02-amd64-077) (x86_64-linux-gnu-gcc-13 (Ubuntu 13.2.0-23ubuntu4) 13.2.0, GNU ld (GNU Binutils for Ubuntu) 2.42)
        

In the example above, the output is as follows:

  • 6.8.0-41-generic: Kernel version
  • buildd@lcy02-amd64-077: Build machine that compiled the kernel
  • x86_64--gnu-gcc-13: Compiler used to build the kernel
  • Ubuntu 13.2.0-23ubuntu4: Ubuntu package version of the gcc compiler
  • GNU ld (GNU Binutils for Ubuntu) 2.42: Linker used during the kernel build

The /etc/issue File

Systems can also be identified by looking at the /etc/issue file. This file usually contains some information about the operating system, but can easily be customized or changed. Also, any file containing system information can be customized or changed. For a clearer understanding of the system, it is always good to look at all of these.

cat /etc/issue
           john@linux-enumeration:~$ cat /etc/issue
Ubuntu 22.04.1 LTS \n \l
        

In the example above, Ubuntu 22.04.1 LTS represents the Ubuntu version running on the host.

The ps Command

The ps command is an effective way to see the running processes on a Linux system. Running ps in your terminal will show processes for the current shell.

The output of the ps (Process Status) will show the following;

  • PID: The process ID (unique to the process)
  • TTY: Terminal type used by the user
  • Time: Amount of CPU time used by the process (this is NOT the time this process has been running for)
  • CMD: The command or executable running (will NOT display any command line parameter)

The ps command provides a few useful options.

  • ps aux: The aux option will show processes for all users a, display the user that launched the process u, and show processes that are not attached to a terminal x. Looking at the ps aux command output, you can have a better understanding of the system and potential vulnerabilities.
  • ps axjf: The axjf option will show processes from all users a, include processes that have no controlling terminal x, use jobs format output j, and forest/tree view f. An example of such tree can be seen below.
ps axjf
           john@linux-enumeration:~$ ps axjf 
1 1039 1039 1039 ? -1 Ss 0 0:00 /usr/sbin/sshd -D
1039 1854 1854 1854 ? -1 Ss 0 0:00 \_ sshd: karen [priv] 1854 1890 1854 1854 ? -1 S 1001 0:00 \_ sshd: karen@pts/0 1890 1891 1891 1891 pts/0 1975 Ss 1001 0:00 \_ -sh 1891 1975 1975 1891 pts/0 1975 R+ 1001 0:00 \_ ps axjf

The cron Service

Cron is a time-based job scheduler in Linux that allows users and the system to schedule commands or scripts to run automatically at specified intervals. You'll often find cron jobs being used for tasks like backups, log rotation, or running maintenance scripts. During enumeration, it's worth checking for cron jobs since they sometimes run as privileged users. If a cron job is running a script that you can modify, it could become a potential escalation vector.

You can start by examining /etc/crontab and listing the contents of /var/spool/cron/ or /etc/cron.d/ to see what's scheduled and, more importantly, who it's running as. You'll explore how to actually exploit misconfigured cron jobs later, but for now, it's important to include them in your enumeration checklist.

Below is an example of an /etc/crontab entry.

cat /etc/crontab
           30 2 * * 1 root /home/ubuntu/clear-mail.sh
        

The output is as follows:

  • The first field represents the minute when the script is supposed to be run (valid range: 0-59)
  • The second field represents the hour when the script is supposed to be run (valid range: 0-23)
  • The third field represents the day of the month when the script is supposed to be run (valid range: 1-31)
  • The fourth field represents the month when the script is supposed to be run (valid range: 1-12)
  • The fifth field represents the day of the week when the script is supposed to be run(valid range: 0-7, both 0 and 7 represent Sunday)
  • The sixth field represents the user who will run the task
  • The final field represents the task to be run, which can be any script or binary as long as it's executable

Putting this all together, the crontab above runs /home/ubuntu/clear-mail.sh every Monday at 2:30 AM as the root user.

The dpkg Command

The dpkg tool allows us to query all installed packages and their version. This is especially helpful in privilege escalation attempts when trying to find vulnerable binaries with known exploits.

The command to list all installed software is dpkg -l.

Answer the questions below

What is the hostname of the target host?

What is the Linux kernel version of the target host?

What version of Ubuntu is running on the host?

What is the full path of the script run by root every 5 minutes?

What is the full version of AppArmor?

This task will focus on obtaining information about local users through commands and files, such as:

  • id
  • env
  • history
  • sudo -l
  • /etc/password

The id Command

The id command will provide a general overview of the user’s privilege level and group memberships. It is worth remembering that the id command can also be used to obtain the same information for another user, as seen below:

id
           john@home:~$ id
uid
=1001(john) gid=1001(john) groups=1001(john),100(users)
john@home:~$ id matt
uid
=1002(matt) gid=1002(matt) groups=1002(matt),27(sudo),116(admin)

The env Command

The env command will show environmental variables.

env
           john@home:~$ env
MAIL=/var/mail/john
USER=john
SSH_CLIENT=10.80.88.217 50500 22
HOME=/home/john
SSH_TTY=/dev/pts/0
QT_QPA_PLATFORMTHEME=appmenu-qt5
LOGNAME=john
TERM=linux
        

The PATH variable may have a compiler or a scripting language (e.g., Python) that could be used to run code on the target system or be leveraged for privilege escalation.

The history Command

Looking at earlier commands with the history command can give us some idea about the target system and, albeit rarely, store information such as passwords or usernames.

The sudo -l Command

The target system may be configured to allow users to run some (or all) commands with root privileges. The sudo -l command can be used to list all commands your user can run using sudo. Depending on the configuration, you may be required to input your current user's password when running the sudo command.

The /etc/passwd File

Reading the /etc/passwd file can be an easy way to discover users on the system.

cat /etc/passwd
           john@home:~$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
        

While the output can be long and a bit intimidating, it can easily be cut and converted to a useful list for brute-force attacks.

cat /etc/passwd | cut -d ":" -f 1
           john@home:~$ cat /etc/passwd | cut -d ":" -f 1
root
daemon
bin
sys
sync
games
man
lp
mail
news
uucp
proxy
www-data
backup
list
irc
gnats
nobody
libuuid

Remember that this will return all users, some of whom are system or service users that would not be very useful. Another approach could be to grep for “home” as real users will most likely have their folders under the “home” directory.

cat /etc/passwd | grep /home
           john@home:~$ cat /etc/passwd | grep /home
matt:x:1000:1000:matt,,,:/home/matt:/bin/bash
karen:x:1001:1001::/home/karen:
        
Answer the questions below

Print the environment variables. What is the value of LANG?

What is the flag in your history?

What is the full path of the command you are allowed to run with elevated privileges?

What is the username of the Mailing List Manager?

In this task, you will learn about ifconfig and netstat, and leverage them to gain information about network interfaces and listening ports.

The ifconfig Command

The target system may be a pivoting point to another network. The ifconfig command gives you information about the network interfaces of the system. In the snippet below, for example, you can see that there is a Docker interface, which suggests that Docker is probably running on the host.

ifconfig
           john@home:~$ ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:2aff:feef:cb59  prefixlen 64  scopeid 0x20<link>
        ether 02:42:2a:ef:cb:59  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 38  bytes 5128 (5.1 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
ens5: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 9001
inet 10.80.96.65 netmask 255.255.192.0 broadcast 10.80.127.255
inet6 fe80::89f:a8ff:fed4:b8e9 prefixlen 64 scopeid 0x20<link>
ether 0a:9f:a8:d4:b8:e9 txqueuelen 1000 (Ethernet)
RX packets 14085 bytes 14572272 (14.5 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4151 bytes 7292416 (7.2 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

On modern Linux distributions, this command has been replaced by the ip command. The equivalent of ifconfig is ip addr. ifconfig still exists as part of the net-tools package.

The netstat Command

Following an initial check for existing interfaces and network routes, it is worth looking into existing communications. The netstat command can be used with several different options to gather information on existing connections.

netstat -a shows all listening ports and established connections.

netstat -at or netstat -au can also be used to list TCP or UDP protocols, respectively.

netstat -l lists ports in “listening” mode. These ports are open and ready to accept incoming connections. This can be used with the -t option to list only ports that are listening using the TCP protocol, as shown below:

netstat -lt
           john@home:~$ netstat -lt
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:ldap            0.0.0.0:*               LISTEN     
tcp        0      0 localhost:postgresql    0.0.0.0:*               LISTEN     
tcp        0      0 localhost:5433          0.0.0.0:*               LISTEN 
        

netstat -s lists network usage statistics by protocol. This can also be used with the -t or -u options to limit the output to a specific protocol.

netstat -s
           john@home:~$ netstat -s
Ip:
    Forwarding: 1
    66019 total packets received
    5 with invalid addresses
    0 forwarded
    0 incoming packets discarded
    66012 incoming packets delivered
    60939 requests sent out
    74 outgoing packets dropped
Icmp:
    156 ICMP messages received
    0 input ICMP message failed
    ICMP input histogram:
        destination unreachable: 156
    156 ICMP messages sent
    0 ICMP messages failed
    ICMP output histogram:
        destination unreachable: 156
        

netstat -tp lists connections with the service name and PID information.

netstat -tp
           john@home~$ netstat -tp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 10.80.96.65:55010       172.31.66.192:9092      TIME_WAIT   -                   
tcp        0      0 localhost:5901          localhost:55988         ESTABLISHED
        

This can also be used with the -l option to list listening ports/services. The -n flag tells netstat to show numeric addresses and port numbers instead of resolving them.

netstat -tpl
           john@home~$ netstat -tpln
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:389            0.0.0.0:*               LISTEN
        

You can see the “/Program name” column is empty, as this process is owned by another user. Below is the same command run with root privileges, which reveals this information as 1144/slapd.

netstat -tpl
           john@home~$ netstat -tpln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:389            0.0.0.0:*               LISTEN      1144/slapd
        

netstat -i shows interface statistics.

netstat -i
           john@home~$ netstat -i
Kernel Interface table
Iface      MTU    RX-OK RX-ERR RX-DRP RX-OVR    TX-OK TX-ERR TX-DRP TX-OVR Flg
docker0   1500        0      0      0 0            72      0      0      0 BMRU
ens5      9001    75667      0      0 0         54412      0      0      0 BMRU
        

The netstat usage you will probably see most often in blog posts, write-ups, and courses is netstat -ano which could be broken down as follows;

  • -a: Display all sockets
  • -n: Do not resolve names
  • -o: Display timers
netstat -ano
           john@home:~$ netstat -ano
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       Timer
tcp        0      0 0.0.0.0:389             0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 127.0.0.1:5432          0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 127.0.0.1:5433          0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:53              0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:5901            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 0.0.0.0:6001            0.0.0.0:*               LISTEN      off (0.00/0/0)
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN
        

On modern Linux distributions, netstat has been replaced by the ss command. The core is mainly the same, with some subtle differences, like routing information being moved to IP, and some new functionality being added. As an example, ss -tpl is the equivalent of netstat -tpl. netstat still exists as part of the net-tools package.

Answer the questions below

What is the name of the network interface, other than loopback?

What port, other than 22, is listening on the host?

In this task, you will expand your already existing knowledge of ls and find to locate sensitive files on Linux systems.

The ls Command

One of the common commands used in is probably ls. While looking for potential privilege escalation vectors, remember to always use the ls command with the -la parameter. The example below shows how the “secret.txt” file can easily be missed using the ls or ls -l commands.

ls
           john@home:~$ ls
john@home:~$ ls -l
total 0
john@home~$ ls -la
total 24
drwxrwxrwt  4 root  root  4096 Feb 16 04:36 .
drwxr-xr-x 23 root  root  4096 Jun 18  2021 ..
drwxrwxrwt  2 root  root  4096 Feb 16 04:25 .ICE-unix
-rw-rw-r--  1 karen karen   23 Feb 16 04:36 .secret.txt
-r--r--r--  1 root  root    11 Feb 16 04:25 .X0-lock
drwxrwxrwt  2 root  root  4096 Feb 16 04:25 .X11-unix
john@home:~$ cat .secret.txt
This is a secret file.
        

The find Command

Searching the target system for important information and potential privilege escalation vectors can be fruitful. The built-in find command is useful and worth keeping in your arsenal.

Below are some useful examples for the find command.

Find files:

  • find . -name flag1.txt finds the file named “flag1.txt” in the current directory and subdirectories recursively
  • find /home -name flag1.txt finds the file names “flag1.txt” in the /home directory and subdirectories recursively
  • find / -type d -name config finds the directory named config under “/”
  • find / -type f -perm 0777 finds files with the 777 permissions (files readable, writable, and executable by all users)
  • find / -perm -a=x finds executable files
  • find /home -user frank finds all files for user “frank” under “/home”
  • find / -mtime -10 finds files that were modified in the last 10 days
  • find / -atime -10 finds files that were accessed in the last 10 days
  • find / -cmin -60 finds files changed within the last hour (60 minutes)
  • find / -amin -60 finds files accessed within the last hour (60 minutes)
  • find / -size +50M finds files with at least 50 MB size

This command can also be used with (+) and (-) signs to specify a file that is larger or smaller than the given size.

find / -size +100M
           john@home:~$ find / -size +100M
/john/.ZAP/plugin/ZAP_2.15.0_Linux.tar.gz
/john/.gradle/wrapper/dists/gradle-6.8-bin/1jblhjyydfkclfzx1agp92nyl/gradle-6.8-bin.zip
        

The example above returns files that are larger than 100 MB. It is important to note that the find command tends to generate errors, which sometimes makes the output hard to read. To address this, we can use 2>/dev/null, which sends errors to /dev/null, effectively ignoring them.

Folders and files that can be written to or executed from:

  • find / -writable -type d 2>/dev/null finds world-writeable folders.
  • find / -perm -222 -type d 2>/dev/null finds world-writeable folders.
  • find / -perm -o w -type d 2>/dev/null finds world-writeable folders.

The reason you see three different find commands that could potentially lead to the same result can be seen in the manual document. As you can see below, the perm parameter affects the way find works.

-perm usage
                  -perm mode
              File's  permission  bits  are  exactly mode (octal or symbolic).
              Since an exact match is required, if you want to use  this  form
              for  symbolic  modes,  you  may have to specify a rather complex
              mode string.  For example `-perm  g=w'  will  only  match  files
              which  have  mode 0020 (that is, ones for which group write per\u2010
              mission is the only permission set).  It is more likely that you
              will want to use the `/' or `-' forms, for example `-perm -g=w',
              which matches any file with group write permission.  See the EX\u2010
              AMPLES section for some illustrative examples.

       -perm -mode
              All  of the permission bits mode are set for the file.  Symbolic
              modes are accepted in this form, and this is usually the way  in
              which  you would want to use them.  You must specify `u', `g' or
              `o' if you use a symbolic mode.  See the  EXAMPLES  section  for
              some illustrative examples.

       -perm /mode
              Any  of the permission bits mode are set for the file.  Symbolic
              modes are accepted in this form.  You must specify `u',  `g'  or
              `o'  if  you  use a symbolic mode.  See the EXAMPLES section for
              some illustrative examples.
        
  • find / -perm -o x -type d 2>/dev/null finds world-executable folders

Find development tools and supported languages:

  • find / -name perl*
  • find / -name python*
  • find / -name gcc*

Wildcards can be used when you don't know the exact name of a file you are looking for. Say, for example, you want to find a text file containing passwords. You could use the following command.

  • find / -name pass*.txt

The command above will find file names such as pass.txt, password.txt, passwords.txt, etc.

Below is a short example used to find files that have the SUID bit set. The SUID bit allows the file to run with the privilege level of the account that owns it, rather than the account that runs it. 

  • find / -perm -u=s -type f 2>/dev/null finds files with the SUID bit, which allows us to run the file with a higher privilege level than the current user.
Answer the questions below

What are the contents of the secret file in your home folder?

Find a file that has TryHackMe in its name. What is its content?

In this room, you've learned:

  • How to find information about the system you are targeting
  • How to enumerate local users
  • How to leverage ifconfig and netstat to gain information on network connections
  • How to find interesting or hidden files on Linux systems

As you could see, there is a lot of information to be gained about a target system that doesn't necessarily give you a clear-cut escalation path, but does aid in your privilege escalation efforts. Please spend some time getting comfortable with commands such as find, locate, grep, cut, sort, etc.

Answer the questions below

Enumeration done.