📄 nikto_core.plugin
字号:
foreach my $toget (@DBTOGET) { print "+ Retrieving '$toget'\n"; (my $RES, $CONTENT) = fetch("$serverdir/$toget","GET"); if ($RES ne 200) { print STDERR "+ ERROR: Unable to get $server$serverdir/$toget\n"; exit; } if ($CONTENT ne "") { open(OUT,">$NIKTO{plugindir}/$toget") || die print STDERR "+ ERROR: Unable to open '$NIKTO{plugindir}/$toget' for write: $@\n"; print OUT $CONTENT; close(OUT); } }# CHANGES fileif ($code_updates) { print "+ Retrieving 'CHANGES.txt'\n"; (my $RES, $CONTENT) = fetch("$serverdir/CHANGES.txt","GET"); if (($CONTENT ne "") && ($RES eq 200)) { open(OUT,">$NIKTO{plugindir}/../docs/CHANGES.txt") || die print STDERR "+ ERROR: Unable to open '$NIKTO{plugindir}/../CHANGES.txt' for write: $@\n"; print OUT $CONTENT; close(OUT); } }if ($#DBTOGET < 0 ) { print "+ No updates required.\n"; }if ($remotemsg ne "") { print "+ $server message: $remotemsg\n"; }exit;}###############################################################################sub auth_guess{ my ($realm, $checkid) = @_; my $successful=0; # check for 'broken' web server, returns a blank www-auth header no matter what the id/pw sent my $tid=LW2::utils_randstr(); LW2::http_close(\%request); # force-close any old connections LW2::auth_set("basic",\%request,$tid,$tid); $request{'whisker'}->{'http_eol'}=$http_eol; LW2::http_fixup_request(\%request); if ($CLI{pause} > 0) { sleep $CLI{pause}; } LW2::http_do_request_timeout(\%request,\%result); # test auth if ($result{'www-authenticate'} ne "") { foreach my $REALM (keys %REALMS) { if (($REALMS{$REALM}{id} eq "") && ($REALMS{$REALM}{pw} eq "") && ($result{'www-authenticate'} =~ /$REALMS{$REALM}{realm}/i)) { nprint("+ $REALMS{$REALM}{realm}: $REALMS{$REALM}{msg}"); $TARGETS{$CURRENT_HOST_ID}{positives}{$REALMS{$REALM}{tid}}=1; $TARGETS{$CURRENT_HOST_ID}{total_vulns}++; } if (($result{'www-authenticate'} =~ /$REALMS{$REALM}{realm}/i) || ($REALMS{$REALM}{realm} eq "\@ANY")) { my $realm_temp=$result{'www-authenticate'}; # grab name LW2::http_close(\%request); # force-close any old connections LW2::auth_set("basic",\%request,$REALMS{$REALM}{id},$REALMS{$REALM}{pw}); # set auth $request{'whisker'}->{'http_eol'}=$http_eol; LW2::http_fixup_request(\%request); if ($CLI{pause} > 0) { sleep $CLI{pause}; } LW2::http_do_request_timeout(\%request,\%result); # test auth if ($result{'www-authenticate'} eq "") { nprint("+ Default account found for '$realm' at $TESTS{$checkid}{uri} (ID '$REALMS{$REALM}{id}', PW '$REALMS{$REALM}{pw}'). $REALMS{$REALM}{msg}"); $TARGETS{$CURRENT_HOST_ID}{positives}{$REALMS{$REALM}{tid}}=1; $TARGETS{$CURRENT_HOST_ID}{total_vulns}++; #set auth stuff & run auth_check again $NIKTO{hostid}=$REALMS{$REALM}{id}; $NIKTO{hostpw}=$REALMS{$REALM}{pw}; $result{'www-authenticate'}=$realm_temp; # set it back so auth_check properly checks it auth_check(); # and lastly, redo the check $successful=1; (my $RES, $CONTENT) = fetch($TESTS{$checkid}{uri},$TESTS{$checkid}{method},$TESTS{$checkid}{data}); nprint("- $RES for $TESTS{$checkid}{method}:\t$request{whisker}{uri}","v"); last; } } } } else { print "+ ERROR: Authorization is required, but bogus auth test appeared to work. Server is a bit whacked.\n"; } $REALMS_TESTED{$realm}=1; my $pa = $request{'Proxy-Authorization'}; LW2::auth_unset(\%request); if ($pa ne '') { $request{'Proxy-Authorization'} = $pa; }}################################################################################ auth_check# if the server requires authentication & we have it...###############################################################################sub auth_check{ my $REALM=$result{'www-authenticate'} || return; $REALM =~ s/^Basic //i; $REALM =~ s/realm=//i; if ($REALM eq "") { $REALM="unnamed"; }if ($result{'www-authenticate'} !~ /basic|ntlm/i) # doh, not basic! { my $AUTHTYPE=$result{'www-authenticate'}; $AUTHTYPE =~ s/ .*$//; nprint("+ ERROR: Host uses '$AUTHTYPE'"); return; }elsif ($NIKTO{hostid} eq "") { nprint("+ ERROR: No auth credentials for $REALM, please set."); return; }else { nprint("- Attempting authorization to $REALM realm.","v"); LW2::auth_set("basic",\%request,$NIKTO{hostid},$NIKTO{hostpw},$NIKTO{hostdomain}); # set auth LW2::http_fixup_request(\%request); if ($CLI{pause} > 0) { sleep $CLI{pause}; } $request{'whisker'}->{'http_eol'}=$http_eol; LW2::http_do_request_timeout(\%request,\%result); # test auth dump_var("Request Hash", \%request); dump_var("Result Hash", \%result); if ($result{'www-authenticate'} ne "") { nprint("+ ERROR: Unable to authenticate to $REALM"); } else { nprint("- Successfully authenticated to realm $REALM."); } }return;}################################################################################ read_data ( prompt, mode )# read STDIN data from the user# portions of this (POSIX code) were taken from the # Term::ReadPassword module by Tom Phoenix <rootbeer@redcat.com> (many thanks).# it has been modified to not require Term::ReadLine, but still requires# POSIX::Termios of it's a POSIX machine###############################################################################sub read_data{ if ($NIKTOCONFIG{PROMPTS} =~ /no/i) { return; } my($prompt, $mode, $POSIX) = @_; my $input = ""; if ($^O =~ /Win32/) { $POSIX=0; } else { $POSIX=1; } my %SPECIAL = ( "\x03" => 'INT', # Control-C, Interrupt "\x08" => 'DEL', # Backspace "\x7f" => 'DEL', # Delete "\x0d" => 'ENT', # CR, Enter "\x0a" => 'ENT', # LF, Enter ); # if we're on a non-POSIX machine we can't not-echo the # characters, so just use getc to avoid the dependency on # POSIX::Termios. We would be best to get rid of this # entirely and use another way... if ($POSIX) { local(*TTY, *TTYOUT); open TTY, "<&STDIN" or return; open TTYOUT, ">>&STDOUT" or return; # Don't buffer it! select( (select(TTYOUT), $|=1)[0] ); print TTYOUT $prompt; # Remember where everything was my $fd_tty = fileno(TTY); my $term = POSIX::Termios->new(); $term->getattr($fd_tty); my $original_flags = $term->getlflag(); if ($mode eq "noecho") { my $new_flags = $original_flags & ~(ISIG | ECHO | ICANON); $term->setlflag($new_flags); } $term->setattr($fd_tty, TCSAFLUSH);KEYSTROKE: while (1) { my $new_keys = ''; my $count = sysread(TTY, $new_keys, 99); if ($count) { for my $new_key (split //, $new_keys) { if (my $meaning = $SPECIAL{$new_key}) { if ($meaning eq 'ENT') { last KEYSTROKE; } elsif ($meaning eq 'DEL') { chop $input; } elsif ($meaning eq 'INT') { last KEYSTROKE; } else { $input .= $new_key; } } else { $input .= $new_key; } } } else { last KEYSTROKE; } } # Done with waiting for input. Let's not leave the cursor sitting # there, after the prompt. print TTY "\n"; print "\n"; # Let's put everything back where we found it. $term->setlflag($original_flags); $term->setattr($fd_tty, TCSAFLUSH); close(TTY); close(TTYOUT); } else # non-POSIX { print $prompt; $input=<STDIN>; chomp($input); }return $input;}###############################################################################sub proxy_setup{ if (!$CLI{useproxy}) { return; } # HTTP proxy $request{'whisker'}->{'proxy_host'}=$NIKTOCONFIG{PROXYHOST}; $request{'whisker'}->{'proxy_port'}=$NIKTOCONFIG{PROXYPORT}; return; }###############################################################################sub proxy_check{ $request{'whisker'}->{'method'}="HEAD"; $request{'whisker'}->{'uri'}="/"; if ($request{'whisker'}->{'proxy_host'} ne "") # proxy is set up { LW2::http_close(\%request); # force-close any old connections $request{'whisker'}->{'http_eol'}=$http_eol; LW2::http_fixup_request(\%request); if ($CLI{pause} > 0) { sleep $CLI{pause}; } LW2::http_do_request_timeout(\%request,\%result); if ($result{'whisker'}{'code'} eq "407") # proxy requires auth { # have id/pw? if ($NIKTOCONFIG{PROXYUSER} eq "") { $NIKTOCONFIG{PROXYUSER}=read_data("Proxy ID: ",""); $NIKTOCONFIG{PROXYPASS}=read_data("Proxy Pass: ","noecho"); } if ($result{'proxy-authenticate'} !~ /Basic/i) { my @x=split(/ /,$result{'proxy-authenticate'}); nprint("+ Proxy server uses '$x[0]' rather than 'Basic' authentication. $NIKTO{name} $NIKTO{version} can't do that."); exit; } # test it... LW2::http_close(\%request); # force-close any old connections LW2::auth_set("proxy-basic",\%request,$NIKTOCONFIG{PROXYUSER},$NIKTOCONFIG{PROXYPASS}); # set auth $request{'whisker'}->{'http_eol'}=$http_eol; LW2::http_fixup_request(\%request); if ($CLI{pause} > 0) { sleep $CLI{pause}; } LW2::http_do_request_timeout(\%request,\%result); if ($result{'proxy-authenticate'} ne "") { my @pauthinfo=split(/ /,$result{'proxy-authenticate'}); my @pauthinfo2=split(/=/,$result{'proxy-authenticate'}); $pauthinfo2[1]=~s/^\"//; $pauthinfo2[1]=~s/\"$//; nprint("+ Proxy requires authentication for '$pauthinfo[0]' realm '$pauthinfo2[1]', unable to authenticate."); exit; } else { nprint("- Successfully authenticated to proxy.","v"); } } } $PROXYCHECKED=1; return;}###############################################################################sub dirlist{ my $DIR=$_[0] || return; my $PATTERN=$_[1] || ""; my @FILES_TMP = (); opendir(directory,$DIR) || die print STDERR "+ ERROR: Can't open directory '$DIR': $@"; foreach my $file (readdir(directory)) { if ($file =~ /^\./) { next; } # skip hidden files, '.' and '..' if ($PATTERN ne "") { if ($file =~ /$PATTERN/) { push (@FILES_TMP,$file); } } else { push (@FILES_TMP,$file); } }closedir(directory); return @FILES_TMP;}#######################################################################sub dump_var{ return if !$OUTPUT{debug}; my $msg = $_[0]; my %hash_in = %{$_[1]}; my $display = LW2::dump('', \%hash_in); $display =~ s/^\$/'$msg'/; nprint($display,"d"); return;}#######################################################################sub check_cgi{ my ($gotvalid,$gotinvalid)=0; my @POSSIBLECGI=(); my @CFGCGI=(split(/ /,$VARIABLES{"\@CGIDIRS"})); my ($res, $possiblecgidir) =""; if ($CLI{forcecgi} eq "all") # all possible CGI dirs to be "true" { nprint("Using 'all' CGI directories\n","d"); $VARIABLES{"\@CGIDIRS"} = join(" ",@CFGCGI); } elsif ($CLI{forcecgi} eq "none") # scan no CGI directories { nprint("Using no CGI directories\n","d"); $VARIABLES{"\@CGIDIRS"} = ""; } elsif ($CLI{forcecgi} =~ /[a-zA-Z0-9]/) # scan a specific directory { nprint("Using CGI dir '$CLI{forcecgi}'\n","d"); $VARIABLES{"\@CGIDIRS"} = $CLI{forcecgi}; } else # or normal testing of each dir { foreach $possiblecgidir (@CFGCGI) { ($res, $CONTENT)=fetch($possiblecgidir,"GET"); nprint("Checked for CGI dir\t$possiblecgidir\tgot:$res","d"); if (($res eq 302) || ($res eq 200) || ($res eq 403)) { push(@POSSIBLECGI,$possiblecgidir); $gotvalid++; } } if ($gotvalid eq 0) { nprint("+ No CGI Directories found (use '-C all' to force check all possible dirs)"); $VARIABLES{"\@CGIDIRS"} = ""; } elsif ($#CFGCGI eq $#POSSIBLECGI) { nprint("+ All CGI directories 'found', use '-C none' to test none"); $VARIABLES{"\@CGIDIRS"} = join(" ",@CFGCGI); } else { $VARIABLES{"\@CGIDIRS"} = join(" ",@POSSIBLECGI); } } # end !$CLI{forcecgi} nprint("- Checking for CGI in: $VARIABLES{\"\@CGIDIRS\"}","v"); return;}#######################################################################sub fetch{ if ($CLI{pause} > 0) { sleep $CLI{pause}; } LW2::http_close(\%request); # force-close any old connections $request{'whisker'}->{'uri'} = $CLI{root} . $_[0]; # prepend -root option value $request{'whisker'}->{'method'} = $_[1]; $request{'whisker'}->{'http_eol'}=$http_eol; delete $reque
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -