Nikto (NASL wrapper)

2004-08-11T00:00:00
ID NIKTO.NASL
Type nessus
Reporter This script is Copyright (C) 2004-2018 Tenable Network Security, Inc.
Modified 2004-08-11T00:00:00

Description

This plugin runs Nikto2, an open source (GPL) web server scanner used to perform comprehensive tests for multiple issues, such as outdated server versions, potentially dangerous files or programs, version specific problems, various configuration items, etc.

See the section

                                        
                                            #TRUSTED 10f1c3b06b272fe12b85181df7d93f0a41e8b7abeae04141b53934e3cbc6359bd3912f8d9d04da0be068bb054431772ff96b4534ee736ed7ee69b88a19e52f37c8ea3b62d5a1f012257325a8e87596beb2d6c9a6c3bc8561112817ac8e983102620c54a341570c5905494bf99cf3787257b6218297f4e3a0355dfad7f3a201f4e639298d19da1c6162221b7279a5551558fc42e36dbc248fb377c5d0249ae49df68a9a0b420cbe8d11f5fb6ea2d90b6b27d700a0cf426237c554bdbdcf51c27118e06fc5c45471b48ee93049e15c00cd4ed51ad955cc9884b50214a7b7ce79c65dee76927723a5de54cc9f7cad8d9be9e296b1ed9dd9cc34f63fb495ae96b6643175bd3755f6ae792a5cc8b079411237f318f6f349d7a7baa8c60f4742811e68d7aca79127db34cdd3318c9b9f4b810f730fda4e1cdba11d9f3e9d3b82499c8ecd188acf6f0e61a8d244e8f98b071530305f2e26723db6e522ebc8cd3c3b3f608ca496140d0dd0241a16267733eae5706b520ce93c3b2326e197eef7885ed6ff6d09559f1fa492983fba4227f2d24468fe71662e4f826ba73e44728266e11e0af6729270718901c99267ff0e6521d0db16305ff4f6bafda8e8818d09746f83a120330fa4f937dd32010f8716b342ca09d3feb3a7d946841d86c70043ea43a97f9ed3828f931519224e72d387df9635f957e989fc99c6652082c8ad06379ac761
#
# (C) Tenable Network Security, Inc.
#

if (NASL_LEVEL >= 6000) exit(0);

if ( ! defined_func("pread")) exit(0, "nikto.nasl cannot run: pread() is not defined.");
cmd = NULL;

if ( find_in_path("nikto.pl") ) cmd = "nikto.pl";
else if ( find_in_path("nikto") ) cmd = "nikto";

if ( ! cmd && description) {
	if ( NASL_LEVEL < 3000 ) exit(0);
	exit(0, "Nikto was not found in '$PATH'.");
}

include("compat.inc");

if(description)
{
 script_id(14260);
 script_version ("1.34");
 script_set_attribute(attribute:"plugin_modification_date", value:"2018/11/15"); 

 script_name(english: "Nikto (NASL wrapper)");
 script_summary(english: "Run Nikto2.");
 
 script_set_attribute(attribute:"synopsis", value:
"This plugin runs Nikto2." );
 script_set_attribute(attribute:"description", value:
"This plugin runs Nikto2, an open source (GPL) web server scanner used
to perform comprehensive tests for multiple issues, such as outdated
server versions, potentially dangerous files or programs, version
specific problems, various configuration items, etc.

See the section 'plugins options' to configure it.");
 script_set_attribute(attribute:"see_also", value:"https://cirt.net/nikto2" );
 script_set_attribute(attribute:"solution", value:"n/a" );
 script_set_attribute(attribute:"risk_factor", value:"None" );

 script_set_attribute(attribute:"plugin_publication_date", value: "2004/08/11");

 script_set_attribute(attribute:"plugin_type", value:"remote");
 script_end_attributes();

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

 script_copyright(english:"This script is Copyright (C) 2004-2018 Tenable Network Security, Inc.");

 script_dependencies("http_version.nasl", "find_service1.nasl", "httpver.nasl", "logins.nasl", "no404.nasl");
 script_require_ports("Services/www", 80);

 script_timeout(0);
 script_add_preference(name:"Enable Nikto", type:"checkbox", value:"no");
 script_add_preference(name:"Disable if server never replies 404", type:"checkbox", value:"yes");

 script_add_preference(name:"Root directory", type:"entry", value:"");
 script_add_preference(name:"Pause between tests (s)", type:"entry", value:"");
 script_add_preference(name:"Scan CGI directories",
                       type:"radio", value:"User supplied;All;None");
 script_add_preference(type: "checkbox", value: "no", name: "Display: 1 Show redirects");
 script_add_preference(type: "checkbox", value: "no", name: "Display: 2 Show cookies received");
 script_add_preference(type: "checkbox", value: "no", name: "Display: 3 Show all 200/OK responses");
 script_add_preference(type: "checkbox", value: "no", name: "Display: 4 Show URLs which require authentication");
 script_add_preference(type: "checkbox", value: "no", name: "Display: V Verbose Output");

 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 1 Interesting File / Seen in logs");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 2 Misconfiguration / Default File");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 3 Information Disclosure");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 4 Injection (XSS/Script/HTML)");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 5 Remote File Retrieval - Inside Web Root");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 6 Denial of Service");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 7 Remote File Retrieval - Server Wide");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 8 Command Execution / Remote Shell");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 9 SQL Injection");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: 0 File Upload");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: a Authentication Bypass");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: b Software Identification");
 script_add_preference(type: "checkbox", value: "no", name: "Tuning: c Remote Source Inclusion");
 if ( NASL_LEVEL >= 3000 )
  script_add_preference(type: "checkbox", value: "no", name: "Tuning: x Reverse Tuning Options (i.e., include all except specified)");

 script_add_preference(type: "checkbox", value: "no", name: "Mutate: 1 Test all files with all root directories");
 script_add_preference(type: "checkbox", value: "no", name: "Mutate: 2 Guess for password file names");
 if ( NASL_LEVEL >= 3000 )
 {
  script_add_preference(type: "checkbox", value: "no", name: "Mutate: 3 Enumerate user names via Apache (/~user type requests)");
  script_add_preference(type: "checkbox", value: "no", name: "Mutate: 4 Enumerate user names via cgiwrap (/cgi-bin/cgiwrap/~user type requests)");
 }

 exit(0);
}

#

function my_cgi_dirs()	# Copied from http_func.inc
{
 local_var	kb;
 kb = get_kb_list("/tmp/cgibin");
 if(isnull(kb)) kb = make_list("/cgi-bin", "/scripts", "");
 else kb = make_list(kb, "");
}

if (! COMMAND_LINE)
{
 p = script_get_preference("Enable Nikto");
 if ( "yes" >!< p ) exit(0, "Nikto is not enabled (per policy).");
}

if (! defined_func("pread"))
{
  set_kb_item(name: "/tmp/UnableToRun/14254", value: TRUE);
  display("Script #14254 (nikto_wrapper) cannot run\n");
  exit(0, "nikto.nasl cannot run: pread() is not defined.");
}

if (! cmd)
{
  display("Nikto was not found in $PATH\n");
  exit(0, "Nikto was not found in '$PATH'.");
}

user = get_kb_item("http/login");
pass = get_kb_item("http/password");
ids = get_kb_item("Settings/Whisker/NIDS");

port = get_kb_item("Services/www");
if (! port) port = 80;
if (! get_port_state(port)) exit(0, "No open HTTP port.");

# Nikto may generate many false positives if the web server is broken
p = script_get_preference("Disable if server never replies 404");
if ("yes" >< p || "no" >!< p)
{
no404 = get_kb_item("www/no404/" + port);
  if ( no404 ) exit(0, "The web server on port "+port+" does not return 404 codes.");
  s = http_open_socket(port);
  if (! s) exit(1, "TCP connection to port "+port+" failed.");
  r = http_get(port: port, item: '/'+ rand()+'/'+rand()+'.cgi');
  send(socket: s, data: r);
  r = recv_line(socket: s, length: 512);
  http_close_socket(s);
  if (r =~ '^HTTP/[0-9.]+ +(200|40[13])')
   exit(1, "The web server on port "+port+" does not return 404 code on random pages.");
}

i = 0;
argv[i++] = cmd;

p = script_get_preference("Scan CGI directories");
if (p)
if ("User supplied" >!< p)
{
 argv[i++] = "-Cgidirs";
 argv[i++] = tolower(p);
}
else
{
 v = my_cgi_dirs();
 n = 0;
 if (! isnull(v))   n = max_index(v);
 if (n > 0)
 {
  l = "";
  for (j = 0; j < n; j ++)
  {
   l = strcat(l, v[j]);
   if (! match(string: v[j], pattern: "*/")) l = strcat(l, "/");
   l = strcat(l, " ");
  }
  argv[i++] = "-Cgidirs";
  argv[i++] = l;
 }
}

httpver = get_kb_item("http/"+port);
if (httpver == "11")
{
  argv[i++] = "-vhost";
  argv[i++] = get_host_name();
}

display='';
l = make_list("Display: 1 Show redirects", 
	"Display: 2 Show cookies received",
	"Display: 3 Show all 200/OK responses", 
	"Display: 4 Show URLs which require authentication",
	"Display: V Verbose Output");

foreach opt (l)
{
 p = script_get_preference(opt);
 if ("yes" >< p) display = strcat(display, substr(opt, 9, 9));
}

if (display)
{
 argv[i++] = "-Display";
 argv[i++] = display;
}

mutate = '';
l = make_list("Mutate: 1 Test all files with all root directories",
	"Mutate: 2 Guess for password file names",
	"Mutate: 3 Enumerate user names via Apache (/~user type requests)",
	"Mutate: 4 Enumerate user names via cgiwrap (/cgi-bin/cgiwrap/~user type requests)");
foreach opt (l)
{
 p = script_get_preference(opt);
 if ("yes" >< p) mutate = strcat(mutate, substr(opt, 8, 8));
}
if (strlen(mutate) > 0)
{
 argv[i++] = "-mutate";
 argv[i++] = mutate;
}

p = script_get_preference("Pause between tests (s)");
p = int(p);
if (p > 0)
{
 argv[i++] = "-Pause";
 argv[i++] = p;
}

p = script_get_preference("Root directory");
if (strlen(p) > 0)
{
 argv[i++] = "-root";
 argv[i++] = p;
}


l = make_list("Tuning: 1 Interesting File / Seen in logs",
	"Tuning: 2 Misconfiguration / Default File",
	"Tuning: 3 Information Disclosure",
	"Tuning: 4 Injection (XSS/Script/HTML)",
	"Tuning: 5 Remote File Retrieval - Inside Web Root",
	"Tuning: 6 Denial of Service",
	"Tuning: 7 Remote File Retrieval - Server Wide",
	"Tuning: 8 Command Execution / Remote Shell",
	"Tuning: 9 SQL Injection",
	"Tuning: 0 File Upload",
	"Tuning: a Authentication Bypass",
	"Tuning: b Software Identification",
	"Tuning: c Remote Source Inclusion",
	"Tuning: x Reverse Tuning Options (i.e., include all except specified)");
tuning= '';
foreach opt (l)
{
 p = script_get_preference(opt);
 if ("yes" >< p) tuning = strcat(tuning, substr(opt, 8, 8));
}
if (strlen(tuning) > 0)
{
 argv[i++] = "-Tuning";
 argv[i++] = tuning;
}


p = int(get_preference("checks_read_timeout"));
if (p > 0)
{
 argv[i++] = "-timeout";
 argv[i++] = p;
}

argv[i++] = "-host"; argv[i++] = get_host_ip();
argv[i++] = "-port"; argv[i++] = port;

encaps = get_port_transport(port);
if (encaps > 1) argv[i++] = "-ssl";

#p = script_get_preference("Force scan all possible CGI directories");
#if ("yes" >< p) argv[i++] = "-allcgi";
p = script_get_preference("Force full (generic) scan");
if ("yes" >< p) argv[i++] = "-generic";

if (idx && idx != "X")
{
  argv[i++] = "-evasion";
  argv[i++] = ids[0];
}

if (user)
{
  if (pass)
    s = strcat(user, ':', pass);
  else
    s = user;
  argv[i++] = "-id";
  argv[i++] = s;
}

r = pread(cmd: cmd, argv: argv, cd: 1);
if (! r)
{
 s = '';
 for (i = 0; ! isnull(argv[i]); i ++) s = strcat(s, argv[i], ' ');
 display('Command exited in error: ', s, '\n');
 exit(0, "Command exited with an error.");	# error
}
if ("No HTTP(s) ports found" >< r) exit(0, "Nikto did not find any HTTP ports.");

report = '\nHere is the Nikto report :\n\n';
foreach l (split(r))
{
  #display(j ++, "\n");
  l = ereg_replace(string: l, pattern: '^[ \t]+', replace: '');
  if (l[0] == '+' || l[0] == '-' || ! match(pattern: "ERROR*", string: l))
    report += l;
}

security_note(port: port, extra: report);
if (COMMAND_LINE) display(report, '\n');