📄 nikto_core.plugin
字号:
# run_plugins# load plugins & run them# this ugly, and potentially dangerous if untrusted plugins are present#################################################################################sub run_plugins{ open(ORDERFILE,"<$NIKTO{plugindir}/nikto_plugin_order.txt"); my @ORDER=<ORDERFILE>; close(ORDERFILE); foreach my $pluginf (@ORDER) { if ($pluginf =~ /^\#/) { next; } chomp($pluginf); $pluginf =~ s/\s+//; if ($pluginf eq "") { next; } require "$NIKTO{plugindir}/$pluginf\.plugin"; nprint("- Calling plugin:$pluginf\.plugin","d"); # just call it...hope it works...taint doesn't like this very much for obvious reasons &$pluginf; }return;}################################################################################## check_updates#################################################################################sub check_updates{ LW::http_init_request(\%request); my (%REMOTE, %LOCAL, @DBTOGET) = (); my ($pluginmsg, $remotemsg) = ""; my $code_updates=0; my $serverdir="/nikto/UPDATES/$NIKTO{version}"; my $server="www.cirt.net"; $request{'whisker'}->{'http_ver'}="1.1"; $request{'whisker'}->{'port'}=80; $request{'whisker'}->{'anti_ids'}=""; $request{'User-Agent'}="Nikto Update Agent"; $request{'whisker'}->{'host'}="www.cirt.net"; for (my $i=0;$i<=$#ARGV;$i++) { if (($ARGV[$i] eq "-u") || ($ARGV[$i] eq "-useproxy")) { $CLI{useproxy}=1; last; } } if (($CONFIG{PROXYHOST} ne "") && ($CLI{useproxy})) { $request{'whisker'}->{'proxy_host'}=$CONFIG{PROXYHOST}; $request{'whisker'}->{'proxy_port'}=$CONFIG{PROXYPORT}; } my $ip=gethostbyname($server); if ($ip ne "") { $request{'whisker'}->{'host'}= inet_ntoa($ip); } else { $request{'whisker'}->{'host'}=$server; } # retrieve versions file LW::http_fixup_request(\%request); (my $RES, $CONTENT) = fetch("$serverdir/versions.txt","GET"); if ($RES eq 407) # requires Auth { if ($CONFIG{PROXYUSER} eq "") { $CONFIG{PROXYUSER}=read_data("Proxy ID: ",""); $CONFIG{PROXYPASS}=read_data("Proxy Pass: ","noecho"); } LW::auth_set_header("proxy-basic",\%request,$CONFIG{PROXYUSER},$CONFIG{PROXYPASS}); # and try again LW::http_fixup_request(\%request); ($RES, $CONTENT) = fetch("$serverdir/versions.txt","GET"); } if ($RES ne 200) { print "+ ERROR ($RES): Unable to get $request{'whisker'}->{'host'}$serverdir/versions.txt\n"; exit; } # make hash for (split(/\n/,$CONTENT)) { my @l=parse_csv($_); if ($_ =~ /^msg/) { $remotemsg="$l[1]"; next; } $REMOTE{$l[0]}=$l[1]; } # get local versions of plugins/dbs my @FILES=dirlist($NIKTO{plugindir},"(^nikto|\.db\$)"); foreach my $file (@FILES) { my $v=""; open(LOCAL,"<$NIKTO{plugindir}/$file") || print "+ ERROR: Unable to open '$NIKTO{plugindir}/$file' for read: $@\n"; my @l=<LOCAL>; close(LOCAL); my @VERS=grep(/^#VERSION/,@l); chomp(@VERS[0]); $LOCAL{$file}=(parse_csv(@VERS[0]))[1]; } # check main nikto versions foreach my $remotefile (keys %REMOTE) { if ($remotefile eq "nikto") # main program version { if ($REMOTE{$remotefile} > $NIKTO{version}) { print "+ Nikto has been updated to $REMOTE{$remotefile}, local copy is $NIKTO{version}\n"; print "+ No update has taken place. Please upgrade Nikto by visiting http://$server/\n"; if ($remotemsg ne "") { print "+ $server message: $remotemsg\n"; } exit; } next; } if (($LOCAL{$remotefile} eq "") || ($REMOTE{$remotefile} > $LOCAL{$remotefile})) { push(@DBTOGET,$remotefile); if ($remotefile !~ /\.db$/) { $code_updates=1; } } elsif ($REMOTE{$remotefile} < $LOCAL{$remotefile}) # local is newer (!) { print "+ Local '$remotefile' (ver $LOCAL{$remotefile}) is NEWER than remote (ver $REMOTE{$remotefile}).\n"; } } # replace local files if updated foreach my $toget (@DBTOGET) { print "+ Retrieving '$toget'\n"; (my $RES, $CONTENT) = fetch("$serverdir/$toget","GET"); if ($RES ne 200) { print "+ ERROR: Unable to get $server$serverdir/$toget\n"; exit; } if ($CONTENT ne "") { open(OUT,">$NIKTO{plugindir}/$toget") || die print "+ 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 "+ 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;}################################################################################## auth_check# if the server requires authentication & we have it...#################################################################################sub auth_check{ my $REALM=$result{'www-authenticate'}; $REALM =~ s/^Basic //i; $REALM =~ s/realm=//i; if ($REALM eq "") { $REALM="unnamed"; } if (($result{'www-authenticate'} !~ /basic|ntlm/i) && ($result{'www-authenticate'} ne ""))# doh, not basic! { my $AUTHTYPE=$result{'www-authenticate'}; $AUTHTYPE =~ s/ .*$//; nprint("+ ERROR: Host uses '$AUTHTYPE'"); nprint("+ Continuing scan without authentication , but suppressing 401 messages."); $NIKTO{suppressauth}=1; }elsif ($NIKTO{hostid} eq "") { nprint("+ ERROR: No auth credentials for $REALM, please set."); nprint("+ Continuing scan without authentication, but suppressing 401 messages."); $NIKTO{suppressauth}=1; return; }else { nprint("- Attempting authorization to $REALM realm.","v"); # check for 'broken' web server, returns a blank www-auth header no matter what the id/pw sent my $tid=LW::utils_randstr(); LW::auth_set_header("basic",\%request,$tid,$tid,$NIKTO{hostdomain}); # set auth LW::http_fixup_request(\%request); LW::http_do_request(\%request,\%result); # test auth if ($result{'www-authenticate'} eq "") # broken { nprint("+ ERROR: Unable to verify authentication to $REALM works (server doesn't respond properly). Nikto is using it blindly."); } else # test { LW::auth_set_header("basic",\%request,$NIKTO{hostid},$NIKTO{hostpw},$NIKTO{hostdomain}); # set auth LW::http_fixup_request(\%request); LW::http_do_request(\%request,\%result); # test auth if ($result{'www-authenticate'} ne "") { nprint("+ ERROR: Unable to authenticate to $REALM"); nprint("+ Continuing scan without authentication, but suppressing 401 messages."); $NIKTO{suppressauth}=1; } 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 ($CONFIG{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); return $input; } else # non-POSIX { print $prompt; $input=<STDIN>; chomp($input); return $input; }return;}################################################################################## proxy_setuup# Setup the required proxy stuff#################################################################################sub proxy_setup{ if (!$CLI{useproxy}) { return; } # HTTP proxy $request{'whisker'}->{'proxy_host'}=$CONFIG{PROXYHOST}; $request{'whisker'}->{'proxy_port'}=$CONFIG{PROXYPORT}; # SOCKS return; }################################################################################## proxy_check# test whether proxy requires authentication, and if we can use it#################################################################################sub proxy_check{ $request{'whisker'}->{'method'}="HEAD"; $request{'whisker'}->{'uri'}="/"; if ($request{'whisker'}->{'proxy_host'} ne "") # proxy is set up { LW::http_fixup_request(\%request); LW::http_do_request(\%request,\%result); if ($result{'whisker'}{'http_resp'} eq "407") # proxy requires auth { # have id/pw? if ($CONFIG{PROXYUSER} eq "") { $CONFIG{PROXYUSER}=read_data("Proxy ID: ",""); $CONFIG{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... LW::auth_set_header("proxy-basic",\%request,$CONFIG{PROXYUSER},$CONFIG{PROXYPASS}); # set auth LW::http_fixup_request(\%request); LW::http_do_request(\%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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -