CMSeeK is a modern, Python 3-based CMS detection and exploitation framework. Unlike WPScan or JoomScan, which are dedicated to a single platform, CMSeeK is designed as a universal CMS fingerprinting tool, capable of identifying more than 180 different Content Management Systems using a signature-detection engine (built on top of the CMSeeK detection database, which is compatible with the widely-used whatcms/cms-detector style signature format).
For the most common and high-value CMS platforms — WordPress, Joomla, Drupal, Magento, PrestaShop, OpenCart, and others — CMSeeK goes a step further and triggers dedicated deep-scan modules that extract:
- CMS name, version, and detection confidence
- Users/authors (where applicable)
- Installed plugins/themes/extensions and their versions
- Known vulnerabilities associated with the detected CMS/version
- Server technology stack (PHP version, web server, etc.)
- robots.txt and admin panel discovery
- Whether the target is running behind a CDN/WAF
CMSeeK is typically the first tool run in a CMS security workflow because of its speed and broad platform coverage — its output determines which CMS-specific deep-scan tool (WPScan, JoomScan, Droopescan) should be used next.
Key Features
- Detects 180+ CMS platforms via signature matching
- Deep-scan modules for major platforms (WordPress, Joomla, Drupal, Magento, etc.)
- Result caching in structured JSON per target for easy automation/integration
- Bulk scanning support via list input
- Update mechanism to refresh CMS detection signatures
- Lightweight and fast compared to full CMS-specific scanners — ideal for the initial triage phase
Installation
CMSeeK is not always pre-installed by default on every Kali image, so it is commonly installed manually. Verify first:
cmseek --version
If missing, install from the official GitHub repository (the standard installation method for this tool):
Method 1 – Git Clone (Official Method)
sudo apt update
sudo apt install git python3 python3-pip -y
git clone https://github.com/Tuhinshubhra/CMSeeK.git
cd CMSeeK
sudo pip3 install -r requirements.txt --break-system-packages
Run it from within the cloned directory:
python3 cmseek.py --version
Method 2 – Kali Package (if available in your repository release)
sudo apt update
sudo apt install cmseek -y
Method 3 – Create a Global Symlink for Convenience
cd CMSeeK
chmod +x cmseek.py
sudo ln -s "$(pwd)/cmseek.py" /usr/local/bin/cmseek
cmseek --version
Post-Installation: Updating Signatures
python3 cmseek.py --update
Expected output:
[+] Checking for updates...
[+] CMSeeK is up to date! (v1.1.3)
Syntax
General syntax:
python3 cmseek.py -u <target-url> [options]
(or cmseek -u <target-url> [options] if symlinked globally)
Basic example:
cmseek -u http://target-site.com
All Command-Line Options
Target Options
| Option | Description |
|---|---|
-u, --url <url> | Target URL to scan |
-l, --list <file> | File containing a list of target URLs for bulk scanning |
--random-agent | Use a random User-Agent header |
--user-agent <string> | Set a specific custom User-Agent |
--follow-redirects | Follow HTTP redirects to the final URL |
--no-check-certificate | Disable SSL certificate verification |
--timeout <seconds> | Set the HTTP request timeout |
Scan Behavior
| Option | Description |
|---|---|
-b, --batch | Batch mode — non-interactive scanning (needed for scripting/automation) |
-v, --verbose | Verbose output, shows every request/detection attempt |
--is-wp | Force WordPress deep-scan module regardless of detection |
--is-joomla | Force Joomla deep-scan module |
--is-drupal | Force Drupal deep-scan module |
--wp-enumerate <types> | WordPress-specific enumeration: u (users), p (plugins), vp (vulnerable plugins), vt (vulnerable themes) |
--wp-en-uc | Enumerate WordPress config file backups |
Update & Maintenance
| Option | Description |
|---|---|
--update | Update CMSeeK’s CMS detection signature database |
--clear-cache / --rm | Clear cached scan results |
Output Options
| Option | Description |
|---|---|
-r, --result <path> | View/output the cached JSON result for a previously scanned target |
--no-color | Disable colorized terminal output |
Misc
| Option | Description |
|---|---|
-h, --help | Show help menu |
--version | Show installed version |
Basic Usage
cmseek -u http://target-site.com -b
Expected output (truncated):
▄▄▄▄▄▄▄▄▄▄▄
▐░░░░░░░░░░░▌
▀▀▀▀█░█▀▀▀▀
▐░▌
▐░▌
CMSeeK v1.1.3
CMS Detection and Exploitation Suite
Twitter: @Tuhinshubhra
_______________________________________________________________
[+] Target: http://target-site.com
[+] Checking Connection... OK
[+] Target Server: nginx/1.24.0
[+] Checking Whether Target is Blocking us...NO
[+] Checking For Firewall...NOT DETECTED
[+] Detecting CMS
[+] Target CMS: WordPress
[+] Detected Confidence: 100%
[+] Detected Version: 6.5.3
[+] CMS URL: https://wordpress.org
[+] Handing off to WordPress Deep-Scan Module...
[+] Extracted Meta Generator Tag: WordPress 6.5.3
[+] Results saved at: /home/user/CMSeeK/Result/target-site_com/cms.json
Practical Examples with Output
Example 1 – Basic auto-detect scan in batch (non-interactive) mode
cmseek -u http://target-site.com -b
Output (excerpt):
[+] Target CMS: WordPress
[+] Detected Version: 6.5.3
Example 2 – WordPress deep-scan with plugin/user enumeration
cmseek -u http://target-wp-site.com -b --wp-enumerate up
Output (excerpt):
[+] Enumerating WordPress Users
[+] Found User: admin
[+] Found User: editor01
[+] Enumerating WordPress Plugins
[+] Plugin Found: woocommerce (v8.9.1)
[+] Plugin Found: yoast-seo (v22.5)
Example 3 – Force a specific CMS deep-scan module (useful when auto-detect is inconclusive)
cmseek -u http://target-site.com -b --is-joomla
Output (excerpt):
[+] Forcing Joomla Deep-Scan Module...
[+] Joomla Version Detected: 4.4.2
Example 4 – Bulk scan a list of unknown-CMS targets
cat > mixed_targets.txt << 'EOF'
http://site1.example.com
http://site2.example.com
http://site3.example.com
EOF
cmseek -l mixed_targets.txt -b
Output (excerpt):
[*] Scanning http://site1.example.com
[+] Target CMS: Drupal (v10.1.2)
[*] Scanning http://site2.example.com
[+] Target CMS: Magento (v2.4.6)
[*] Scanning http://site3.example.com
[+] Target CMS: Joomla (v3.10.11)
Example 5 – View cached JSON results from a previous scan
cmseek -r target-site_com
Output (excerpt):
{
"cms_id": "wordpress",
"cms_name": "WordPress",
"cms_url": "https://wordpress.org",
"detection_param": "meta_generator",
"confidence": "100",
"version": "6.5.3",
"server": "nginx/1.24.0"
}
Example 6 – Scan with a random User-Agent and SSL verification disabled (staging/self-signed certs)
cmseek -u https://staging.target-site.com -b --random-agent --no-check-certificate
Example 7 – Verbose mode to inspect every detection attempt (useful for debugging false negatives)
cmseek -u http://target-site.com -b -v
Output (excerpt):
[verbose] Trying signature: joomla -> /administrator/manifests/files/joomla.xml -> 404
[verbose] Trying signature: wordpress -> /wp-login.php -> 200
[verbose] Match found: wordpress
Example 8 – Enumerate WordPress config backups specifically
cmseek -u http://target-wp-site.com -b --wp-en-uc
Output (excerpt):
[+] Checking for Config Backups...
[+] Found: wp-config.php.bak (HTTP 200)
Example 9 – Update signature database before running a fresh engagement
cmseek --update
cmseek -u http://target-site.com -b
Example 10 – Clear cached results before re-scanning a target that has since been patched
cmseek --clear-cache
cmseek -u http://target-site.com -b
Example 11 – Combine with jq to extract only the CMS name and version for a report
cmseek -r target-site_com | jq '{cms: .cms_name, version: .version}'
Output:
{
"cms": "WordPress",
"version": "6.5.3"
}
Example 12 – Full engagement scan: detection + deep-scan + all enumeration flags
cmseek -u http://target-wp-site.com -b --wp-enumerate vp,vt,u --random-agent --timeout 30
Output (excerpt):
[+] Target CMS: WordPress (v6.5.3)
[+] Enumerating Vulnerable Plugins... 2 found
[+] Enumerating Vulnerable Themes... 0 found
[+] Enumerating Users... 3 found
Common Use Cases
- First-pass CMS triage: Quickly determine which CMS platform (out of 180+ possibilities) a target is running before deciding which specialized tool to run next.
- Unknown-CMS environments: In large external attack-surface assessments where the CMS platform per host is unknown, CMSeeK’s bulk-scan mode rapidly categorizes hundreds of hosts.
- Lightweight WordPress/Joomla/Drupal auditing: When a full WPScan/JoomScan run isn’t necessary, CMSeeK’s built-in deep-scan modules provide a fast summary of version, users, and plugins.
- Asset inventory building: Security teams use CMSeeK output (cached as structured JSON) to build and maintain an inventory of CMS platforms and versions across an organization’s web properties.
- Shadow IT discovery: Identifying forgotten or unmanaged CMS installations (old Joomla/Drupal sites) during external reconnaissance.
Automation with Bash
Bulk Triage and Auto-Routing to Specialized Scanners
#!/bin/bash
# cmseek_triage.sh - detect CMS for each target, then route to the right specialized tool
TARGETS="mixed_targets.txt"
mkdir -p triage_results
while IFS= read -r url; do
echo "[*] Detecting CMS for $url"
cmseek -u "$url" -b > /dev/null 2>&1
name=$(echo "$url" | sed -E 's#https?://##; s#[/:]#_#g')
result="$HOME/CMSeeK/Result/${name}/cms.json"
if [ -f "$result" ]; then
cms=$(jq -r '.cms_id' "$result")
echo "[+] $url -> $cms"
case "$cms" in
wordpress)
wpscan --url "$url" -e vp,vt --format json --output "triage_results/${name}_wpscan.json" ;;
joomla)
joomscan -u "$url" -ec -ir "triage_results/${name}_joomscan" ;;
drupal)
droopescan scan drupal -u "$url" -e a -o json > "triage_results/${name}_droopescan.json" ;;
*)
echo "[i] No specialized scanner routed for CMS: $cms" ;;
esac
fi
done < "$TARGETS"
Nightly CMS Inventory Snapshot
#!/bin/bash
# nightly_cms_inventory.sh
cmseek --update
cmseek -l company_hosts.txt -b
echo "== CMS Inventory Report $(date) ==" > inventory_report.txt
for dir in "$HOME"/CMSeeK/Result/*/; do
if [ -f "${dir}cms.json" ]; then
jq -r '"\(.cms_name) \(.version // "unknown")"' "${dir}cms.json" >> inventory_report.txt
fi
done
sort inventory_report.txt | uniq -c | sort -rn
Cron Job for Weekly Asset Inventory
# crontab -e
0 1 * * 0 /usr/local/bin/nightly_cms_inventory.sh >> /var/log/cmseek_weekly.log 2>&1
Tips and Best Practices
- Always run CMSeeK first in a CMS security assessment — its speed and broad coverage make it ideal for triage before committing time to a heavier, CMS-specific scan.
- Use
-b(batch mode) for any scripted or automated workflow; without it, CMSeeK may prompt interactively and break automation pipelines. - Periodically run
cmseek --updateto keep the 180+ platform signature database current, since new CMS platforms and detection signatures are added regularly. - Use
--clear-cachebefore re-scanning a target that you know has changed (e.g., after a patch or migration), since CMSeeK caches results per-target by default. - Combine CMSeeK’s JSON output with
jqfor easy integration into asset inventory databases or SIEM pipelines. - When CMSeeK’s auto-detection is inconclusive or ambiguous (common on heavily customized sites), use the
--is-wp,--is-joomla, or--is-drupalflags to force the relevant deep-scan module and get a second opinion. - For any positively identified WordPress, Joomla, or Drupal target, follow up CMSeeK’s initial pass with the dedicated deep-scan tool (WPScan, JoomScan, or Droopescan respectively) for the most authoritative, up-to-date vulnerability data.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
CMS Not Detected on a known CMS site | Custom install hides generator tags/signatures | Try -v verbose mode to see which signatures were tested; force the module with --is-wp / --is-joomla / --is-drupal |
| Script hangs waiting for input | Ran without -b (batch mode) in an automated pipeline | Always include -b for non-interactive scripted scans |
ModuleNotFoundError on startup | Missing Python dependencies | Re-run pip3 install -r requirements.txt --break-system-packages inside the CMSeeK directory |
| Cached results are stale after target was patched | CMSeeK reuses cached JSON by target name | Run cmseek --clear-cache before re-scanning |
| SSL handshake failures | Self-signed certificate on staging environment | Add --no-check-certificate |
--update fails | No internet access or GitHub connectivity blocked | Verify with curl -I https://github.com; check firewall/proxy rules |
| Deep-scan module doesn’t trigger even though CMS is correctly detected | Confidence threshold not met, or module intentionally skipped for low-confidence matches | Force the module manually with the relevant --is-* flag |
Global cmseek command not found | Tool installed via git clone without symlink setup | Either run python3 cmseek.py from within the cloned directory, or create the symlink as shown in the Installation section |
References
- CMSeeK Official GitHub Repository: https://github.com/Tuhinshubhra/CMSeeK
- CMSeeK Wiki / Usage Documentation: https://github.com/Tuhinshubhra/CMSeeK/wiki
- Kali Linux Tools Listing – CMSeeK: https://www.kali.org/tools/cmseek/
- CMS Detection Signature Format Reference (whatcms-style): https://github.com/Tuhinshubhra/CMSeeK#cms-detection