Lucene search

K
nessusThis script is Copyright (C) 2005-2023 and is owned by Tenable, Inc. or an Affiliate thereof.MEDIAWIKI_DETECT.NASL
HistoryJul 20, 2005 - 12:00 a.m.

MediaWiki Detection

2005-07-2000:00:00
This script is Copyright (C) 2005-2023 and is owned by Tenable, Inc. or an Affiliate thereof.
www.tenable.com
10

The remote host is running MediaWiki, an open source wiki application written in PHP.

#
# (C) Tenable Network Security, Inc.
#

include("compat.inc");

if (description)
{
  script_id(19233);
  script_version("1.18");
  script_set_attribute(attribute:"plugin_modification_date", value:"2023/05/24");

  script_name(english:"MediaWiki Detection");

  script_set_attribute(attribute:"synopsis", value:
"The remote web server contains a wiki application written in PHP.");
  script_set_attribute(attribute:"description", value:
"The remote host is running MediaWiki, an open source wiki application
written in PHP.");
  script_set_attribute(attribute:"see_also", value:"https://www.mediawiki.org/wiki/MediaWiki");
  script_set_attribute(attribute:"solution", value:
"n/a");
  script_set_attribute(attribute:"risk_factor", value:"None");

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

  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:mediawiki:mediawiki");
  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_exclude_keys("Settings/disable_cgi_scanning");
  script_require_ports("Services/www", 80);

  exit(0);
}

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

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

# Find where MediaWiki is installed
# Possible (relative) uris for MediaWiki
uris = make_list("", "/wiki");

if (thorough_tests)
{
  uris = make_list(uris, cgi_dirs(), "/Wiki", "/mediawiki");
  uris = sort(list_uniq(uris));
}

ver_capture = "(\d+(\.\d+)*([\d\.]\d*([a-zA-Z]+)?\d*)?)";

# Relative URIs mapped to lists of regexes that extract version info
# regexes[0] verifies page is MediaWiki, regexes[1] extracts version. Reused.
checks = make_array();

# Hold all installs found temporarily regardless of potential duplicates
interim_installs = make_array();

# Look at generator meta tag, available even if page access is user-only.
# Note that this tag did not exist prior to 1.13.0
regexes = make_list();
regexes[0] = make_list(
  '<meta name="generator" content="MediaWiki',
  'id="ca-nstab-main"'
);
regexes[1] = make_list(
  '<meta name="generator" content="MediaWiki ' + ver_capture + '" />'
);
checks["/index.php"] = regexes;

# If we are able to view Special:Recentchanges, we can use the generator tag
# in the atom output. This is available at least since 1.3.0, probably older
regexes = make_list();
regexes[0] = make_list(
  '<generator>MediaWiki '
);
regexes[1] = make_list(
  '<generator>MediaWiki ' + ver_capture + '</generator>'
);
checks["/?title=Special:Recentchanges&feed=atom"] = regexes;

# Cover the case where mediawiki is installed, but not set up.
regexes = make_list();
regexes[0] = make_list(
  "<title>MediaWiki " + ver_capture + " installation</title>",
  "<h1>MediaWiki " + ver_capture + " installation</h1>"
);
regexes[1] = make_list("<h1>MediaWiki " + ver_capture + " installation</h1>");
#  /config prior to 1.17.x, /mw-config thereafter.
checks["/mw-config"] = regexes;

# Detect version from the RELEASE-NOTES file that's part of the archive.
# This will not work on >= 1.18.0 since version information is now
# appended to the file's name (e.g. RELEASE-NOTES-1.18).
regexes = make_list();
regexes[0] = make_list("= MediaWiki release notes =");
regexes[1] = make_list("== MediaWiki " + ver_capture + " ==");
checks["/RELEASE-NOTES"] = regexes;

foreach uri (uris)
{
  # Quick optimization :
  # if a substring of the uri has
  # already been identified as
  # an install, skip it.
  # e.g. if we see /installurl/ and
  # then see /installurl/somepage
  # then don't even check the second one.
  seen = FALSE;
  foreach interim_uri (keys(interim_installs))
    if (stridx(uri, interim_uri) == 0)
      seen = TRUE;

  if (seen) continue;

  foreach check (keys(checks))
  {
    version = NULL;
    ctrl_regex_pass = FALSE;
    res = http_send_recv3(
      item         : uri + check,
      method       : "GET",
      port         : port,
      follow_redirect : 5,
      exit_on_fail : TRUE
    );

    # Is this mediawiki?
    regexes = checks[check];
    foreach regex (regexes[0])
    {
      egrep_res = egrep(string:res[2], pattern:regex);
      if (strlen(egrep_res) > 0)
      {
        ctrl_regex_pass = TRUE;
        break;
      }
    }
    if (!ctrl_regex_pass) continue;

    # If so, get the version
    foreach regex (regexes[1])
    {
      matches = eregmatch(string:res[2], pattern:regex, icase:TRUE);
      if (!isnull(matches))
      {
        version = matches[1];
        break;
      }
    }

    if (!isnull(version))
    {
      interim_installs[uri] = version;
      break;
    }
  }
}

if (max_index(keys(interim_installs)) == 0) audit(AUDIT_WEB_APP_NOT_INST, app, port);

# Now that we have a list of potential installs,
# need to 'uniq' them to remove logical duplicates,
# e.g., /url1/page1 and /url1 are the same install,
# so only keep /url1
# 'remove' means set to NULL and ignore later
foreach item (sort(keys(interim_installs)))
{
  foreach item2 (keys(interim_installs))
  {
    if (item != item2 && stridx(item, item2) == 0)
    {
      interim_installs[item] = NULL;
      break;
    }
  }
}

# Store installs
foreach url (keys(interim_installs))
{
  dir = url;
  version = interim_installs[url];

  register_install(
    vendor   : "MediaWiki",
    product  : "MediaWiki",
    app_name : app,
    path     : dir,
    port     : port,
    version  : version,
    cpe      : "cpe:/a:mediawiki:mediawiki",
    webapp   : TRUE
  );
}
report_installs(port:port);
VendorProductVersionCPE
mediawikimediawikicpe:/a:mediawiki:mediawiki