Open Ticket Request System (OTRS) and ITSM Detection (HTTP)
🗓️ 22 Feb 2010 00:00:00Reported by Copyright (C) 2010 Greenbone AGType
openvas🔗 plugins.openvas.org👁 25 Views
| Source | Link |
|---|---|
| otrscommunityedition | www.otrscommunityedition.com/ |
| otrs | www.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