Skip to content
HackIndex logo

HackIndex

CMS Detection and Fingerprinting

5 min read Jul 10, 2026

CMS detection identifies which content management system and version is running before applying specific enumeration tooling. WordPress, Drupal, and Joomla 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.

whatweb

whatweb is the primary tool and usually identifies the CMS in a single request:

┌──(kali㉿kali)-[~]
└─$ 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]
Explain command
-a 3 Sets aggression level to 3 (aggressive, more requests sent).
http://$TARGET_IP:$PORT/ Target URL with variable host IP and port to fingerprint.
--log-brief=- Outputs brief log format to stdout (dash = standard output).
┌──(kali㉿kali)-[~]
└─$ whatweb -a 3 https://$DOMAIN/ 2>/dev/null
Explain command
-a 3 Set aggression level to 3 (aggressive, sends more requests).
https://$DOMAIN/ Target URL with placeholder domain to fingerprint.
2>/dev/null Redirect stderr to /dev/null to suppress error messages.

When whatweb identifies a CMS, cross-reference the version against known CVEs. The version number alone often determines the exploitation path.

Manual Fingerprinting by CMS

When whatweb is inconclusive, probe CMS-specific paths manually. Each platform has unique indicators:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/magento_version
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/ | grep -i 'magento\|mage'
┌──(kali㉿kali)-[~]
└─$ curl -sk -o /dev/null -w '%{http_code}' http://$TARGET_IP:$PORT/index.php/admin/
Magento/2.4.3 (Community)
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allows insecure SSL connections by skipping certificate verification.
http://$TARGET_IP:$PORT/magento_version Target URL with variable host and port to probe Magento version endpoint.
http://$TARGET_IP:$PORT/ Target base URL with variable host and port.
-i Case-insensitive pattern matching in grep.
'magento\|mage' Grep pattern matching Magento-related strings in the response body.
-o /dev/null Discards the response body by redirecting output to null.
-w '%{http_code}' Outputs only the HTTP status code after the request completes.
http://$TARGET_IP:$PORT/index.php/admin/ Target URL pointing to the Magento admin panel path.
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/ | grep -i 'typo3\|typo'
┌──(kali㉿kali)-[~]
└─$ curl -sk -o /dev/null -w '%{http_code}' http://$TARGET_IP:$PORT/typo3/
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/typo3conf/LocalConfiguration.php
Explain command
-s Silent mode; suppresses progress and error output.
-k Allows insecure SSL/TLS connections, skipping cert validation.
http://$TARGET_IP:$PORT/ Target URL with variable host and port placeholders.
-i Case-insensitive pattern matching in grep.
'typo3\|typo' Grep pattern matching either 'typo3' or 'typo' strings.
-o /dev/null Discards response body by redirecting output to /dev/null.
-w '%{http_code}' Prints only the HTTP response status code after request.
http://$TARGET_IP:$PORT/typo3/ Target URL pointing to the TYPO3 CMS admin directory.
http://$TARGET_IP:$PORT/typo3conf/LocalConfiguration.php Target URL for TYPO3 local config file containing sensitive data.
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/ | grep -i 'umbraco'
┌──(kali㉿kali)-[~]
└─$ curl -sk -o /dev/null -w '%{http_code}' http://$TARGET_IP:$PORT/umbraco/
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/umbraco/webservices/legacyAjaxCalls.asmx
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure SSL/TLS connections, skipping certificate verification.
http://$TARGET_IP:$PORT/ Target URL with variable host IP and port placeholders.
-i 'umbraco' Case-insensitive grep filter for the string 'umbraco'.
-o /dev/null Discards response body by redirecting output to /dev/null.
-w '%{http_code}' Outputs only the HTTP response status code after the request.
http://$TARGET_IP:$PORT/umbraco/ Target URL pointing to the Umbraco CMS root path.
http://$TARGET_IP:$PORT/umbraco/webservices/legacyAjaxCalls.asmx Target URL for the Umbraco legacy AJAX web service endpoint.
┌──(kali㉿kali)-[~]
└─$ curl -skI http://$TARGET_IP:$PORT/ | grep -iE 'x-shopify|x-powered-by|server'
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/ | grep -i 'shopify\|cdn.shopify'
Explain command
-s Silent mode; suppresses progress and error output.
-k Skips SSL/TLS certificate verification.
-I Sends a HEAD request to fetch headers only.
http://$TARGET_IP:$PORT/ Target URL using variable IP and port placeholders.
-iE Case-insensitive match with extended regex support.
'x-shopify|x-powered-by|server' Regex pattern matching common tech-disclosure headers.
-i Performs case-insensitive string matching.
'shopify\|cdn.shopify' Pattern matching Shopify platform indicators in response body.

Generator Meta Tag and HTTP Headers

Many CMS platforms disclose themselves in the HTML meta generator tag or custom HTTP headers:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/ | grep -i 'generator'
<meta name="generator" content="TYPO3 CMS" />
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure TLS connections, skipping certificate verification.
http://$TARGET_IP:$PORT/ Target URL constructed from IP and port variable placeholders.
-i Makes the grep pattern match case-insensitive.
'generator' Pattern to search for 'generator' meta tag in the HTML response.
┌──(kali㉿kali)-[~]
└─$ curl -skI http://$TARGET_IP:$PORT/ | grep -iE 'x-powered-by|x-cms|x-generator|x-drupal|x-joomla'
X-Powered-By: TYPO3 CMS
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allows insecure TLS connections, skipping certificate verification.
-I Sends a HEAD request, fetching only HTTP response headers.
http://$TARGET_IP:$PORT/ Target URL built from variable IP and port placeholders.
-iE Case-insensitive match using extended regex pattern.
'x-powered-by|x-cms|x-generator|x-drupal|x-joomla' Regex pattern matching common CMS/framework fingerprinting headers.

Session cookie names are CMS-specific and often reveal the platform without any other indicators:

┌──(kali㉿kali)-[~]
└─$ curl -skI http://$TARGET_IP:$PORT/ | grep -i 'set-cookie'
Set-Cookie: PHPSESSID=abc123; path=/
Set-Cookie: fe_typo_user=xyz789; path=/
Explain command
-s Silent mode; suppresses progress and error output.
-k Allow insecure TLS connections, skipping certificate verification.
-I Send HEAD request and fetch HTTP headers only.
http://$TARGET_IP:$PORT/ Target URL built from variable IP and port placeholders.
-i Makes the grep pattern match case-insensitive.
'set-cookie' Filter pattern to display only Set-Cookie header lines.

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

After identifying the CMS and version, search searchsploit and exploit-db for known vulnerabilities before moving to vulnerability discovery:

┌──(kali㉿kali)-[~]
└─$ searchsploit typo3 2>&1 | head -20
Explain command
2>&1 Redirects stderr (fd 2) to stdout (fd 1), merging both streams.
head -20 Outputs only the first 20 lines of the piped input.

References