Droopescan - Scanner to identify issues with several CMSs, mainly Drupal & Silverstripe

Monday, September 7, 2015

A plugin-based scanner that aids security researchers in identifying issues with several CMS:
  • Drupal.
  • SilverStripe.
Partial functionality for:
  • Wordpress.
  • Joomla.
computer:~/droopescan$ droopescan scan drupal -u http://example.org/ -t 8
[+] No themes found.

[+] Possible interesting urls found:
    Default changelog file - https://www.example.org/CHANGELOG.txt
    Default admin - https://www.example.org/user/login

[+] Possible version(s):

[+] Plugins found:
    views https://www.example.org/sites/all/modules/views/
    token https://www.example.org/sites/all/modules/token/
    pathauto https://www.example.org/sites/all/modules/pathauto/
    libraries https://www.example.org/sites/all/modules/libraries/
    entity https://www.example.org/sites/all/modules/entity/
    google_analytics https://www.example.org/sites/all/modules/google_analytics/
    ctools https://www.example.org/sites/all/modules/ctools/
    features https://www.example.org/sites/all/modules/features/
    [... snip for README ...]

[+] Scan finished (0:04:59.502427 elapsed)
You can get a full list of options by running:
droopescan --help
droopescan scan --help

Why not X?

Because droopescan:
  • is fast
  • is stable
  • is up to date
  • allows simultaneous scanning of multiple sites
  • is 100% python

Installation is easy using pip:
apt-get install python-pip
pip install droopescan

Manual installation is as follows:
git clone https://github.com/droope/droopescan.git
cd droopescan
pip install -r requirements.txt
droopescan scan --help
The master branch corresponds to the latest release (what is in pypi). Development branch is unstable and all pull requests must be made against it. More notes regarding installation can be found here.


Scan types.

Droopescan aims to be the most accurate by default, while not overloading the target server due to excessive concurrent requests. Due to this, by default, a large number of requests will be made with four threads; change these settings by using the --number and --threads arguments respectively.

This tool is able to perform four kinds of tests. By default all tests are ran, but you can specify one of the following with the -e or --enumerate flag:
  • p -- Plugin checks: Performs several thousand HTTP requests and returns a listing of all plugins found to be installed in the target host.
  • t -- Theme checks: As above, but for themes.
  • v -- Version checks: Downloads several files and, based on the checksums of these files, returns a list of all possible versions.
  • i -- Interesting url checks: Checks for interesting urls (admin panels, readme files, etc.)
More notes regarding scanning can be found here.

Target specification

You can specify a particular host to scan by passing the -u or --url parameter:
    droopescan scan drupal -u example.org
You can also omit the drupal argument. This will trigger “CMS identification”, like so:
    droopescan scan -u example.org
Multiple URLs may be scanned utilising the -U or --url-file parameter. This parameter should be set to the path of a file which contains a list of URLs.
    droopescan scan drupal -U list_of_urls.txt
The drupal parameter may also be ommited in this example. For each site, it will make several GET requests in order to perform CMS identification, and if the site is deemed to be a supported CMS, it is scanned and added to the output list. This can be useful, for example, to run droopescan across all your organisation's sites.
    droopescan scan -U list_of_urls.txt
The code block below contains an example list of URLs, one per line:
A file containing URLs and a value to override the default host header with separated by tabs or spaces is also OK for URL files. This can be handy when conducting a scan through a large range of hosts and you want to prevent unnecessary DNS queries. To clarify, an example below: example.org example.org  example.org
It is quite tempting to test whether the scanner works for a particular CMS by scanning the official site (e.g. wordpress.org for wordpress), but the official sites rarely run vainilla installations of their respective CMS or do unorthodox things. For example, wordpress.org runs the bleeding edge version of wordpress, which will not be identified as wordpress by droopescan at all because the checksums do not match any known wordpress version.


The application fully supports .netrc files and http_proxy environment variables.

You can set the http_proxy and https_proxy variables. These allow you to set a parent HTTP proxy, in which you can handle more complex types of authentication (e.g. Fiddler, ZAP, Burp)
export http_proxy='user:password@localhost:8080'
export https_proxy='user:password@localhost:8080'
droopescan scan drupal --url http://localhost/drupal
Another option is to use a .netrc file for basic authentication. An example ~/.netrc file could look as follows:
machine secret.google.com
    login admin@google.com
    password Winter01
WARNING: By design, to allow intercepting proxies and the testing of applications with bad SSL, droopescan allows self-signed or otherwise invalid certificates. ˙ ͜ʟ˙


This application supports both "standard output", meant for human consumption, or JSON, which is more suitable for machine consumption. This output is stable between major versions.
This can be controlled with the --output flag. Some sample JSON output would look as follows (minus the excessive whitespace):
  "themes": {
    "is_empty": true,
    "finds": [

  "interesting urls": {
    "is_empty": false,
    "finds": [
        "url": "https:\/\/www.drupal.org\/CHANGELOG.txt",
        "description": "Default changelog file."
        "url": "https:\/\/www.drupal.org\/user\/login",
        "description": "Default admin."
  "version": {
    "is_empty": false,
    "finds": [
  "plugins": {
    "is_empty": false,
    "finds": [
        "url": "https:\/\/www.drupal.org\/sites\/all\/modules\/views\/",
        "name": "views"
Some attributes might be missing from the JSON object if parts of the scan are not ran.
This is how multi-site output looks like; each line contains a valid JSON object as shown above.

    $ droopescan scan drupal -U six_and_above.txt -e v
    {"host": "http://localhost/drupal-7.6/", "version": {"is_empty": false, "finds": ["7.6"]}}
    {"host": "http://localhost/drupal-7.7/", "version": {"is_empty": false, "finds": ["7.7"]}}
    {"host": "http://localhost/drupal-7.8/", "version": {"is_empty": false, "finds": ["7.8"]}}
    {"host": "http://localhost/drupal-7.9/", "version": {"is_empty": false, "finds": ["7.9"]}}
    {"host": "http://localhost/drupal-7.10/", "version": {"is_empty": false, "finds": ["7.10"]}}
    {"host": "http://localhost/drupal-7.11/", "version": {"is_empty": false, "finds": ["7.11"]}}
    {"host": "http://localhost/drupal-7.12/", "version": {"is_empty": false, "finds": ["7.12"]}}
    {"host": "http://localhost/drupal-7.13/", "version": {"is_empty": false, "finds": ["7.13"]}}
    {"host": "http://localhost/drupal-7.14/", "version": {"is_empty": false, "finds": ["7.14"]}}
    {"host": "http://localhost/drupal-7.15/", "version": {"is_empty": false, "finds": ["7.15"]}}
    {"host": "http://localhost/drupal-7.16/", "version": {"is_empty": false, "finds": ["7.16"]}}
    {"host": "http://localhost/drupal-7.17/", "version": {"is_empty": false, "finds": ["7.17"]}}
    {"host": "http://localhost/drupal-7.18/", "version": {"is_empty": false, "finds": ["7.18"]}}
    {"host": "http://localhost/drupal-7.19/", "version": {"is_empty": false, "finds": ["7.19"]}}
    {"host": "http://localhost/drupal-7.20/", "version": {"is_empty": false, "finds": ["7.20"]}}
    {"host": "http://localhost/drupal-7.21/", "version": {"is_empty": false, "finds": ["7.21"]}}
    {"host": "http://localhost/drupal-7.22/", "version": {"is_empty": false, "finds": ["7.22"]}}
    {"host": "http://localhost/drupal-7.23/", "version": {"is_empty": false, "finds": ["7.23"]}}
    {"host": "http://localhost/drupal-7.24/", "version": {"is_empty": false, "finds": ["7.24"]}}
    {"host": "http://localhost/drupal-7.25/", "version": {"is_empty": false, "finds": ["7.25"]}}
    {"host": "http://localhost/drupal-7.26/", "version": {"is_empty": false, "finds": ["7.26"]}}
    {"host": "http://localhost/drupal-7.27/", "version": {"is_empty": false, "finds": ["7.27"]}}
    {"host": "http://localhost/drupal-7.28/", "version": {"is_empty": false, "finds": ["7.28"]}}
    {"host": "http://localhost/drupal-7.29/", "version": {"is_empty": false, "finds": ["7.29"]}}
    {"host": "http://localhost/drupal-7.30/", "version": {"is_empty": false, "finds": ["7.30"]}}
    {"host": "http://localhost/drupal-7.31/", "version": {"is_empty": false, "finds": ["7.31"]}}
    {"host": "http://localhost/drupal-7.32/", "version": {"is_empty": false, "finds": ["7.32"]}}
    {"host": "http://localhost/drupal-7.33/", "version": {"is_empty": false, "finds": ["7.33"]}}
    {"host": "http://localhost/drupal-7.34/", "version": {"is_empty": false, "finds": ["7.34"]}}

Subscribe via e-mail for updates!