📄 nikto_core.plugin
字号:
LW::http_fixup_request(\%request); dump_request_hash(); LW::http_do_request(\%request,\%result); dump_result_hash(); if (exists($result{'set-cookie'})) { push(@COOKIES,"/--=--$result{'set-cookie'}"); } return $result{'whisker'}->{'http_resp'}, $result{'whisker'}->{'data'};}######################################################################## return $_[0] 'x' characters#######################################################################sub junk{ return "x" x $_[0];}######################################################################## load the scan database#######################################################################sub load_scan_items{ open(IN,"<$FILES{dbfile}") || die print "+ ERROR: Unable to open '$FILES{dbfile}' for read: $@\n"; @DBFILE=<IN>; close(IN); open(IN,"<$FILES{serverdbfile}") || die print "+ ERROR: Unable to open '$FILES{serverdbfile}' for read: $@\n"; @SERVERFILE=<IN>; close(IN); # load a user database if it exists... if (-e $FILES{userdbfile}) { open(IN,"<$FILES{userdbfile}") || die print "+ ERROR: Unable to open '$FILES{userdbfile}' for read: $@\n"; my @DBFILE_USER=<IN>; close(IN); # join them... foreach $line (@DBFILE_USER) { push(@DBFILE,$line); } } return;}######################################################################## get server categories#######################################################################sub set_server_cats{ # first figure out server type foreach $line (@SERVERFILE) { if ($line =~ /^\"/) { if ($line =~ /\#/) { $line=~s/\#.*$//; $line=~s/\s+$//; } chomp($line); @scat=parse_csv($line); nprint("servercat compare: '$TARGETS{$CURRENT_HOST_ID}{ports}{$CURRENT_PORT}{banner}' to '$scat[1]'","d"); if ($TARGETS{$CURRENT_HOST_ID}{ports}{$CURRENT_PORT}{banner} =~ /$scat[1]/i) { $TARGETS{$CURRENT_HOST_ID}{ports}{$CURRENT_PORT}{category}=$scat[0]; nprint("servercat match:$scat[0]","d"); last; } } } if ($TARGETS{$CURRENT_HOST_ID}{ports}{$CURRENT_PORT}{category} eq "") { $TARGETS{$CURRENT_HOST_ID}{ports}{$CURRENT_PORT}{category}="generic"; }return;}######################################################################## set up the scan database#######################################################################sub set_scan_items{ set_server_cats(); my $shname=$TARGETS{$CURRENT_HOST_ID}{hostname} || $TARGETS{$CURRENT_HOST_ID}{ip}; my ($line, $stype) = ""; my (@item, @scat, $FILES, $RESPS, $METHD, $INFOS, $DATAS) = (); $ITEMCOUNT=0; # now load checks foreach $line (@DBFILE) { if ($line =~ /^\"/) # check { chomp($line); @item=parse_csv($line); # if the right category or cat is generic... if (($TARGETS{$CURRENT_HOST_ID}{ports}{$CURRENT_PORT}{category} =~ /$item[0]/i) || ($item[0] =~ /generic/i) || ($TARGETS{$CURRENT_HOST_ID}{ports}{$CURRENT_PORT}{banner} eq "") || ($CLI{forcegen})) { # substitute for @IP, @HOSTNAME in check $line =~ s/\@IP/$TARGETS{$CURRENT_HOST_ID}{ip}/g; $line =~ s/\@HOSTNAME/$shname/g; for (my $i=1;$i<=$#item;$i++) { chomp($item[$i]); if ($i eq 3) { next; } # skip method if ($item[$i] =~ /(JUNK\([0-9]+\))/) # junk text { my $j= my $m=$1; $j=~ s/^JUNK\(//; $j=~ s/\)//; $j=junk($j); $m=~s/([^a-zA-Z0-9])/\\$1/g; $item[$i] =~ s/$m/$j/; } } if ($item[1] eq "") { $item[2]="/"; } if (($#item < 4) || ($#item > 6)) { nprint("Invalid check syntax:@item:","d"); } # Build the check items. First check for any @ values to replace # this nasty set of loops allows for multiple values per line if ($item[1] =~ /^\@/) # multiple checks in one { my @clones=(); my $todelete=""; push(@clones,$item[1]); foreach my $varname (keys %VARIABLES) { for (my $i=0;$i<=$#clones;$i++) { if ($clones[$i] =~ /$varname/) { my @values=split(/ /,$VARIABLES{$varname}); foreach my $val (@values) { my $temp=$clones[$i]; $temp =~ s/$varname/$val/g; push(@clones,$temp); $todelete=$i; } splice(@clones,$todelete,1); $i--; # step back in the @clones 'cause we deleted one. more work, but it guarantees it's complete } } } # now actually populate the checks for (my $i=0;$i<=$#clones;$i++) { $ITEMCOUNT++; $FILES{$ITEMCOUNT}="$CLI{root}$clones[$i]"; $RESPS{$ITEMCOUNT}=$item[2]; $METHD{$ITEMCOUNT}=$item[3]; $INFOS{$ITEMCOUNT}=$item[4]; $DATAS{$ITEMCOUNT}=$item[5]; } } else # normal, single check { $ITEMCOUNT++; $FILES{$ITEMCOUNT}="$CLI{root}$item[1]"; $RESPS{$ITEMCOUNT}=$item[2]; $METHD{$ITEMCOUNT}=$item[3]; $INFOS{$ITEMCOUNT}=$item[4]; $DATAS{$ITEMCOUNT}=$item[5]; } } } }nprint("- Server category identified as '$TARGETS{$CURRENT_HOST_ID}{ports}{$CURRENT_PORT}{category}', if this is not correct please use -g to force a generic scan.","v");nprint("- $ITEMCOUNT server checks loaded","v");if ($ITEMCOUNT eq 0) { nprint("+ Unable to load valid checks!"); exit; }if ($CLI{forcegen} eq 0) { nprint("+ Forcing full DB scan","v"); }return;}######################################################################## escape all non standard chars in a string (for regex's really)# char_escape 'string'#######################################################################sub char_escape{ my $text=$_[0]||return; $text =~ s/([^a-zA-Z0-9 ])/\\$1/g; return $text;}######################################################################## turn CSV data to an array# parse_csv 'string'#######################################################################sub parse_csv{ my $text = $_[0]; my @new = (); push(@new, $+) while $text =~ m{ "([^\"\\]*(?:\\.[^\"\\]*)*)",? | ([^,]+),? | , }gx; push(@new, undef) if substr($text, -1,1) eq ','; return @new;}######################################################################## print version info#######################################################################sub version{ my @FILES=dirlist($NIKTO{plugindir},"(^nikto|\.db\$)"); print "$DIV\n$NIKTO{name} Versions\n$DIV\n"; print "File Version Last Mod\n"; print "----------------------------- -------- ----------\n"; print "Nikto main $NIKTO{version}\n"; print "LibWhisker $LW::VERSION\n"; my $col1=35; my $col2=13; foreach my $FILE (@FILES) { open(FI,"<$NIKTO{plugindir}/$FILE") || die print "- ERROR: Unable to open '$NIKTO{plugindir}/$FILE': $!\n";;; my @F=<FI>; close(FI); my @VERS=grep(/^#VERSION/,@F); my @MODS=grep(/^#LASTMOD/,@F); chomp($VERS[0]); chomp($MODS[0]); $VERS[0] =~ s/^#VERSION,//; $MODS[0] =~ s/^#LASTMOD,//; my $ws1=($col1-length($FILE)); my $ws2=($col2-length($VERS[0])); print "$FILE", " " x $ws1 , "$VERS[0]", " " x $ws2, "$MODS[0]\n"; } print "$DIV\n"; exit;}######################################################################## send version update info to CIRT.net, if desired#######################################################################sub send_updates{ if ($CONFIG{UPDATES} !~ /yes|auto/i) { return; } my $have_updates=0; my ($updated_version, $answer, $RES); foreach my $ver (keys %UPDATES) { if ($UPDATES{$ver} eq 1) { if ($ver !~ /[0-9]/) { next; } # no version info...useless if ($ver eq "Win32") { next; } # also no use if ($ver eq "Linux-Mandrake") { next; } # just... usually garbage $have_updates=1; $updated_version .= "$ver "; } } if (!$have_updates) { return; } if ($updated_version eq "") { return; } # make sure the outdated.db isn't *too* old open(OD,"<$NIKTO{plugindir}/outdated.db") || die print "- ERROR: Unable to open '$NIKTO{plugindir}/outdated.db': $!\n";; @F=<OD>; close(OD); my @LASTUPDATED=grep(/^#LASTMOD/,@F); chomp($LASTUPDATED[0]); $LASTUPDATED[0]=~s/^.*,//; my @lu=split(/\./,$LASTUPDATED[0]); my $lm="$lu[2]$lu[0]"; my @NOW=localtime(time); $NOW[5]+=1900; $NOW[4]++; if ($NOW[4] < 10) { $NOW[4]="0$NOW[4]"; } my $now="$NOW[5]$NOW[4]"; if (($now - $lm) > 4) { return; } # DB is 4 months old... ignore the updates! $updated_version =~ s/\s+$//; $updated_version =~ s/^\s+//; if ($CONFIG{UPDATES} eq "auto") { $answer = "y"; } else { $answer=read_data("\n ***** Portions of the server's ident string ($updated_version) are not in the Nikto database or is newer than the known string. Would you like to submit this information (*no server specific data*) to CIRT.net for a Nikto update (or you may email to sullo\@cirt.net) (y/n)? ",""); } if ($answer !~ /y/i) { return; } LW::http_init_request(\%request); 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{'Host'}="www.cirt.net"; for (my $i=0;$i<=$#ARGV;$i++) { if (($ARGV[$i] eq "-u") || ($ARGV[$i] eq "-useproxy")) { $CLI{useproxy}=1; last; } } my $ip=gethostbyname($server); if ($ip ne "") { $request{'whisker'}->{'host'}= inet_ntoa($ip); } else { $request{'whisker'}->{'host'}=$server; } if (($CONFIG{PROXYHOST} ne "") && ($CLI{useproxy})) { $request{'whisker'}->{'proxy_host'}=$CONFIG{PROXYHOST}; $request{'whisker'}->{'proxy_port'}=$CONFIG{PROXYPORT}; } # send data LW::http_fixup_request(\%request); ($RES, $CONTENT) = fetch("/cgi-bin/versions?DATA=$updated_version","GET"); # if res is blank... maybe only proxy to get to net? if (($RES eq "") && ($CONFIG{PROXYHOST} ne "")) { $request{'whisker'}->{'proxy_host'}=$CONFIG{PROXYHOST}; $request{'whisker'}->{'proxy_port'}=$CONFIG{PROXYPORT}; ($RES, $CONTENT) = fetch("/cgi-bin/versions?DATA=$updated_version","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("/cgi-bin/versions?DATA=$updated_version","GET"); } if ($CONTENT !~ /SUCCESS/) { print "- ERROR ($RES, $CONTENT): Unable to send updated version string(s) to CIRT.net\n"; } else { print "- Sent updated version string(s) to CIRT.net\n"; }return;}######################################################################## print usage info#######################################################################sub usage{ nprint($NIKTO{options}); exit;}#######################################################################sub nikto_core { return; } # trap for this plugin being called to run#######################################################################1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -