source: trunk/plugins/nikto_auth.plugin @ 425

Revision 425, 6.4 KB checked in by deity, 3 years ago (diff)

Fixes to parameters and new parameter for test to report after a number of tests

  • Property svn:executable set to *
Line 
1#VERSION,1.01
2# $Id$
3###############################################################################
4#  Copyright (C) 2004 CIRT, Inc.
5#
6#  This program is free software; you can redistribute it and/or
7#  modify it under the terms of the GNU General Public License
8#  as published by the Free Software Foundation; version 2
9#  of the License only.
10#
11#  This program is distributed in the hope that it will be useful,
12#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14#  GNU General Public License for more details.
15#
16#  You should have received a copy of the GNU General Public License
17#  along with this program; if not, write to the Free Software
18#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19###############################################################################
20# PURPOSE:
21# Search content for known bad strings
22###############################################################################
23use vars /$REALMS %REALMSMATCHED/;
24
25sub nikto_auth_init {
26    my $id = { name             => 'auth',
27               full_name        => 'Guess authentication',
28               author           => 'Sullo/Deity',
29               description      => 'Attempt to guess authentication realms',
30               recon_method     => \&nikto_auth_load,
31               recon_weight     => 1,
32               postfetch_cond   => '$result->{whisker}->{code} eq 401',
33               postfetch_method => \&nikto_auth,
34               postfetch_weight => 19,
35               prefetch_method  => \&nikto_auth_pre,
36               prefetch_weight  => 19,
37               copyright        => "2010 CIRT Inc"
38               };
39
40    return $id;
41}
42
43sub nikto_auth_load {
44    # Load up the database as soon as we can
45   
46    $REALMS=init_db("db_realms");
47    %REALMSMATCHED = ();
48}
49
50sub nikto_auth_pre {
51    my ($mark, $parameters, $request, $result) = @_;
52    # If we know the realm then don't bother guessing it
53    # See whether we've already guessed it
54   
55    my ($uridir) = $request->{'whisker'}->{'uri'};
56    $uridir =~ s#/[^/]*$#/#g;
57
58    if (exists $REALMSMATCHED{$mark->{'hostname'}}{$uridir}) {
59        # Just set up the auth and return the valid result
60        LW2::auth_set($REALMSMATCHED{$mark->{'hostname'}}{$uridir}{'authtype'}, $request, $REALMSMATCHED{$mark->{'hostname'}}{$uridir}{'id'}, $REALMSMATCHED{$mark->{'hostname'}}{$uridir}{'password'});
61        # Patch to fix short reads
62        $request->{'whisker'}->{'allow_short_reads'} = 1;
63        LW2::http_fixup_request($request);
64    }
65    return $request, $result;
66}
67
68sub nikto_auth {
69    my ($mark, $parameters, $request, $result) = @_;
70    my ($authtype)  = 'basic';
71    my ($body)      = $result->{'whisker'}->{'data'};
72    my ($uri)       = $result->{'whisker'}->{'uri'};
73    my ($method)    = $result->{'whisker'}->{'method'} || "GET";
74    my ($realm, $save_auth);
75
76    unless (defined $result->{'www-authenticate'}) {
77        nprint("+ ERROR: No authentication header defined: $uri");
78        return $request, $result;
79    }
80   
81    # Save to revert
82    $save_auth = $result{'www-authenticate'};
83   
84    # Split up www-authenticate to realm and method
85    my @authenticate = split(/ /, $result->{'www-authenticate'});
86    if ($#authenticate == 0) {    # Only one parameter: realm
87        $realm = $authenticate[0];
88        if ($realm =~ /^ntlm/i) {
89            $realm    = "";
90            $authtype = $authenticate[0];
91        }
92    }
93    else {
94        $authtype = $authenticate[0];
95        $realm    = $authenticate[1];
96        $realm    =~ s/^realm=//;
97    }
98   
99    nprint("+ $uri - Requires Authentication for realm '$realm'") if $CLI{'display'} =~ /4/;
100
101    # Now we have this we can try guessing the password
102    foreach my $entry (@{$REALMS}) {
103        unless ($realm =~ /$entry->{'realm'}/i || $entry->{realm} eq '@ANY') { next; }
104       
105        if ($result->{'www-authenticate'} =~ /^ntlm/i) {
106            $authtype='ntlm';
107        }       
108        # Set up LW hash
109        LW2::auth_set($authtype, $request, $entry->{'id'}, $entry->{'password'});
110        # Patch to fix short reads
111                $request->{'whisker'}->{'allow_short_reads'} = 1;
112        LW2::http_fixup_request($request);     
113        # pause if needed
114        if ($CLI{'pause'} > 0) { sleep $CLI{'pause'}; }
115
116        LW2::http_do_request_timeout($request, $result);    # test auth
117        $NIKTO{'totalrequests'}++;
118        dump_var("Auth Request",  $request);
119        dump_var("Auth Response", $result);
120       
121        if ($result{'www-authenticate'} =~ /^ntlm/i) {
122            # Deal with ntlm
123            my @ntlm_x = split(/ /, $result{'www-authenticate'});
124            if ($#ntlm_x == 1) {
125                LW2::http_do_request_timeout(\%request, \%result);
126                $NIKTO{'totalrequests'}++;
127            }
128        }
129        my $uridir = $request->{'whisker'}->{'uri'};
130        $uridir =~ s#/[^/]*$#/#g;
131       
132        if ($result->{'www-authenticate'} eq ''
133            && !defined $result->{'whisker'}->{'error'}) {
134           
135            my $message="Default account found for '$realm' at $uridir ($request->{'whisker'}->{'uri'}) (ID '$entry->{'id'}', PW '$entry->{'password'}'). $entry->{message}";
136            if ($entry->{'id'} eq '' && $entry->{'password'} eq '') {
137                $message="Blank credentials found at $uridir ($request{whisker}->{uri}), $entry->{'realm'}: $entry->{'msg'}"
138            }
139            unless ( $entry->{'checked'} == 1) {
140                add_vulnerability(
141                    $mark,
142                    $message,
143                    $entry->{tid},
144                    0,
145                    "GET",
146                    $uridir,
147                    $result
148                    );
149                $entry->{checked} = 1;
150            }
151
152            # Finally repeat the check
153            LW2::http_do_request_timeout($request, $result);    # test auth
154            $NIKTO{'totalrequests'}++;
155           
156            # Set up so we don't have to repeat in future
157            # / isn't a valid entry in a hash  - more stupid perl
158
159            $REALMSMATCHED{$mark->{hostname}}{$uridir}{'id'}=$entry->{'id'};
160            $REALMSMATCHED{$mark->{hostname}}{$uridir}{'password'}=$entry->{'password'};
161            $REALMSMATCHED{$mark->{hostname}}{$uridir}{'authtype'}=$authtype;
162
163            # and leave
164            last;
165        }
166        else {
167            $result->{'www-authenticate'} = $save_auth;
168        }
169    }
170    LW2::auth_unset(\%request);
171
172    return $request, $result;
173}
174
1751;
Note: See TracBrowser for help on using the repository browser.