Changeset 388


Ignore:
Timestamp:
04/11/2010 08:24:23 PM (3 years ago)
Author:
deity
Message:

fetch is dead, long live nfetch

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/docs/CHANGES.txt

    r387 r388  
     12010-04-11 
     2        - Ticket 125: fetch is dead, long live nfetch 
     3        - Moved URI error handling and reporting result to nfetch, rather than being in nikto_tests (Ticket 139, partial) 
    142010-04-10 
    25        - Merged apacheusers and apache_enum_users together 
  • trunk/plugins/nikto_core.plugin

    r387 r388  
    13871387        my $olddebug   = $OUTPUT{'debug'}; 
    13881388        my $olderrors  = $OUTPUT{'errors'}; 
    1389         nprint("- Running $type for \"$plugin->{full_name}\" plugin", "v"); 
     1389        nprint("- Running $type for \"$plugin->{full_name}\" plugin", "v") 
     1390            unless ($type eq "prefetch" || $type eq "postfetch"); 
    13901391        if (defined $plugin->{'parameters'}->{'verbose'} 
    13911392            && $plugin->{'parameters'}->{'verbose'} == 1) { 
     
    19491950 
    19501951####################################################################### 
    1951 sub fetch { 
    1952     if ($CLI{'pause'} > 0) { sleep $CLI{'pause'}; } 
    1953     LW2::http_close(\%request);    # force-close any old connections 
    1954     $request{'whisker'}->{'uri'} = $_[0]; 
    1955     if (defined $CLI{'root'}) { 
    1956         $request{'whisker'}->{'uri'} = $CLI{'root'} . $_[0];    # prepend -root option value 
    1957     } 
    1958  
    1959     # Set testid in UA 
    1960     my $temp_ua = $request{'User-Agent'}; 
    1961     my $testid  = $_[3]; 
    1962     $request{'User-Agent'} =~ s/\@TESTID/$testid/g; 
    1963  
    1964     $request{'whisker'}->{'method'} = $_[1]; 
    1965     delete $request{'whisker'}->{'data'}; 
    1966     delete $request{'Content-Encoding'}; 
    1967     delete $request{'Content-Length'}; 
    1968     my $header_hash = $_[3]; 
    1969  
    1970     if (defined $_[2]) { 
    1971         my $r = $_[2]; 
    1972         $r =~ s/\\\"/\"/g; 
    1973         $request{'whisker'}->{'data'} = $r; 
    1974     } 
    1975  
    1976     # check for extra HTTP headers 
    1977     if (defined $_[3]) { 
    1978  
    1979         # loop through the hash ref passed and add each header to request 
    1980         while (my ($key, $value) = each(%$header_hash)) { 
    1981             $request{$key} = $value; 
    1982         } 
    1983     } 
    1984     unless ($_[4]) { LW2::http_fixup_request(\%request); } 
    1985  
    1986     # Cache 
    1987     if (   defined($CACHE{ $request{'whisker'}->{'uri'} }) 
    1988         && !defined($CLI{'nocache'}) 
    1989         && ($CACHE{ $request{'whisker'}->{'uri'} }{'method'} eq $request{'whisker'}->{'method'})) { 
    1990  
    1991         # Get from cache 
    1992         nprint("- Retrieving $request{'whisker'}->{'uri'} from cache.", "v"); 
    1993         $result{'whisker'}->{'code'} = $CACHE{ $request{'whisker'}->{'uri'} }{'res'}; 
    1994         $result{'whisker'}->{'data'} = $CACHE{ $request{'whisker'}->{'uri'} }{'content'}; 
    1995     } 
    1996     else { 
    1997         LW2::http_do_request_timeout(\%request, \%result); 
    1998         $NIKTO{'totalrequests'}++; 
    1999         unless (defined $CLI{'nocache'}) { 
    2000             $CACHE{ $request{'whisker'}->{'uri'} }{'method'}  = $request{'whisker'}->{'method'}; 
    2001             $CACHE{ $request{'whisker'}->{'uri'} }{'res'}     = $result{'whisker'}->{'code'}; 
    2002             $CACHE{ $request{'whisker'}->{'uri'} }{'content'} = $result{'whisker'}->{'data'}; 
    2003         } 
    2004         if ($OUTPUT{'debug'}) { 
    2005             dump_var("Request Hash", \%request); 
    2006             dump_var("Result Hash",  \%result); 
    2007         } 
    2008     } 
    2009  
    2010     if (   defined $CLI{'display'} 
    2011         && ($CLI{'display'} =~ /2/) 
    2012         && (defined($result{'whisker'}->{'cookies'}))) { 
    2013         foreach my $c (@{ $result{'whisker'}->{'cookies'} }) { 
    2014             nprint("+ $request{'whisker'}->{'uri'} sent cookie: $c"); 
    2015         } 
    2016     } 
    2017  
    2018     # Clean up extra headers 
    2019     if (defined $_[3]) { 
    2020         while (my ($key, $value) = each(%$header_hash)) { 
    2021             delete $request{$key}; 
    2022         } 
    2023     } 
    2024  
    2025     # content search 
    2026     content_search($result{'whisker'}->{'data'}, 
    2027                    $request{'whisker'}->{'uri'}, 
    2028                    $request{'whisker'}->{'method'}); 
    2029  
    2030     $request{'User-Agent'} = $temp_ua;    # reset UA 
    2031     return $result{'whisker'}->{'code'}, $result{'whisker'}->{'data'}; 
    2032 } 
    2033  
    2034 ####################################################################### 
    20351952sub setup_hash { 
    20361953    my ($reqhash, $mark, $testid) = @_; 
     
    21252042        } 
    21262043    } 
    2127  
    2128     if (   defined $CLI{'display'} 
     2044    nprint("- $result{'whisker'}{'code'} for $method:\t$uri", "v"); 
     2045 
     2046    # Check for errors to reduce false positives 
     2047    if (defined $result{'whisker'}->{'error'}) { 
     2048        $mark->{'total_errors'}++; 
     2049        nprint("+ ERROR: $uri returned an error: $result{'whisker'}{'error'}\n", "e"); 
     2050        next; 
     2051    } 
     2052     
     2053    if ( defined $CLI{'display'} 
    21292054        && ($CLI{'display'} =~ /2/) 
    21302055        && (defined($result{'whisker'}->{'cookies'}))) { 
  • trunk/plugins/nikto_tests.plugin

    r387 r388  
    4040 
    4141    # this is the actual the looped code for all the checks 
    42     foreach my $CHECKID (sort keys %TESTS) { 
    43         if ($CHECKID >= 500000) { next; }    # skip TESTS added manually during run (for reports) 
     42    foreach my $checkid (sort keys %TESTS) { 
     43        if ($checkid >= 500000) { next; }    # skip TESTS added manually during run (for reports) 
    4444                                             # replace variables in the uri 
    45         my @urilist = change_variables($TESTS{$CHECKID}{'uri'}); 
     45        my @urilist = change_variables($TESTS{$checkid}{'uri'}); 
    4646 
    4747        # Now repeat for each uri 
    4848        foreach my $uri (@urilist) { 
    49             (my $RES, $CONTENT) = 
    50               fetch($uri, $TESTS{$CHECKID}{'method'}, $TESTS{$CHECKID}{'data'}, $CHECKID); 
    51             nprint("- $RES for $TESTS{$CHECKID}{'method'}:\t$request{'whisker'}{'uri'}", "v"); 
    52  
    53             # Check for errors to reduce false positives 
    54             if (defined $result{'whisker'}->{'error'}) { 
    55  
    56                 # An error occured, show in verbose mode and skip 
    57                 # Try it again before we report it fully 
    58                 sleep(1); 
    59                 ($RES, $CONTENT) = 
    60                   fetch($uri, $TESTS{$CHECKID}{'method'}, $TESTS{$CHECKID}{'data'}, $CHECKID); 
    61                 nprint("- $RES for $TESTS{$CHECKID}{'method'}:\t$request{'whisker'}{'uri'}", "v"); 
    62  
    63                 if (defined $result{'whisker'}->{'error'}) { 
    64                     $mark->{'total_errors'}++; 
    65                     nprint("+ ERROR: $uri returned an error: $result{'whisker'}{'error'}\n", "e"); 
    66                     next; 
    67                 } 
    68             } 
    69  
    70             # do auth/redir first, independent of test pass/fail 
    71             if ($RES eq 401) { 
    72                 $result{'www-authenticate'} =~ /realm=\"(.+)\"/; 
    73                 my $R = $1; 
    74                 if ($R eq '') { $R = $result{'www-authenticate'} } 
    75                 do_auth($request, $result, $mark); 
    76                 nprint("+ $uri - Requires Authentication for realm '$R'") if $CLI{'display'} =~ /4/; 
    77                 $RES     = $result{'whisker'}->{'code'}; 
    78                 $CONTENT = $result{'whisker'}->{'data'}; 
    79             } 
    80             elsif ($RES eq 200) { 
    81                 nprint("+ $uri - 200/OK Response could be $TESTS{$CHECKID}{'message'}") 
     49            (my $res, $content, $error) = 
     50              nfetch($mark, $uri, $TESTS{$checkid}{'method'}, $TESTS{$checkid}{'data'}, "",  "", $checkid); 
     51 
     52            # auth is now done in nfetch 
     53            if ($result eq 200) { 
     54                nprint("+ $uri - 200/OK Response could be $TESTS{$checkid}{'message'}") 
    8255                  if $CLI{'display'} =~ /3/; 
    8356            } 
    84             elsif ($RES =~ /30([0-3]|7)/) { 
    85                 nprint(  "+ $uri - Redirects ($RES) to " 
     57            elsif ($result =~ /30([0-3]|7)/) { 
     58                nprint(  "+ $uri - Redirects ($result) to " 
    8659                       . $result{'location'} 
    87                        . " , $TESTS{$CHECKID}{'message'}") 
     60                       . " , $TESTS{$checkid}{'message'}") 
    8861                  if $CLI{'display'} =~ /1/; 
    8962            } 
     
    9467 
    9568            # how to check each conditional 
    96             if ($TESTS{$CHECKID}{'match_1'}     =~ /^[0-9]{3}$/) { $m1_method  = "code"; } 
    97             if ($TESTS{$CHECKID}{'match_1_or'}  =~ /^[0-9]{3}$/) { $m1o_method = "code"; } 
    98             if ($TESTS{$CHECKID}{'match_1_and'} =~ /^[0-9]{3}$/) { $m1a_method = "code"; } 
    99             if ($TESTS{$CHECKID}{'fail_1'}      =~ /^[0-9]{3}$/) { $f1_method  = "code"; } 
    100             if ($TESTS{$CHECKID}{'fail_2'}      =~ /^[0-9]{3}$/) { $f2_method  = "code"; } 
     69            if ($TESTS{$checkid}{'match_1'}     =~ /^[0-9]{3}$/) { $m1_method  = "code"; } 
     70            if ($TESTS{$checkid}{'match_1_or'}  =~ /^[0-9]{3}$/) { $m1o_method = "code"; } 
     71            if ($TESTS{$checkid}{'match_1_and'} =~ /^[0-9]{3}$/) { $m1a_method = "code"; } 
     72            if ($TESTS{$checkid}{'fail_1'}      =~ /^[0-9]{3}$/) { $f1_method  = "code"; } 
     73            if ($TESTS{$checkid}{'fail_2'}      =~ /^[0-9]{3}$/) { $f2_method  = "code"; } 
    10174 
    10275            # basic match for positive result 
    10376            if ($m1_method eq "content") { 
    104                 if ($CONTENT =~ /$TESTS{$CHECKID}{'match_1'}/) { 
     77                if ($content =~ /$TESTS{$checkid}{'match_1'}/) { 
    10578                    $positive = 1; 
    10679                } 
    10780            } 
    10881            else { 
    109                 if (($RES eq $TESTS{$CHECKID}{'match_1'}) || ($RES eq $FoF{'okay'}{'response'})) { 
     82                if (($result eq $TESTS{$checkid}{'match_1'}) || ($result eq $FoF{'okay'}{'response'})) { 
    11083                    $positive = 1; 
    11184                } 
     
    11386 
    11487            # no match, check optional match 
    115             if ((!$positive) && ($TESTS{$CHECKID}{'match_1_or'} ne "")) { 
     88            if ((!$positive) && ($TESTS{$checkid}{'match_1_or'} ne "")) { 
    11689                if ($m1o_method eq "content") { 
    117                     if ($CONTENT =~ /$TESTS{$CHECKID}{'match_1_or'}/) { 
     90                    if ($content =~ /$TESTS{$checkid}{'match_1_or'}/) { 
    11891                        $positive = 1; 
    11992                    } 
    12093                } 
    12194                else { 
    122                     if (   ($RES eq $TESTS{$CHECKID}{'match_1_or'}) 
    123                         || ($RES eq $FoF{'okay'}{'response'})) { 
     95                    if (   ($result eq $TESTS{$checkid}{'match_1_or'}) 
     96                        || ($result eq $FoF{'okay'}{'response'})) { 
    12497                        $positive = 1; 
    12598                    } 
     
    129102            # matched on something, check fails/ands 
    130103            if ($positive) { 
    131                 if ($TESTS{$CHECKID}{'fail_1'} ne "") { 
     104                if ($TESTS{$checkid}{'fail_1'} ne "") { 
    132105                    if ($f1_method eq "content") { 
    133                         if ($CONTENT =~ /$TESTS{$CHECKID}{'fail_1'}/) { next; } 
     106                        if ($content =~ /$TESTS{$checkid}{'fail_1'}/) { next; } 
    134107                    } 
    135108                    else { 
    136                         if ($RES eq $TESTS{$CHECKID}{'fail_1'}) { next; } 
    137                     } 
    138                 } 
    139                 if ($TESTS{$CHECKID}{'fail_2'} ne "") { 
     109                        if ($result eq $TESTS{$checkid}{'fail_1'}) { next; } 
     110                    } 
     111                } 
     112                if ($TESTS{$checkid}{'fail_2'} ne "") { 
    140113                    if ($f2_method eq "content") { 
    141                         if ($CONTENT =~ /$TESTS{$CHECKID}{'fail_2'}/) { next; } 
     114                        if ($content =~ /$TESTS{$checkid}{'fail_2'}/) { next; } 
    142115                    } 
    143116                    else { 
    144                         if ($RES eq $TESTS{$CHECKID}{'fail_2'}) { next; } 
    145                     } 
    146                 } 
    147                 if ($TESTS{$CHECKID}{'match_1_and'} ne "") { 
     117                        if ($result eq $TESTS{$checkid}{'fail_2'}) { next; } 
     118                    } 
     119                } 
     120                if ($TESTS{$checkid}{'match_1_and'} ne "") { 
    148121                    if ($m1a_method eq "content") { 
    149                         if ($CONTENT !~ /$TESTS{$CHECKID}{'match_1_and'}/) { next; } 
     122                        if ($content !~ /$TESTS{$checkid}{'match_1_and'}/) { next; } 
    150123                    } 
    151124                    else { 
    152                         if ($RES ne $TESTS{$CHECKID}{'match_1_and'}) { next; } 
     125                        if ($result ne $TESTS{$checkid}{'match_1_and'}) { next; } 
    153126                    } 
    154127                } 
     
    156129                # if it's an index.php, check for normal /index.php to see if it's a FP 
    157130                if ($uri =~ /^\/index.php\?/) { 
    158                     my $CONTENT = rm_active_content($CONTENT, $uri); 
    159                     if (LW2::md4($CONTENT) eq $FoF{'index.php'}{'match'}) { next; } 
     131                    my $content = rm_active_content($content, $uri); 
     132                    if (LW2::md4($content) eq $FoF{'index.php'}{'match'}) { next; } 
    160133                } 
    161134 
    162135                # lastly check for a false positive based on file extension or type 
    163136                if (($m1_method eq "code") || ($m1o_method eq "code")) { 
    164                     if (is_404($request{'whisker'}{'uri'}, $CONTENT, $RES)) { next; } 
    165                 } 
    166  
    167                 $TESTS{$CHECKID}{'osvdb'} =~ s/\s+/ OSVDB\-/g; 
     137                    if (is_404($request{'whisker'}{'uri'}, $content, $result)) { next; } 
     138                } 
     139 
     140                $TESTS{$checkid}{'osvdb'} =~ s/\s+/ OSVDB\-/g; 
    168141                add_vulnerability($mark, 
    169                                   "$request{'whisker'}{'uri'}: $TESTS{$CHECKID}{'message'}", 
    170                                   $CHECKID, 
    171                                   $TESTS{$CHECKID}{'osvdb'}, 
    172                                   $TESTS{$CHECKID}{'method'}, 
     142                                  "$request{'whisker'}{'uri'}: $TESTS{$checkid}{'message'}", 
     143                                  $checkid, 
     144                                  $TESTS{$checkid}{'osvdb'}, 
     145                                  $TESTS{$checkid}{'method'}, 
    173146                                  $uri 
    174147                                  ); 
Note: See TracChangeset for help on using the changeset viewer.