# CMS Detection and Fingerprinting

> Identifies CMS platforms (WordPress, Joomla, Drupal) via HTTP responses, meta tags, file paths, and headers to map attack surface during web enumeration.

- **URL:** https://hackindex.io/services/web/enumeration/cms-detection
- **Path:** HTTP/HTTPS > Enumeration
- **Up:** [Enumeration](https://hackindex.io/services/web/enumeration.md)
- **Published:** 2026-03-28
- **Updated:** 2026-07-10

CMS detection identifies which content management system and version is running before applying specific enumeration tooling. [WordPress](https://hackindex.io/services/web/enumeration/wordpress-enumeration), [Drupal](https://hackindex.io/services/web/enumeration/drupal-enumeration), and [Joomla](https://hackindex.io/services/web/enumeration/joomla-enumeration) have dedicated pages: this page covers the initial detection step and fingerprinting for other platforms including Magento, Typo3, Umbraco, and custom frameworks. Correct identification prevents wasting time with wrong tooling and surfaces version-specific CVEs immediately.

Detection relies on several overlapping signals. No single indicator is conclusive on its own. Work through all available layers before committing to a platform:

- HTTP response headers: `Server`, `X-Powered-By`, `X-Generator`
- HTML meta generator tag: often includes platform and version
- Cookie names: `fe_typo_user` (TYPO3), `UMB_UCONTEXT` (Umbraco)
- URL patterns: `/wp-admin/`, `/administrator/`, `/?q=node`
- Known static file paths: `/CHANGELOG.txt`, `/readme.html`, `/magento_version`

Misidentification sends enumeration in the wrong direction and means any tooling you run will produce irrelevant output.

Start with automated tools. They parse multiple signals in a single pass and usually return a confident answer. Fall back to manual path probing only when automation is blocked or returns conflicting results. WAFs, custom error pages, and aggressive header stripping all degrade automated results and require manual follow-up.

## whatweb

whatweb is the primary tool and usually identifies the CMS in a single request. Aggression level 3 sends additional follow-up requests to confirm initial findings. This increases detection accuracy at the cost of more traffic. Use level 1 when noise matters. The output line includes the HTTP status code, detected plugins with versions shown in square brackets, server software, and the page title. Focus on the plugin names: they map directly to dedicated enumeration workflows. If whatweb returns a version number, treat that as your primary lead. Missing version information is common on patched or hardened installs and means you need to probe version-disclosure endpoints manually.

```bash
whatweb -a 3 http://$TARGET_IP:$PORT/ --log-brief=-
# http://10.10.10.50/ [200 OK] Magento[2.4.3], PHP[7.4.3], nginx[1.18], Title[Home Page]
```

```bash
whatweb -a 3 https://$DOMAIN/ 2>/dev/null
```

When whatweb identifies a CMS, cross-reference the version against known CVEs. The version number alone often determines the exploitation path. Run the version through searchsploit immediately. If whatweb returns a version range or no version at all, note the CMS type and probe version-disclosure endpoints specific to that platform. A missing version in the whatweb output is not a dead end: it means the next step is manual version probing rather than CVE lookup.

## Manual Fingerprinting by CMS

When whatweb is inconclusive, probe CMS-specific paths manually. Each platform has unique indicators. whatweb returns inconclusive results when a WAF intercepts and rewrites responses, when the server returns a generic error page for all paths, or when the application strips technology-identifying headers. In those cases, request known installation paths directly. A 200 or 302 on a CMS-specific path is strong evidence even when the response body contains no version string. A 403 on an admin path also confirms the platform is likely present: the application is protecting the route, which means the route exists. Combine at least two signals before concluding which CMS is running.

#### Magento

```bash
curl -sk http://$TARGET_IP:$PORT/magento_version
curl -sk http://$TARGET_IP:$PORT/ | grep -i 'magento\|mage'
curl -sk -o /dev/null -w '%{http_code}' http://$TARGET_IP:$PORT/index.php/admin/
# Magento/2.4.3 (Community)
```

#### TYPO3

```bash
curl -sk http://$TARGET_IP:$PORT/ | grep -i 'typo3\|typo'
curl -sk -o /dev/null -w '%{http_code}' http://$TARGET_IP:$PORT/typo3/
curl -sk http://$TARGET_IP:$PORT/typo3conf/LocalConfiguration.php
```

#### Umbraco

```bash
curl -sk http://$TARGET_IP:$PORT/ | grep -i 'umbraco'
curl -sk -o /dev/null -w '%{http_code}' http://$TARGET_IP:$PORT/umbraco/
curl -sk http://$TARGET_IP:$PORT/umbraco/webservices/legacyAjaxCalls.asmx
```

#### Shopify / SaaS

```bash
curl -skI http://$TARGET_IP:$PORT/ | grep -iE 'x-shopify|x-powered-by|server'
curl -sk http://$TARGET_IP:$PORT/ | grep -i 'shopify\|cdn.shopify'
```

## Generator Meta Tag and HTTP Headers

Many CMS platforms disclose themselves in the HTML meta generator tag or custom HTTP response headers. The generator meta tag appears in the page head section and often includes both the platform name and the version string. Hardened installations frequently remove this tag, but the corresponding HTTP headers are often overlooked by administrators. The X-Powered-By and X-Generator headers survive in many configurations where the meta tag has been removed. Check both layers on every target. When neither the meta tag nor the custom headers are present, move to cookie name fingerprinting next.

```bash
curl -sk http://$TARGET_IP:$PORT/ | grep -i 'generator'
# <meta name="generator" content="TYPO3 CMS" />
```

```bash
curl -skI http://$TARGET_IP:$PORT/ | grep -iE 'x-powered-by|x-cms|x-generator|x-drupal|x-joomla'
# X-Powered-By: TYPO3 CMS
```

## Cookie Name Fingerprinting

Session cookie names are CMS-specific and often reveal the platform without any other indicators. Cookies persist even when administrators strip response headers and remove the generator meta tag. This makes them a reliable signal on hardened targets where other methods return nothing. Send a HEAD request to the root path and inspect the Set-Cookie headers. The cookie name alone can confirm the platform. If the response sets multiple cookies, check each one against known CMS patterns before drawing a conclusion.

```bash
curl -skI http://$TARGET_IP:$PORT/ | grep -i 'set-cookie'
# Set-Cookie: PHPSESSID=abc123; path=/
# Set-Cookie: fe_typo_user=xyz789; path=/
```

Common cookie name indicators:

| Cookie name | Platform |
| --- | --- |
| fe_typo_user | TYPO3 |
| PHPSESSID + frontend | Magento |
| UMB_UCONTEXT | Umbraco |
| ASP.NET_SessionId | .NET / Umbraco / Kentico |
| PHPSESSID only | PHP app, check further |

A bare PHPSESSID without any accompanying CMS-specific cookie only confirms the application uses PHP sessions. It does not identify the platform. Continue to the path-probing methods above when this is the only cookie present. An ASP.NET_SessionId without UMB_UCONTEXT could be Kentico, Sitecore, or another .NET CMS. In those cases, look for CMS-specific paths in page source or use whatweb at a higher aggression level to resolve the ambiguity.

After identifying the CMS and version, search searchsploit and exploit-db for known vulnerabilities before moving to vulnerability discovery. Filter results by the exact version number. Prioritize authentication bypass and RCE entries first. If no direct match exists, check whether vulnerabilities for nearby minor versions are listed: many CVEs apply across multiple patch levels and the exact version boundary is worth confirming against the CVE details. When searchsploit returns nothing useful, search the NVD directly using the CMS name and version as keywords.

```bash
searchsploit typo3 2>&1 | head -20
```

## References

- [WhatWeb](https://github.com/urbanadventurer/WhatWeb) - CMS fingerprinting rules and aggression levels
