If you're looking for a more detailed methodology for navigating OSCP boxes, check out. The tips here are some quick tricks to try when you are running out of ideas.
General Tips (Applicable to all OS)
Initial Foothold
Initial Scans & Enum:
Scans can sometimes return false positives or missing ports due to different reasons.
Revert all the machines at the start of the exam.
Revert & rescan the machines midway through your exam, especially when you cannot find a way through.
OSCP is an enumeration exam, so there will be a lot of intentionally misleading paths and dead ends (rabbit holes). Moreover, the actual solution is usually broken into partial clues scattered across different services, such as a username on Port 80 (web page) and a password in a file on Port 21 (FTP).
Don’t spend too much time at the same location - Make sure you have covered every other area first.
Take thorough notes during your enumeration so you can piece the puzzle together.
NEVER forget about UDP Ports! There could be vulnerable UDP services such as SNMP (running on Port 161/162).
Do a quick UDP scan and look for open ports.
Ports with open | filtered status are likely just filtered ports.
sudo nmap <ip> -F -sU -vv
If a port's service cannot be identified by Nmap, use netcat or telnet to manually interact with the port.
Send random strings (and press enter) to see if the port responds.
Send common command strings such as help or ls to check if the port is serving some sort of terminals.
Send GET / HTTP 1.1, press enter, and send Host: test, and press enter twice to see if it is running a web server. Alternative, try curl or wget on the port (http://<ip>:><port>).
This will less likely work since Nmap would usually pick this up. You can try it regardless if nothing else work.
Shells & Connections:
Always prioritize using open ports on the target machine for listening to reverse shells (i.e., the listening port on our Kali when running netcat listener.)
Open ports on the target machine are more likely to have exceptions for inbound & outbound connections.
Alternatively, try common ports: 21, 22, 139, 445, 80, 443, 3389, etc.
Port 4444 is usually blocked for security reasons.
Remember to add potential hostnames & domains into our local kali's /etc/hosts file.
If this is the intended path, you will likely see emails / URLs on the web pages that give you information on the hostname / domain.
It is also possible that the box name / service name is used as the hostname.
This may reveal pages with hostname restrictions, or pages behind virtual hosts.
Also, try enumerate the web pages before adding the hostname. The server may react differently to different hostnames, or no hostname.
File Shares:
When there is a file share (e.g., SMB / FTP) and a web server running together on the machine, always check if the web server hosted under the file share's directory. If that's the case, check if we can:
Upload a web shell to the file share, and trigger it via the web page.
Read sensitive config files and look for credentials to access the web page.
Tools like NetExec are extremely useful, but they can sometimes be inaccurate. I once checked an SMB share with NetExec, and it indicated that I only had read access to the share. However, I was able to upload files to the SMB shareregardless.
Always try using commands like PUT to test if you can upload any files. A quick check like this may save you hours of scratching your head, wondering what went wrong!
File shares can often run on weak / default credentials. A quick check never hurts.
ftp:ftp
admin:admin
anonymous:anonymous (Or simple just no password)
Web Services:
Here are all my directory busting tips and tricks:
Try 2 or more different directory busting tools, as well as wordlists. Personally I use FeroxBuster and DirSearch , with /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt , directory-list-2.3-medium.txt and directory-list-2.3-big.txt.
Always do recursive directory busting.
FeroxBuster does this by default, but it can be slow sometimes.
Try add file extensions (e.g., .pdf, .php, etc.) if the initial busting returns nothing.
For example, /index may returns 404, but /index.php may returns 200.
Try add box name / service name / username as the first directory.
For example, if you suspect WordPress is running on the web server, but you can't find anything, try do directory busting with this base URL instead: example.com/wordpress/.
For Directory-like results that do not show as "Open Directory Listing " (e.g., example.com/test/), always try visit the URL anyway, as some pages are configured with hidden index pages.
Always perform subdomain enumeration. I find this less common in OffSec's Proving Ground (PG) boxes, but very common in HTB & TryHackMe boxes.
There could be hidden admin panels, API endpoints, sites that are still in development (.git lying somewhere maybe?), etc.
Always remember to perform directory busting on the newly discovered subdomain endpoints.
The .git directory is a gold mine if you found it via directory busting. Some wordlists may miss it, so make sure you run multiple wordlists and tools.
Suppose the .git directory is located at example.com/.git/:
git-dumper http://example.com ./output_folder
Read through the source codes to look for hard-coded credentials, session tokens, or vulnerable codes such as LFI & SQL injections.
Use git show and git diff to look for commit changes. There may be credentials that were deleted, but were logged in the commit changes.
Always look for potential usernames / emails / credentials on page contents.
Understand all functionalities, such as user login, file upload, etc, so that you can focus on or skip relevant attack vectors based on the existing functions.
Don't just spam 'OR 1=1 -- // for potential SQL injections, as SQLi is not always about authentication bypass. Here are a few SQL injections tips & tricks:
Using ' is the most common way to test for error-based SQL injections. However, don't miss out on Blind SQLi (with sleep /delay functions).
If SQL injection is possible, try the following items:
Authentication Bypass
Remote Code Execution
Dumping Database Info
System File Read / File Write
Pay attention to the SQL service in use, as different SQL services have different syntaxes.
For example, commenting out is -- - in MSSQL, but -- // in MySQL.
There is a lot that we can look for with local file read vulnerability.
/etc/passwd & /etc/shadow files on Linux.
SSH Keys (Usually located under /home/<user>/.ssh on Linux, or C:\Users\<user>\.ssh on Windows. They can also be on the user's Desktop, or other similar folders.)
Especially when you see SSH is up on the server.
Config files (Especially for web servers & file shares)
May require some research on the services in use. Go through the documentations if needed.
.htaccess is one of the most common config files that contains useful information. It usually lies on the web root.
Log Files (E.g., Access Logs, Error Logs, etc.)
History Files (E.g., Bash History, PowerShell History)
If file write is possible, there are usually 2 scenarios:
We can write and access a web shell.
Look for an accessible web directory that we can visit and trigger the web shell.
For PHP apps, if phpinfo() is present, we can check the full web directory path.
For Linux, try /var/www/html/as the web root.
We can overwrite some important system files and bypass authentication.
E.g., Overwriting the SSH public key with our public key.
E.g., Appending a new root user to the /etc/passwd file.
E.g., Rewriting the .htaccess to bypass access restrictions, and allow uploading & execution of certain file extensions (e.g., .php).
If file upload is possible, there are usually 4 scenarios:
We can upload and access a web shell / reverse shell (May require restriction bypass).
We can overwrite some important system files and bypass authentication.
E.g., Overwriting the SSH public key with our public key.
We can upload a malicious file and wait for user interactions.
Less likely in the exam - and there should be hints if it is intended (e.g., "An administrator will review this file.")
It is a rabbit hole :'(
Try switching between different HTTP request methods (e.g., GET / POST) to see if the server responds differently. Detailed error messages may return, etc.
Try changing a GET request to a POST request, and vice versa.
Supply some random parameter values (e.g., GET /index.php?test=123) to check if the server responds with hints on the correct parameters.
Databases:
Always check if the SQL service allows file read / write. Follow the same tips on exploiting file read & write in the Web Service section.
For MSSQL:
File Read
SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents
SELECT "<?php echo shell_exec($_GET['cmd']);?>" INTO OUTFILE '/var/www/html/webshell.php';
If misconfigured, it is possible to execute system-level commands via SQL services.
For MSSQL, we can use xp_cmdshell to execute commands if it is enabled, or if we can enable it.
EXECUTE xp_cmdshell 'whoami';
For MySQL, user-defined functions (UDF) are required to execute system commands, and it is mostly used during privilege escalation, not initial access.
Suppose you have obtained access to the SQL database, always check the non-default databases and tables to look for user credentials.
For examples, many CMS store user password hashes in a users table. We can dump the hashes and crack them to obtain plaintext passwords.
For MySQL, we should also dump the MySQL user credentials with the following command:
SELECT * FROM mysql.user;
Login & Password Attacks:
Always try default or weak credentials - admin / admin, admin / password, you name it. These are easy quick wins and should always be tried first before doing any hard work.
Google the service name & version + default credentials.
Try admin:admin and all those similar stuff.
It is always possible that the passwords are configured conveniently as the username or the service's name.
Spray the usernames as passwords.
E.g., john:john, mary:mary, etc.
Also, try use service names as passwords.
E.g., for Tomcat, use tomcat:tomcat, for FTP, use ftp:ftp, etc.
While it is unlikely for many cases, it never hurts to run some quick brute-force attacks, especially when you have run out of ideas.
Run a quick brute-force login attack with rockyou.txt on available services. If this is intended, it should be cracked right away (or at least under 10-20 minutes).
Public Exploits:
When in doubt, revert the machine.
Sometimes our previous exploitation attempts may have caused unexpected behaviours in the target machine.
I once tried to set up some port-forwarding rules on the machine to run an exploit, but I was using the wrong exploit, so the attack did not work. I later found and ran the correct exploit, but it was not working as intended, likely due to the previous port-forwarding attempts. Reverting the machine solved the issue.
If the exploit does not specify "Authenticated", try running it without authentication.
For example, it is possible that we can directly send a crafted HTTP request to an internal endpoint without needing to be logged in.
Try adding http:// to the URL parameter if the web exploit is not working.
E.g., 192.168.1.1 --> http://192.168.1.1.
As some exploits are written with a full URL target in mind.
Always read through the exploit codes to understand how the payload is crafted.
For some vulnerabilities, there may be multiple available exploits online. I always recommend to try out the simpler ones first, as the more complex ones can be much more difficult to debug.
Even when the simpler ones do not work for the first time, I would go through the exploit codes to make sure I am not making mistakes in supplying the arguments, haven't clean up the exploit codes, etc.
There may also be multiple exploits on the same attack vector. For example, a particular version of a CMS can have both a File Read vulnerability and an Authentication Bypass vulnerability. It will never be a bad idea to try both, but it is better to try understanding what exactly are we looking for in the attack.
Try to encode your payloads in different formats when they are not working (and you believe they are supposed to).
Always URL-encode the payloads for web exploits, especially those that are sent through URLs (GET requests).
Here is another example payload of inject a command into a Linux file name:
Always run multiple different enumeration scripts when stuck.
For example, I always run WinPEAS, PowerUp.ps1, and jaws-enum.ps1 on a Windows target, as each of them has a different way of presenting their output, and they sometimes use different methods in checking the same vulnerabilities.
This also helps to filter out potential false positives.
Sometimes the automated scripts (or the exploits) may have given you what you need, they may just be right under your nose. Always re-read the output line-by-line if you are stuck!
I was once stuck for more than hours on a pivoted user, as I can't find anything useful on their directories, nor authenticating to other services. I finally gave up and re-ran WinPEAS for the last time, and I realize there was a credential stored in the registry, and I had missed that line of output the whole time.
Services:
Don't sleep on the service version when performing privilege escalations. The attack path could be to exploit an outdated and vulnerable internal application with publicly available exploits.
You can check them either by interacting with the binary in CLI (e.g., adding -h), or running the application in GUI and check the about section.
Login & Password Attacks:
SSH keys can be sprayed both externally and internally.
Some SSH keys may be configured to only work in the internal network, or even in the local machine (127.0.0.1). If spraying them externally does not return anything, try to spray them again internally. For example, run this command on the target machine:
ssh root@127.0.0.1 -i id_rsa
Sensitive Information:
Always enumerate config files for more credentials, even after you obtained an initial shell.
Say if you uploaded a web shell and has successfully obtained a shell as www-root. We should always go back to the web server directory and go through all the readable config files to look for hard-coded credentials. In many cases, we may find database connection credentials that were previously unknown to us.
As password reuse is very common, we can try to use the obtained credentials as is, or we can also spray the password to other usernames to see if different users share the same password.
Through enumeration is always the key. Don't skip any potentially interesting files!
I have once found the root password within a mail file in the /var/mail directory, which usually does not contain any files.
Pivoting:
Quite often the attack path can involve lateral movements between multiple users, before reaching the final root account. So if you see more than one users in under the /home or c:\users directory, there is a high likelihood that several lateral movements are needed.
Let's say you obtained a shell as www-data. It is possible that you cannot escalate to root directly from www-data, but instead have to find a password in the web config file, spray that password on a local user john, then you exploit an internal service as john to gain access to another user peter, and finally escalate to root by sudo with peter.
Linux-specific Tips
Privilege Escalation
Services & Processes:
Run strings & strace on suspicious binaries.
This may reveal plaintext passwords, commands, other executables being called, potential Shared Objection injection, etc.
When running ps aux, don't just grep the output from the root user.
Always also grep the processes that belongs to other human users, as we may learn what have other users executed, as well as discover potential credentials used within the command they executed.
Sensitive Information:
Don't forget to run the alias command to check what command alias were set.
In realistic scenarios, system administrators may have created command alias for commonly used commands, and some of these commands may contain user credentials.
Always check the /media, /mnt and /opt directories for uncommon applications and files.
The /opt directory often contains non-standard installations of services, or directories that contain sensitive information.
While less commonly seen, the /media and /mnt directories sometimes contain juicy files, such as USB drives, mounted NFS shares, etc.
The /tmp folder is also always worth checking.
For all sorts of compressed & archived files, we can use the binwalk command to read the archives within the file:
binwalk [filename]
Since spreadsheet files such as .xlsx and .xlsm are just compressed files, we can read the Marcos in the format of XML files by extracting them from the excel files.
We can do this to extract all files from the XLSM file:
binwalk -e [filename]
Group Membership:
Group Membership can be a privilege escalation vector if our user belongs to some of the privileged groups. Also check if other users are in these interesting groups, as they may be the target for lateral movements.
Common privileged groups on Linux:
LXC / LXD (Abusing Container Privileges)
Docker (Abusing Container Privileges)
Disk (Full File Read & Write Privileges)
ADM (Privileges to Read Logs)
Scheduled Tasks / Cron Jobs:
We can monitor all live running processes without needing root privileges. This is extremely useful for detecting cronjobs that runs in a fixed interval (e.g., 1 minute),
This is especially useful when we do not have access to crontab, or crontab is not showing anything but we suspect there are cronjobs.
Sometimes we may not have visibility on the processes and crontabs to validate if there are any cronjobs running. However, we should always look for any suspicious script files within the system.
It is possible that the root user is running that particular script file as a cronjob, but we just don't have the visibility on the actual running process.
When exploiting cronjobs, a common attack technique is to use the root privilege to create a copy of the Bash binary and adding the SUID bit to that copied binary. Below is an example payload:
cp /bin/bash /tmp/bash & chmod +s /tmp/bash
However, I have found this payload occasionally not working.
Here are some other alternative payloads you can run:
One, simply adding the SUID bit to the /bin/bash binary directly:
chmod u+s /bin/bash
Two, create a reverse shell to your Netcat listener. The connected shell will be running as root:
Suppose this is the intended attack path, there should be hints on locations and areas that users may visit and interact with.
For example, there may be a feedback form with a note saying that the administrator will go through all of the comments.
Alternatively, it is also possible that we can force an NTLM theft without needing the user to react to our payloads. Try to look for user input areas where we can direct the connection towards our controlled SMB server, for examples:
xp_dirtree in MSSQL.
File Inclusion that allows visiting an SMB share.
A function that will visit any URLs (including SMB URIs).
Shells & Connections:
When running a Windows reverse Shells, always use the PowerShell Base64 payload, as it has the highest success rate.
Since the payload is Base64 encoded, it has the lowest risk of being corrupted midway during transmission.
If a Windows payload is not working, we can try changing forward slashes (/) to backslashes (\), and vice versa.
Different tools and exploits may be crafted in different languages and formats, so that the format of slashes are not consistent across them.
Privilege Escalation
Kernel Exploits:
If we are certain that the kernel is vulnerable, we should always try to run a few different applicable exploits, since not all of them may work due to multiple reasons.
For older Windows Systems (e.g., Windows 7), they are most likely to be vulnerable to the well-known SMB exploits.
We can run a Nmap SMB scripts can them to check if they are vulnerable.
nmap -vv -p 139,445 --script smb* <ip>
nmap -vv -p 139,445 --script smb-vuln-ms* <ip>
Sometimes the first script scan may miss some of the scripts like MS-17010. Just run both to be safe.
Since the older systems are severely out-of-date, they may look vulnerable to multiple vulnerabilities. However, some of them may be patched and could be rabbit holes.
Don't stay on one exploit for too long if it does not work. Retry the previous ones, or move on to new ones.
Group Memberships:
Sometimes we may have compromised a LOCAL SERVICE or NETWORK SERVICE account, but its privileges were missing. This is because the account may be configured to be running with a restricted sets of privileges.
It is possible to recover its permissions by creating a scheduled task. The new process created by the Task Scheduler Service will have all the default privileges of the associated user account.
Use to dump the .git directory (Amazing tool).
For Linux: /proc files. (See more )
Here's an example of a PoC that looks like an authenticated exploit, but it can actually be used without authentication: .
is the best tool to monitor all processes and potential cronjobs on a Linux machine.
Moreover, the exploitation techniques in are not limited to sudo & SUID attacks only. As long as the process or binary can be executed by root (here via root-user Cronjobs), we can apply the same technique to escalate our privileges.