#VERSION,2.04 # $Id: nikto_httpoptions.plugin 155 2009-08-13 21:43:24Z deity $ ############################################################################### # Copyright (C) 2006 CIRT, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; version 2 # of the License only. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ############################################################################### ############################################################################### # PURPOSE # HTTP options check ############################################################################### sub nikto_httpoptions_init { my $id = { name => "httpoptions", full_name => "HTTP Options", author => "Sullo", description => "Performs a variety of checks against the HTTP options returned from the server.", scan_method => \&nikto_httpoptions, copyright => "2008 CIRT Inc." }; return $id; } # This just gets the HTTP options & checks 'em out. # See RFC 2626 for more info... sub nikto_httpoptions { my ($mark) = @_; my %headers; # test for both OPTIONS / and OPTIONS * as they may give different results (my $res, $content) = nfetch($mark,"*", "OPTIONS", "", \%headers); my $aoptions = "$headers{allow}, "; my $poptions = "$headers{public}, "; my ($allow_methods, $public_methods, $txt); my $dbarray; $dbarray=initialise_db("db_httpoptions"); ($res, $content) = nfetch($mark,"/", "OPTIONS", "", \%headers); $aoptions .= $headers{allow}; $poptions .= $headers{public}; foreach my $o (split(/,[ ]?/, $aoptions)) { $allow_methods .= ", $o" unless ($allow_methods =~ /\b$o\b/ || $o eq ''); } $allow_methods =~ s/^[ ]?, //; foreach my $o (split(/,[ ]?/, $poptions)) { $public_methods .= ", $o" unless ($public_methods =~ /\b$o\b/ || $o eq ''); } $public_methods =~ s/^[ ]?, //; # proxy can impose it's methods... should actually check this not just warn if ($CLI{useproxy} ne "") { $txt = "(May be proxy's methods, not server's)"; } if ($allow_methods ne "") { add_vulnerability($mark,"Allowed HTTP Methods: $allow_methods $txt",999990,0); foreach my $m (split /,? /, $allow_methods) { eval_methods($m, "Allow", $dbarray,$mark); } } if ($public_methods ne "") { add_vulnerability($mark,"Public HTTP Methods: $public_methods $txt",999985,0); foreach my $m (split /,? /, $public_methods) { eval_methods($m, "Public", $dbarray,$mark); } } # Check for other weirdness # IIS Debug ($res, $content) = nfetch($mark,"/","DEBUG",); if ($res == 200) { add_vulnerability($mark,"DEBUG HTTP verb may show server debugging information",999972,0,"DEBUG"); } # IIS PROPFIND HEADER my %headers=( "Host" => "", "Content-Length" => "0", ); ($res, $content) = nfetch($mark,"/","PROPFIND","",\%headers,1); if ($res == 207) { if ($content =~ "http://") { my $ipfound=$content; $ipfound =~ s/^.*//g; $ipfound =~ s/<\/a:href>.*$//g; add_vulnerability($mark,"PROPFIND HTTP verb may show the server's internal IP address: $ipfound",999973,13431); } } # Special checks for TRACE/TRACK to see whether its vulnerable my %headers=( "Host" => "Nikto", ); foreach my $method (split(/ /,"TRACE TRACK")) { # Check for all flavours of HTTP foreach my $version (split(/ /,"1.0 1.1")) { $request{whisker}{version} = $version; ($res, $content) = nfetch($mark,"/","$method","",\%headers); if ($res == 200) { if ($content =~ "Nikto") { add_vulnerability($mark,"HTTP $method method is active, suggesting the host is vulnerable to XST",999971,877); # now we know its vulnerable stop testing last; } } } } # Now release memory for the dbarray undef @$dbarray; return; } sub eval_methods { my $method = $_[0] || return; my $type = $_[1]; my $dbarray = $_[2]; my $mark = $_[3]; my $message; $method = uc($method); # Now search database for the method. foreach my $item (@$dbarray) { if ($item->{method} eq $method) { $message = $item->{message}; $message =~ s/\@TYPE\@/$type/; add_vulnerability($mark,"$message",$item->{nikto_id},$item->{osvdb}); } } } 1;