#VERSION,2.06 # $Id: nikto_httpoptions.plugin 300 2010-02-01 21:02:40Z sullo $ ############################################################################### # 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, "", "httpoptions: OPTIONS *"); my $aoptions = "$headers{'allow'}, "; my $poptions = "$headers{'public'}, "; my ($allow_methods, $public_methods); my $txt = ""; my $dbarray; $dbarray=init_db("db_httpoptions"); ($res, $content) = nfetch($mark, "/", "OPTIONS", "", \%headers, "", "httpoptions: OPTIONS /"); $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", "" ,"" ,"" ,"httpoptions: DEBUG"); if ($res == 200) { add_vulnerability($mark,"DEBUG HTTP verb may show server debugging information. See http://msdn.microsoft.com/en-us/library/e8z01xdh%28VS.80%29.aspx for details.",999972,0,"DEBUG"); } # IIS PROPFIND HEADER %headers=( "Host" => "", "Content-Length" => "0", ); ($res, $content) = nfetch($mark, "/", "PROPFIND", "", \%headers, 1, "httpoptions: PROPFIND"); 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 %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, "", "httpoptions: $method"); 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;