Skip to content
HackIndex logo

HackIndex

Drupal enumeration

4 min read Apr 24, 2026

Drupal enumeration identifies the installed version, active modules, themes, and user accounts. The version is the critical signal — Drupal 7 and older Drupal 8 releases have well-known RCE vulnerabilities including Drupalgeddon2 and Drupalgeddon3. Run this after tech fingerprinting confirms Drupal.

Confirm Drupal and Version

Version is often disclosed in the changelog or install.txt files before any tooling is needed:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/CHANGELOG.txt | head -5
Drupal 7.57, 2018-02-21
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure TLS connections, skipping certificate verification.
http://$TARGET_IP:$PORT/CHANGELOG.txt Target URL using variable host and port to fetch CHANGELOG.txt.
head -5 Pipes output and displays only the first 5 lines.
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/core/CHANGELOG.txt | head -5
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure SSL connections by skipping certificate verification.
http://$TARGET_IP:$PORT/core/CHANGELOG.txt Target URL with variable host IP and port to fetch CHANGELOG.txt.
head -5 Pipes output and displays only the first 5 lines.
┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/install.txt | head -5
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure TLS connections, skipping certificate verification.
http://$TARGET_IP:$PORT/install.txt Target URL with variable host and port to fetch install.txt.
head -5 Pipes output and displays only the first 5 lines.

Drupal 7 uses /CHANGELOG.txt. Drupal 8 and 9 use /core/CHANGELOG.txt. If the files are removed, check the meta generator tag:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/ | grep -i 'generator\|drupal'
<meta name="generator" content="Drupal 7 (https://www.drupal.org)" />
Explain command
-s Silent mode; suppresses progress and error messages.
-k Allow insecure TLS connections, skipping certificate verification.
http://$TARGET_IP:$PORT/ Target URL built from host IP and port placeholders.
-i Makes the grep pattern matching case-insensitive.
'generator\|drupal' Regex pattern matching 'generator' or 'drupal' in output.

droopescan

droopescan enumerates modules, themes, and version ranges passively. It's slower than manual checks but more thorough on module discovery:

┌──(kali㉿kali)-[~]
└─$ droopescan scan drupal -u http://$TARGET_IP:$PORT/
[+] Plugins found:
    views http://10.10.10.50/sites/all/modules/views/
    token http://10.10.10.50/sites/all/modules/token/

[+] Themes found:
    bartik http://10.10.10.50/themes/bartik/

[+] Possible version(s):
    7.57
Explain command
scan Subcommand to initiate a scan against the target CMS.
drupal Specifies Drupal as the target CMS type to scan.
-u Specifies the target URL to scan.
http://$TARGET_IP:$PORT/ Target URL with variable IP address and port number.

User Enumeration

Drupal 7 leaks usernames through login error messages and the node/user system. Confirm with a direct probe:

┌──(kali㉿kali)-[~]
└─$ curl -sk http://$TARGET_IP:$PORT/?q=user/1
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure connections; skip SSL/TLS certificate verification.
http://$TARGET_IP:$PORT/?q=user/1 Target URL with host, port, and query string to fetch user record 1.
┌──(kali㉿kali)-[~]
└─$ curl -sk -d 'name=admin&pass=wrongpassword&form_id=user_login&op=Log+in' http://$TARGET_IP:$PORT/?q=user/login | grep -i 'error\|unrecognized'
Sorry, unrecognized username or password.
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure SSL connections, skipping certificate verification.
-d Send specified data as HTTP POST request body.
'name=admin&pass=wrongpassword&form_id=user_login&op=Log+in' POST body with Drupal login form fields including credentials.
http://$TARGET_IP:$PORT/?q=user/login Target URL with IP, port placeholders, and Drupal login path.
-i Case-insensitive pattern matching in grep.
'error\|unrecognized' Grep pattern matching 'error' or 'unrecognized' in response output.

If the error says "unrecognized username" for a non-existent user but "incorrect password" for a valid one, the application is vulnerable to username enumeration.

Admin Panel and Registration Check

Check whether registration is open and the admin panel is reachable:

┌──(kali㉿kali)-[~]
└─$ curl -sk -o /dev/null -w '%{http_code}' http://$TARGET_IP:$PORT/?q=admin
200
Explain command
-s Silent mode; suppresses progress meter and error messages.
-k Allow insecure TLS connections, skipping certificate verification.
-o /dev/null Discard response body by writing output to /dev/null.
-w '%{http_code}' Print the HTTP response status code after the request completes.
http://$TARGET_IP:$PORT/?q=admin Target URL with dynamic IP, port, and query string parameter q=admin.
┌──(kali㉿kali)-[~]
└─$ curl -sk -o /dev/null -w '%{http_code}' http://$TARGET_IP:$PORT/?q=user/register
Explain command
-s Silent mode; suppresses progress and error output.
-k Allow insecure TLS connections, skipping certificate verification.
-o /dev/null Discard response body by redirecting output to /dev/null.
-w '%{http_code}' Print only the HTTP response status code after the request.
http://$TARGET_IP:$PORT/?q=user/register Target URL with variable host/port probing the Drupal user register path.

Module and Theme Path Probing

Probe known module paths to identify which are installed without droopescan:

┌──(kali㉿kali)-[~]
└─$ ffuf -w /usr/share/seclists/Discovery/Web-Content/CMS/drupal-modules.txt -u http://$TARGET_IP:$PORT/sites/all/modules/FUZZ/ -mc 200,301,302,403
Explain command
-w /usr/share/seclists/Discovery/Web-Content/CMS/drupal-modules.txt Wordlist file containing Drupal module names for fuzzing.
-u http://$TARGET_IP:$PORT/sites/all/modules/FUZZ/ Target URL with FUZZ keyword as the injection point.
$TARGET_IP:$PORT Variable placeholders for the target host IP and port.
-mc 200,301,302,403 Match only responses with these HTTP status codes.

A Drupal 7 install on a vulnerable version is a high-priority finding. Drupalgeddon2 (CVE-2018-7600) affects Drupal 6, 7, and 8 before specific patch versions and gives unauthenticated RCE. Cross-reference the version against known CVEs before moving to exploitation.

References