Oct 12, 2019
Nov 14, 2020
Overall a nice simple box from HTB. The machine was relatively easy with an out-of-the-box CMS exploit for user and an interesting login behavior abuse to pivot to root. I'll cover both the proper exploits but also a few of my /facepalm moments throughout the experience.
The machine's IP was 10.10.10.138. Let's start off with an nmap enumaration and see what we can find
Alright, SSH and potential web-service. Let's pop over to the browser and see what we can find
Nothing too useful. Let's open up burpsuite and see if we can find anything else of use through here. We do a quick spider and end up with the following.
That's a bit better! We even see index.php that accepts a page parameter. This is starting to look promising. Wait, we didn't see anything of that useful on the main page, how did our spider result get /writeup? Oh there we go, look at robots.txt:
Lesson learned regarding checking everything - always check robots.txt for any leftover crumbs. Let's not make that same mistake twice and go through the source code of the newly discovered writeup/index.php page and see what we can come up with.
This seems interesting. From previous experience we know there are a quite a few CMS related exploits. While we don't see the exact version used here we can initially assume that it is a version released sometime in 2019. Let's see what searchploit has for us.
Geez still a large field. Alright, let's ignore the modules and focus on only the core CMS Made Simple since we don't have any more hints as to what is actually installed. With our assumption that we are working with a version released in 2019 let's take a look at CMS Made Simple < 2.2.10 - SQL Injection a little more closely and see if it will be useful for us.
The exploit's functions all repeat a similar pattern for salt, username, email and password. Let's step through one of those and understand what is going on.
Simply put the exploit iterates through the list of characters, attempting to compare to the actual username. When the character matches the stored username the nested sleep function is also triggered - causing the request to take longer than an unsuccessful request by a measure of TIME defined in the code. sqlinject.net explains this concept:
The attacker may also be interested to extract some information or at least verify a few assumptions. ... this can be done by integrating the time delay inside a conditional statement.
By capturing the elapsed_time while executing the payload we can determine the right first character when the query takes TIME more time. Once successful, the loop stores that character and moves on to the next - repeating the process until no further characters trigger the sleep function, letting us know we have the full value.
Alright enough theory - let's run the exploit and hope for the best.
Bingo, user creds! So here is a proud facepalm moment. Prior to above run, I ran the exploit without --crack or --wordlist and got the same output as above without the password cracked output. In my momentary ignorance I completely ignored that this even looked like a hash, took that line of output verbatim and actually thought this was the password. As you can see below clearly that did not get me far.
Thankfully I quickly realized my error and ran the cracked variant. Just like that we have user access through SSH.
the usual initial checks did not return anything interesting - sudoers list, running processes, initial poking around at the files. Decided to get a few helper scripts over to the host and see if anything else would come up.
Left pspy running in a terminal while I continued to poke around. There were a few other folks on the machine around the same time as me. At first I didn't think pspy would return anything useful, then I saw a few more people log on and something interesting happened.
So what is happening here? Looks like on SSH connection a logon function gets triggered. I wasn't completely familiar with the various options and flags so took a look at the man pages.
Ok so breaking it down: As root, clear out environment variables, set PATH then execute run-parts. Similarly let's look at run-parts' options. You may already know where I went wrong but let's follow my logic as I stepped through.
"run scripts or programs in a directory" huh? That sounds amazingly like something we would want to happen. If we could add our own script within /etc/update-motd.d we could trigger it to be executed by root anytime someone ssh'd in to the host. Unfortunately we did not have write capabilities to that folder as jkr and after beating my head against the keyboard for a few minutes I took a step back.
That's when I realized my mistake... take a look at the pspy output again. How is run-parts being run? Explicit location or...relative location! Since we know exactly what PATH is being set to all we have to do is write our own run-parts in one of the PATH locations prior to its regular location. While we didn't have read entitlements at /usr/local/sbin we did have write entitlements. Since I knew the location of the root flag I decided to skip doing anything fancy like a reverse shell and K.I.S.S.
Now simply open a new terminal and let's hope that everything went smoothly.
And just like that Writeup is officially in the books.
At some point during the pspy enumeration phase I captured what I can only assume was someone utterly exasperated. Unfortunately for them I was too busy trying to get to the end of this box.