Lucene search
+L

Open Ticket Request System (OTRS) and ITSM Detection (HTTP)

🗓️ 22 Feb 2010 00:00:00Reported by Copyright (C) 2010 Greenbone AGType 
openvas
 openvas
🔗 plugins.openvas.org👁 25 Views

Open Ticket Request System (OTRS) and ITSM Detection (HTTP) based on HTTP request and response for OTRS installatio

Refs
Code
SourceLink
otrscommunityeditionwww.otrscommunityedition.com/
otrswww.otrs.com/
# SPDX-FileCopyrightText: 2010 Greenbone AG
# Some text descriptions might be excerpted from (a) referenced
# source(s), and are Copyright (C) by the respective right holder(s).
#
# SPDX-License-Identifier: GPL-2.0-only

if(description)
{
  script_oid("1.3.6.1.4.1.25623.1.0.902018");
  script_version("2026-04-29T06:25:32+0000");
  script_tag(name:"cvss_base", value:"0.0");
  script_tag(name:"cvss_base_vector", value:"AV:N/AC:L/Au:N/C:N/I:N/A:N");
  script_tag(name:"last_modification", value:"2026-04-29 06:25:32 +0000 (Wed, 29 Apr 2026)");
  script_tag(name:"creation_date", value:"2010-02-22 13:34:53 +0100 (Mon, 22 Feb 2010)");

  script_tag(name:"qod_type", value:"remote_banner");

  script_name("Open Ticket Request System (OTRS) and ITSM Detection (HTTP)");

  script_category(ACT_GATHER_INFO);

  script_copyright("Copyright (C) 2010 Greenbone AG");
  script_family("Product detection");
  script_dependencies("find_service.nasl", "no404.nasl", "webmirror.nasl",
                      "DDI_Directory_Scanner.nasl", "global_settings.nasl");
  script_require_ports("Services/www", 443);
  script_exclude_keys("Settings/disable_cgi_scanning");

  script_tag(name:"summary", value:"HTTP based detection of Open Ticket Request System (OTRS) and
  ITSM.");

  script_add_preference(name:"OTRS Web UI Username", value:"", type:"entry", id:1);
  script_add_preference(name:"OTRS Web UI Password", value:"", type:"password", id:2);

  script_xref(name:"URL", value:"https://otrs.com/");
  script_xref(name:"URL", value:"https://otrscommunityedition.com/");

  exit(0);
}

include("cpe.inc");
include("host_details.inc");
include("http_func.inc");
include("http_keepalive.inc");
include("list_array_func.inc");
include("misc_func.inc");
include("port_service_func.inc");

# TODO: We might want to enumerate additional existing "OTRS Business" features.
# On OTRS 5.0.x the following features from https://community.otrs.com/download-otrs-community-edition/ where enumerated and (if a Public Route was available) added to the array:
# FAQ, Fred, OTRSCloneDB, OTRSCodePolicy, OTRSMasterSlave, Survey, SystemMonitoring, TimeAccounting, OTRSAppointmentCalendar
#
# nb: The array contains the URL and a regex which should match for the detection
features = make_array( "/public.pl?Action=PublicFAQExplorer#---#FAQ", "(<title>FAQ - .*</title>|<h1>FAQ Explorer</h1>)",  # e.g. <title>FAQ -  OTRS 6</title> or <title>FAQ -  OTRS 5</title>
                       "/public.pl?Action=PublicSurvey#---#Survey", "(<title>Survey - .*</title>|<h2> Survey Error! </h2>)", # e.g. <title>Survey - Survey -  OTRS 5s</title>, nb: The "Action" variable normally has a ;PublicSurveyKey=<OTRS_PublicSurveyKey> attached but we just want to trigger the error...
                       "/public.pl?Action=PublicCalendar#---#OTRSAppointmentCalendar", "<p>No CalendarID!</p>",  # nb: The "Action" variable normally has a &CalendarID= attached but we just want to trigger the error...
                       "/index.pl#---#Fred", '<div class="(DevelFredBox|DevelFredContainer)"', # nb: This is added to each page, e.g. <div class="DevelFredBox"> or <div class="DevelFredContainer" id="DevelFredContainer">
                       "/public.pl?Action=PublicRepository#---#Public package repository", "<title>PublicRepository.*</title>" # TODO: The pattern needs to be verified on a system where this is working...
                     );

port = http_get_port( default:443 );

foreach dir( make_list_unique( "/", "/support", "/OTRS", "/otrs", http_cgi_dirs( port:port ) ) ) {

  otrsInstalled = FALSE;
  conclUrl = NULL;
  install = dir;
  if( dir == "/" )
    dir = "";

  # nb: index.pl doesn't have the version exposed (at least not in OTRS 3 up to OTRS 5)
  # so keep this as the last file to check...
  foreach path( make_list( "/public.pl", "/installer.pl", "/index.pl", "/customer.pl" ) ) {

    url = dir + path;
    req = http_get( item:url, port:port );
    res = http_keepalive_send_recv( port:port, data:req, bodyonly:TRUE );

    if( res && ( egrep( pattern:"(Powered by OTRS|Powered by.*OTRS|<title>Login - OTRS</title>)", string:res ) ||
        # <title>Login - ((OTRS)) Community Edition</title>
        # ((OTRS)) Community Edition detected possible network issues.
        "(OTRS)) Community Edition" >< res || "OTRS detected possible network issues" >< res ||
        "OTRS runs with a huge lists of browsers" >< res || "<title>Login - OTRS" >< res ) ) {

      banner = http_get_remote_headers( port:port, file:url );

      otrsInstalled = TRUE;
      version = "unknown";

      conclUrl = "  " + http_report_vuln_url( port:port, url:url, url_only:TRUE );

      ## Pattern for OTRS 4 and up
      vers = eregmatch( pattern:'title="OTRS ([0-9.]+)"', string:res );
      if( vers[1] )
        version = vers[1];

      if( version == "unknown" ) {
        ## Pattern for OTRS 3
        vers = eregmatch( pattern:"Powered by.*>OTRS ([0-9.]+)<", string:res );
        if( vers[1] )
          version = vers[1];
      }

      if( version == "unknown" ) {
        ## Pattern for OTRS below version 3
        vers = eregmatch( pattern:">Powered by OTRS ([0-9.]+)<", string:res );
        if( vers[1] )
          version = vers[1];
      }

      if( version == "unknown" ) {
        # X-Powered-By: OTRS 5.0.1 - Open Ticket Request System (http://www.otrs.com/)
        # X-Powered-By: OTRS 3.0.11 - Open Ticket Request System (http://otrs.org)
        # X-Powered-By: OTRS 3.2.8 - Open Ticket Request System (http://otrs.org)
        # X-Powered-By: OTRS 3.3.x git - Open Ticket Request System (http://otrs.org/)
        vers = eregmatch( pattern:"X-Powered-By\s*:\s*OTRS ([0-9]+\.[0-9.x]+)", string:banner, icase:FALSE );
        if( vers[1] )
          version = vers[1];
      }

      # nb: We have the version, no need to continue with the other .pl files...
      if( version != "unknown" )
        break;
    }
  }

  if( otrsInstalled ) {

    extra = "";

    foreach feature( keys( features ) ) {
      _split = split( feature, sep:"#---#", keep:FALSE );
      if( max_index( _split ) != 2 ) continue; # nb: Something went wrong with the syntax...
      _feature = _split[0];
      _desc    = _split[1];
      url = dir + _feature;
      req = http_get( item:url, port:port );
      res = http_keepalive_send_recv( port:port, data:req, bodyonly:TRUE );
      if( egrep( string:res, pattern:features[feature] ) ) {
        extra += "  " + http_report_vuln_url( url:url, port:port, url_only:TRUE ) + ' (Feature: ' +
                 _desc + ')\n';
      }
    }

    if( extra )
      extra = 'The following additional installed features have been identified:\n' + extra;

    if( version == "unknown" ) {
      user = script_get_preference( "OTRS Web UI Username", id:1 );
      pass = script_get_preference( "OTRS Web UI Password", id:2 );

      if( ! user && ! pass ) {
        extra += '\nNote: No username and password for web authentication were provided. Please pass these for version extraction.';
      } else if( ! user && pass ) {
        extra += '\nNote: Password for web authentication was provided but username is missing. Please provide both.';
      }  else if( user && ! pass ) {
        extra += '\nNote: Username for web authentication was provided but password is missing. Please provide both.';
      } else if( user && pass ) {
        url = dir + "/index.pl";

        headers = make_array( "Content-Type", "application/x-www-form-urlencoded" );

        data = "Action=Login&RequestedURL=&Lang=en&TimeZoneOffset=-420&User=root%40localhost&Password=changeme";

        req = http_post_put_req( port:port, url:url, data:data, add_headers: headers );
        res = http_keepalive_send_recv( port:port, data:req );

        if( res =~ "^HTTP/1\.[01] 302" && res =~ "OTRSAgentInterface=[^; ]+" ) {
          token = http_get_cookie_from_header( buf:res, pattern:"(OTRSAgentInterface=[^; ]+)" );

          url = dir + "/index.pl?Action=AdminSupportDataCollector";

          headers = make_array( "Cookie", token );

          req = http_get_req( port:port, url:url, add_headers:headers );
          res = http_keepalive_send_recv( port:port, data:req, bodyonly:TRUE );

          # >Version</td>  <td>6.0.39</td>
          vers = eregmatch( pattern: ">Version</td>[^<]*<td>([0-9.]+)</td>", string:res );
          if( ! isnull( vers[1] ) ) {
            version = vers[1];
            conclUrl += '\n  ' + http_report_vuln_url( port:port, url:url, url_only:TRUE );
          }
        } else {
          extra += '\nNote: Username and password were provided but authentication failed.';
        }
      }
    }

    set_kb_item( name:"otrs/detected", value:TRUE );
    set_kb_item( name:"otrs/http/detected", value:TRUE );

    cpe = build_cpe( value:version, exp:"^([0-9.x]+)", base:"cpe:/a:otrs:otrs:" );
    if( ! cpe )
      cpe = "cpe:/a:otrs:otrs";

    register_product( cpe:cpe, location:install, port:port, service:"www" );

    log_message( data:build_detection_report( app:"OTRS", version:version, install:install, cpe:cpe,
                                              concluded:vers[0], concludedUrl:conclUrl, extra:chomp( extra ) ),
                 port:port );
  }

  ## To detect OTRS::ITSM
  url = dir + "/index.pl";
  res = http_get_cache( item:url, port:port );

  if( res && ( "Welcome to OTRS::ITSM" >< res || "<title>Login - OTRS::ITSM" >< res ||
               "OTRS::ITSM" >< res ) ) {

    version = "unknown";

    vers = eregmatch( pattern:"Welcome to OTRS::ITSM ([0-9\.\w]+)", string:res );
    if( ! isnull(vers[1] ) ) {
      version = vers[1];
      conclUrl = http_report_vuln_url( port:port, url:url, url_only:TRUE );
    }

    set_kb_item( name:"otrs/detected", value:TRUE );
    set_kb_item( name:"otrs/http/detected", value:TRUE );
    set_kb_item( name:"otrs/itms/detected", value:TRUE );
    set_kb_item( name:"otrs/itms/http/detected", value:TRUE );

    cpe = build_cpe( value:version, exp:"^([0-9.]+)", base:"cpe:/a:otrs:otrs_itsm:" );
    if( ! cpe )
      cpe = "cpe:/a:otrs:otrs_itsm";

    register_product( cpe:cpe, location:install, port:port, service:"www" );

    log_message( data:build_detection_report( app:"OTRS ITSM", version:version, install:install, cpe:cpe,
                                              concluded:vers[0], concludedUrl:conclUrl ),
                 port:port );
  }
}

exit( 0 );

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

29 Apr 2026 00:00Current
5.2Medium risk
Vulners AI Score5.2
25