Lucene search
+L

Drupal Software Detection

🗓️ 07 Jul 2005 00:00:00Reported by TenableType 
nessus
 nessus
🔗 www.tenable.com👁 144 Views

Drupal Software Detection. An open source content management system written in PHP is running on the remote web server. Ensure that the use of this software aligns with your organization's security and acceptable use policies

Refs
Code
SourceLink
drupalwww.drupal.org/
###
# (C) Tenable Network Security, Inc.
###

include("compat.inc");

if (description)
{
  script_id(18638);
  script_version("1.35");
  script_set_attribute(attribute:"plugin_modification_date", value:"2023/05/24");
  script_xref(name:"IAVT", value:"0001-T-0586");

  script_name(english:"Drupal Software Detection");

  script_set_attribute(attribute:"synopsis", value:
"A content management system is running on the remote web server.");
  script_set_attribute(attribute:"description", value:
"Drupal, an open source content management system written in PHP, is
running on the remote web server.");
  script_set_attribute(attribute:"see_also", value:"https://www.drupal.org/");
  script_set_attribute(attribute:"solution", value:
"Ensure that the use of this software aligns with your organization's
security and acceptable use policies.");
  script_set_attribute(attribute:"risk_factor", value:"None");

  script_set_attribute(attribute:"plugin_publication_date", value:"2005/07/07");

  script_set_attribute(attribute:"plugin_type", value:"remote");
  script_set_attribute(attribute:"asset_inventory", value:"True");
  script_set_attribute(attribute:"asset_inventory_category", value:"software_enumeration");
  script_set_attribute(attribute:"cpe", value:"cpe:/a:drupal:drupal");
  script_set_attribute(attribute:"thorough_tests", value:"true");
  script_end_attributes();

  script_category(ACT_GATHER_INFO);
  script_family(english:"CGI abuses");

  script_copyright(english:"This script is Copyright (C) 2005-2023 and is owned by Tenable, Inc. or an Affiliate thereof.");

  script_dependencies("http_version.nasl");
  script_require_keys("www/PHP");
  script_require_ports("Services/www", 80, 443);

  exit(0);
}

include("audit.inc");
include("global_settings.inc");
include("misc_func.inc");
include("http.inc");
include("install_func.inc");
include("debug.inc");

port = get_http_port(default:80, php:TRUE);
app = "Drupal";

function drupal_version_from_header( res )
{
  # look in header before we toss result for 'X-Generator: Drupal 8'
  local_var matches = pregmatch(pattern:'Drupal ([0-9\\.]+)', string:res[1]);
  if (!empty_or_null(matches))
  {
    return matches[1];
  }
  return NULL;
}

function drupal_version_from_md5( md5 )
{
  local_var ver_lookup = make_array(
  "dc0fbe017fd1cc3d97b8c12bc45dde41", "4.7.0 4.7.1",
  "98cd0c4c8bde66a3227ce1d583f433f4", "4.7.2 4.7.3",
  "3130d555431177091ff7ac5b4f3fe19e", "4.7.4",
  "dd465695d5ae35ecc33c8cad33f7880c", "4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.7.10 4.7.11",
  "afd188dc6cd982d37463209679ab01ec", "5.0 5.1",
  "9e557006e956d365119eb2ebd2169051", "5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9",
  "2c5e4277fec6afac333e913744e0408f", "5.10 5.11 5.12 5.13 5.14 5.15 5.16",
  "4677b027fed107133090dabccee2b4f5", "5.17 5.18 5.19 5.20 5.21 5.22 5.23",
  "ebbcc0156242a08a25c596432ca92f67", "6.0",
  "2ff7dc985e57d1139ce4dc844b06bc64", "6.1 6.2",
  "398b3832c2de0a0ebd08cb7f2afe1545", "6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 6.12 6.13",
  "88682723723be277fb57c0d8e341c0cf", "6.14 6.15 6.16 6.17 6.18 6.19 6.20",
  "9a1c645566d780facee5ce1a0d3fab7c", "6.21",
  "fe6f8c678cb511d68a3dbe5a94f2e278", "6.22 6.23",
  "90c0aa7ed8581884c2afe73fc87b5697", "6.24 6.25 6.26 6.27",
  "1904f6fd4a4fe747d6b53ca9fd81f848", "6.28 6.29 6.30 6.31 6.32 6.33 6.34 6.35 6.36 6.37 6.38",
  "847afc6e14d280e66a564194e166a66e", "7.0",
  "f3f32021901f4c33d2eebbc634de587d", "7.1",
  "cea76de12c5bb95dd0789fbd3cd754f0", "7.2 7.3 7.4 7.5 7.6 7.7 7.8",
  "d4515f21acd461ca04304233bf0daa1e", "7.9 7.11",
  "cbd95e04bad1be13320ebbe63a863245", "7.10",
  "f9281a1fa8b926ba038bebc3bb0c3d61", "7.12 7.13 7.14 7.15 7.16 7.17 7.18",
  "0bb055ea361b208072be45e8e004117b", "7.19 7.20 7.21 7.22 7.23 7.24 7.25 7.26 7.27 7.28 7.29 7.30 7.31 7.32 7.33 7.34 7.35 7.36 7.37 7.38",
  "bb9f18fb7a42b95fcad87b98dbb19c87", "7.39 7.40 7.41 7.42 7.43 7.44 7.50",
  "acf092762cf1cf821a12325fbf494ecf", "7.51 7.52 7.53 7.54",
  "ce89aafcde644262269009c10d8a9cd2", "7.55 7.56",
  "a4065c93addf975e695586c24a20bda8", "7.57 7.58 7.59 7.60",
  "3dcbe8b1280a271797fe4f1dd5700d0c", "8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6",
  "714d7aeb86ea12acc0de88e2b135f14d", "8.1.0 8.1.1 8.1.2 8.1.3 8.1.4 8.1.5 8.1.6 8.1.7 8.1.8 8.1.9 8.1.10 8.2.0 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.2.7 8.2.8",
  "0e18a6096f1a222fab718c153266444a", "8.3.0 8.3.1 8.3.2 8.3.3 8.3.4 8.3.5 8.3.6 8.3.7",
  "5ef71c6e30d110e9e329c3f7531bb285", "8.3.8 8.3.9",
  "423a643a05f801dea5358481e56d83d7", "8.4.0 8.4.1 8.4.2 8.4.3 8.4.4",
  "767df16aa36ccaa000a195ff5680a9c2", "8.4.5 8.4.6 8.4.7 8.4.8",
  "71bfba813a9f85564220f8e9a1b06da4", "8.5.0 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.5.6 8.5.7 8.5.8",
  "a375001d7040601a26da55bd8c30856d", "8.6.0 8.6.1 8.6.2",
  "ae9cceaa80684c10cdff035fc27fa4de", "9.0.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.0.6 9.0.7 9.1.0 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.1.7 9.1.8 9.1.9 9.2.0 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.2.6"
  );

  # find md5 of drupal.js in lookup table
  local_var jsver = ver_lookup[ md5 ];
  if ( isnull( jsver ) )
  {
    # not found, nothing to report
    return NULL;
  }
  # found, how many versions have this md5 value?
  local_var jsvers = split( jsver, sep:" ", keep:FALSE );
  # only one?
  if ( max_index( jsvers ) == 1 )
  {
    # only one, report this specific version
    return make_list( jsvers, NULL );
  }
  # more than one, report a generic version and note about what it might be
  return make_list( substr(jsver,0,0), 'The version appears to be ' + jsver + ' according to the MD5 of drupal.js'  );
}

# always check root and /drupal
var dirs = make_list('', '/drupal');

if (!get_kb_item('Settings/disable_cgi_scanning'))
{
  dirs = make_list(dirs, cgi_dirs());
  dirs = list_uniq(dirs);
}

installs = 0;
var dir;
foreach dir (dirs)
{
  ver = UNKNOWN_VER;
  altver = UNKNOWN_VER;
  found = FALSE;
  url = dir + "/";
  res = http_send_recv3(method:"GET", item:url, port:port, exit_on_fail:TRUE);
  # /search/node FP
  match = pregmatch(string:res[2], pattern:'name="Generator" content="Drupal (8|9)');
  if (!empty_or_null(match) && '<h3>Your search yielded no results' >!< res[2])
  {
    found = TRUE;
    altver = match[1];
    url = dir + "/core/install.php";
    res = http_send_recv3(method:"GET", item:url, port:port, exit_on_fail:FALSE);
    matches = pregmatch(pattern:'<span class="site-version">([0-9\\.a-z-]+)</span>', string:res[2]);
    dbg::log(src:SCRIPT_NAME, msg:" Drupal found via site version tag ");

    if (!empty_or_null(matches))
    {
      ver = matches[1];
    }
  }
  else
  {
    match = pregmatch(string:res[2], pattern:'<meta name="generator" content="Drupal ([0-9])', icase:TRUE);
    # Simple check of the index page
    if (!empty_or_null(match) && "Drupal.settings" >< res[2] && "/drupal.js" >< res[2])
    {
      found = TRUE;
      altver = match[1];
      dbg::log(src:SCRIPT_NAME, msg:" Drupal found via meta tag ");
    }
    # Index page doesn't appear to be running on Drupal, check 'update.php'
    if (!found)
    {
      url = dir + "/update.php?op=info";
      res = http_send_recv3(method:"GET", item:url, port:port, exit_on_fail:FALSE);
      # If it looks like Drupal...
      if (
        (
          "main Drupal directory" >< res[2] &&
          (
            "<code>$access_check = FALSE;</code>" >< res[2] ||
            "<code>$update_free_access = FALSE;</code>" >< res[2]
          ) ||
          "set $update_free_access" >< res[2]
        ) ||
        "<h1>Drupal database update</h1>" >< res[2]
      )
      {
        found = TRUE;
        altver = drupal_version_from_header( res:res );
        dbg::log(src:SCRIPT_NAME, msg:" Drupal Found via update.php ");
      }
    }
    # update.php doesn't appear to be running on Drupal, check 'misc/drupal.js'
    var drupaljs_dir;
    if (!found)
    {
      var drupaljs_dirs = list_uniq(make_list("/misc", "/core/misc"));
      foreach drupaljs_dir (drupaljs_dirs)
      {
        url = dir + drupaljs_dir + "/drupal.js";
        res = http_send_recv3(method:"GET", item:url, port:port, exit_on_fail:FALSE);
        if (
          res[0] =~ '^HTTP/[0-9.]+ +200' &&
          "var Drupal = Drupal" >< res[2] &&
          "Drupal.attachBehaviors = function" >< res[2] && "Drupal.detachBehaviors = function" >< res[2]
        )
        {
          found = TRUE;
          dbg::log(src:SCRIPT_NAME, msg:" Drupal Found via Drupal.js contents ");

        }
        if ( res[0] =~ '^HTTP/[0-9.]+ +200' )
        {
          md5ver = drupal_version_from_md5( md5:hexstr(MD5(res[2])) );
          if ( empty_or_null( md5ver ) )
          {
            # header detection of version is very weak and last resort
            altver = drupal_version_from_header( res:res );
          }
          else
          {
            # some versions of drupal.js won't match detachBehaviors, but match md5 here
            found = TRUE;
            dbg::log(src:SCRIPT_NAME, msg:" Drupal Found via Drupal.js + MD5 ");
            altver = md5ver[0];
            note = md5ver[1];
          }
          break;
        }
      }
    }
    if (!found) continue;
    # Try to identify the version number from the changelog.
    # Starting with 8.0, CHANGELOG.txt has moved to core/
    changelog = make_list("/", "/core/");
    var path, match;
    foreach path (changelog)
    {
      url = dir + path + "CHANGELOG.txt";
      url = ereg_replace(string:url, pattern: "//+", replace: "/");
      res = http_send_recv3(method:"GET", item:url, port:port, exit_on_fail:FALSE);
      # nb: Drupal 1.0.0 was the first version, released 2001-01-15.
      pat = "^Drupal +([1-9].+), 20";
      matches = pgrep(pattern:pat, string:res[2]);
      if (!empty_or_null(matches))
      {
        foreach match (split(matches, keep:FALSE))
        {
          item = pregmatch(pattern:pat, string:match);
          if (!isnull(item))
          {
            ver = item[1];
            break;
          }
        }
      }
    }
  }
  if (found)
  {
    if ( ( ver == UNKNOWN_VER ) && ( altver != UNKNOWN_VER ) )
    {
      ver = altver;
    }
    extra = NULL;
    if ( !empty_or_null(note) )
    {
      extra = make_array( "Note", note );
    }
    register_install(
      vendor   : "Drupal",
      product  : "Drupal",
      app_name : app,
      path     : dir,
      port     : port,
      version  : ver,
      cpe      : "cpe:/a:drupal:drupal",
      extra    : extra,
      webapp   : TRUE
    );
    installs++;

    # Scan for multiple installations only if the "Perform thorough tests" setting is checked.
    if (!thorough_tests) break;
  }
}
if (installs == 0) audit(AUDIT_WEB_APP_NOT_INST, app, port);
report_installs(port:port);

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

24 May 2023 00:00Current
5.5Medium risk
Vulners AI Score5.5
144