HackTheBox - Feline - Active
Recon
Let's use threader3000 for our recon scan. It's a threaded scanner written in python that does a super quick up/down scan on all TCP ports, then suggests a nmap scan based on the results. It will automatically save the nmap scan results as XML, then we can convert it to HTML
Looks like we have just two open ports 22 and 8080
That's a very new version of OpenSSH, let's see what we are served on port 8080
Looks like a site that would be very similar to VirusTotal.
Let's try to brute force this to see if we can find some other pages to look at
Here is what it found
Service sounds promising Let's check it out
Looks like this is the upload feature to submit samples to the service, If we try to upload multiple types of files we can see, we can't upload .php but were successful in uploading .py, .jar, .sh
Exploit
Googling around for Tomcat 9.0.27 exploits we come across this blog
It basically says if the "Persistent Manager" is enabled on tomcat and there is a way to put files on a server, then through a JSON deserialization attack we can get a RCE on the box.
So what I gather normally is that the cookie is just compared against current sessions, so It takes the value supplied in the cookie JSESSIONID and checks for current sessions and stop there. However with "persistent manager", it keeps going and checks on the disk for the session. Further than that it doesn't sanitize the value to make sure it would be a valid session, These two things combined allow us to pass a file path to the JSESSIONID which the server will then deserialize and execute what is in the file.
That seems bad mmkay
So we know that we can upload files to the server using their "analysis" service. If we send it serialized JSON files with command and then use the JSESSIONID to point to that file it will hopefully run what command we set.
Let me just say this part is a bear because we have two different blind options going here.
We don't know the format the JSON wants to decode
We don't know where the uploaded files land on the server after upload.
For number 1, we can use a tool that will automatically format our command in a bunch of different formats and just try them.
For number 2, it's going to just be a guessing game on the directory, we do see an error message in burpsuite that might shed some light on location.
As we found in our recon we aren't allowed to upload PHP files using the tool provided, but if we capture the response in burpsuite we can see this .
It looks like the process of "analyzing" puts the uploaded file in /opt/tomcat/temp/ for a bit.
If we try our deserialization attack on this location it doesn't fire. So it seems this is just a temporary location before it saves the "samples" somewhere else.
But through some educated guesses and a lot of time we can figure out the location of the final resetting place for the uploaded files.
I'm not going to lie here, this part took absolutely forever, since we didn't know what type of JSON to make and where it ended up.
We can at least use a tool to help us with the first part. That tool is called ysoserial.
https://github.com/frohoff/ysoserial
It's pretty simple to use.
The basic syntax is
So a basic command might look like
With beanshell1 being one of the roughly 30 gadgets the tool has for generating types of JSON payloads.
I found this script on another site.
https://securitycafe.ro/2017/11/03/tricking-java-serialization-for-a-treat/
It basically just goes through and creates a JSON for every type of payload ysoserial has.
I modified it a bit to write them out to files that we could then upload, and to only do the linux command since we are up against an ubuntu box.
So this creates a .session file for every type of gadget and writes it to a file we can then upload.
Next step was to figure out a way to upload the files in a python script.
If we google for curl upload we find this
https://medium.com/@petehouston/upload-files-with-curl-93064dcccc76
We can use the -F option with curl to upload a file hopefully, again we want to script this in python so that we can automate the process.
I'm sure there is a way I could have down this directly with python but we know curl and we can just os.system to call curl
And then we need to figure out a way to automate giving it our modified JSESSIONID, again python to the rescue.
Now that we can automatically generate all the types of payloads, upload them and then try execution on them let's combine all these into one script
It's ugly but I think it should work. I purposefully built each part out in a function that should make it easier to combine all the scripts together.
Here is what I came up with
It will take two user inputs, the first being the location we want to use to try and execute the file and the second being the command we want to place inside the json files.
So the syntax would be
Here is the moment of truth we are going to stick with a ping as our proof of concept here since we can use tcpdump to listen on our VPN IP to see if we get any code execution, and we are just going to blindly guess at the location path until we get some pings.
Let's start our listener
And start poking around for the location.
Well no pings with the first location we tried from what we found in our burpsuite response earlier.
I probably literally tried about a dozen different locations before I found the right path for the files.
I tried variations on sample, upload and different paths like /tmp /opt eventually we stumble blindly on one that works
That is more than just 4 pings like we put in our command so it looks like more than one of the serialization gadgets worked.
At this point we really don't care which one works we have a POC that our script works we were able to find a gadget that encoded correctly, upload it and then get execution using the JSESSIONSID
Immediately I tried just to do a netcat reverse shell.
First let's set up our listener
Then try this command
No dice
We can try some other one line reverse shells like
But no shell back with those either, so it lets us run ping but it's not letting us run these other commands.
Maybe there is some sort of execution block going on or a permissions issue.
I fought with this for hours and still couldn't get it fire from this script… so let's change tactics.
From tinkering and fighting to get this to work I think there is an issue with the way ysoserial uses the quotes for the command input that is screwing up more complicated commands. I also discovered that "CommonsCollections2" is one of the formats that works.
So let's do this, let's use wget to download a shell script to the temp directory on feline, then
Then use our serialized json to run that script… sound simple right? I've modified my python script again to be smaller so we don't have to wait as long for the attempts to run.
Now we need to make a shell script to serve over to feline
Then we start up updog to serve the file
We still accept the two inputs with our new minimal python script so the first command we want to give is to wget our .sh file we name rshell.sh and save it to the /tmp folder
And we can see in our updog session that it did reach out and grab the file.
Now we just need to set up our listener again and run the command to execute that script.
Now execute again using the minimal.py
And we finally have our foothold
And from here we can get to the /home/tomcat directory and read the user.txt flag
Now let's figure out how to escalate to root… if we can :)
Poking around in the file system it doesn't look like it was renaming our uploads after all.
Here in the upload.jsp we can see it was writing samples to /opt/samples/uploads
Now let's check out what's running to see if we can find a path forward.
Let's upload linpeas.sh to the box using our running updog
Then give it execute rights
Then run it using ./linpeas.sh
Not much right off the bat, that I see however looking at some open ports we see something that we didn't see from the outside…
Ports 4505 and 4506… what use those ports?
A quick google search later you find that one possibility is salt
https://docs.saltstack.com/en/getstarted/system/communication.html
And a further search on salt shows a vulnerability.
https://github.com/jasperla/CVE-2020-11651-poc
First let's upgrade to a tty shell using python3
Better.
In order for the salt POC to work we are going to need to have access to port 4506, which is apparently firewalled off to us…
We are going to need to do a tunnel so that our box can access that port, we will use our existing access to feline to create a tunnel to forward our traffic to the ports we don't have access to.
For this we might normally use an SSH tunnel if we have creds to use SSH, but we don't so we are going to use a tool called Chisel.
To install chisel
https://github.com/jpillora/chisel
We need to clone the repo
Since this application is a go application we are going to need to install golang too, if we don't have it already.
Then from the new cloned repo directory we just build the application
Now we should have an executable
Let's use our existing updog connect to wget this onto feline, we need to copy this executable to the same directory we are running updog from
Then on feline we download chisel
** you might notice my VPN IP changed here, i had to take a break and pick this up the next day**
Now we need to give chisel execution rights on feline
If you aren't super familiar with chisel you might take a break here and do some googling
Ok now we need to start the chisel server on our kali box
Then on feline we need to forward the port
Now we can see on our kali box that we were successful in setting up our tunnel
So we started a chisel server on kali on port 8000, then on feline we said connect to port 8000 on kali using chisel and send the request to port 8001 to local port 4506 on feline
Now we can test that exploit we found earlier for salt.
Great, the exploit was able to connect and obtain the root key so this looks like a viable path forward.
This exploit allows us to run commands using the --exec switch which accepts a command inside of quotes just like ysoserial, which is going to give us problems again, so let's solve it exactly like we did before, use the exploit to download a file to a location we can control with a bash script for a reverse shell then execute it.
To that end let's set up another listener and another bash script file.
We will use our existing updog server again to serve up our bash script
It's almost an exact copy of our previous shell script, just a different port
We first download the script using wget
Then we give it execution rights
Then run the script
For some reason, mkfifo wouldn't fire. So I modified the rshell5666.sh to use just a bash reverse shell instead.
We are in as root….. But something looks off here, look at the machine name I expected that to say feline.
There is a todo.txt here, let's read it
So we are in a docker here for salt
Geez this box is hard
Ok so we are in a docker container for salt with root privileges for this container
Let's google around for a way to escape out of docker to our host.
I at first went down a path of trying to exploit docker.sock but didn't have much luck. Then I found some blogs about mounting the host file system inside of our container but the docker binary isn't present on the container…… but we can fix that!
Let's use wget on our kali box to download a copy of docker.
Then unzip it.
Now let's move the docker binary to the folder we are running updog in.
Then on the docker container on feline that we have, let's use wget to download it to the /tmp folder.
And give it execution rights.
So problem solved, this container now has the docker binary.
So now thanks to the nature of docker we can mount a folder of the host into our container.
This will mount the /root folder of the host on our container in /mnt
Comments
Post a Comment