Changeset 387
- Timestamp:
- 04/10/2010 02:26:45 PM (3 years ago)
- Location:
- trunk
- Files:
-
- 1 deleted
- 4 edited
-
docs/CHANGES.txt (modified) (1 diff)
-
plugins/nikto_apacheusers.plugin (modified) (3 diffs)
-
plugins/nikto_core.plugin (modified) (1 diff)
-
plugins/nikto_tests.plugin (modified) (2 diffs)
-
plugins/nikto_user_enum_apache.plugin (deleted)
Legend:
- Unmodified
- Added
- Removed
-
trunk/docs/CHANGES.txt
r386 r387 1 2010-04-10 2 - Merged apacheusers and apache_enum_users together 3 - Add facillity for a plugin to inform which options it can take 1 4 2010-04-09 2 5 - Ticket 137: Added -ask to override nikto.conf's UPDATES value (same options) -
trunk/plugins/nikto_apacheusers.plugin
r344 r387 21 21 # Apache user enumeration 22 22 ############################################################################### 23 23 24 sub nikto_apacheusers_init { 24 25 my $id = { 25 26 name => "apacheusers", 26 27 full_name => "Apache Users", 27 author => " Sullo",28 author => "Javier Fernandez-Sanguinoi Pena", 28 29 description => "Checks whether we can enumerate usernames directly from the web server", 29 30 scan_method => \&nikto_apacheusers, 30 copyright => "2008 CIRT Inc." 31 copyright => "2008 CIRT Inc.", 32 options => { 33 enumerate => "Flag to indicate whether to attempt to enumerate users", 34 dictionary => "Filename for a dictionary file of users", 35 size => "Maximum size of username if bruteforcing" 36 } 31 37 }; 32 38 return $id; … … 34 40 35 41 sub nikto_apacheusers { 36 my ($mark) = @_; 37 (my $RES, $CONTENT) = nfetch($mark, "/~root", "GET", "", "", "", "apacheusers: known user"); 38 39 $CONTENT = char_escape($CONTENT); 40 if ($CONTENT =~ /forbidden/i) # good on "root" 42 my ($mark, $parameters) = @_; 43 my $apacheusers=0; 44 45 # First ensure that the server is vulnerable 46 (my $result, $content) = nfetch($mark, "/~root", "GET", "", "", "", "apacheusers: known user"); 47 48 $content = char_escape($content); 49 if ($content =~ /forbidden/i) # good on "root" 41 50 { 42 (my $ RES, $CONTENT) = nfetch($mark, "/~" . LW2::utils_randstr(8),43 "GET", "", "", "", "apacheusers: invalid user");44 45 $ CONTENT = char_escape($CONTENT);46 if ($ CONTENT!~ /forbidden/i) # Good, it gave an error instead of forbidden51 (my $result, $content) = nfetch($mark, "/~" . LW2::utils_randstr(8), 52 "GET", "", "", "", "apacheusers: invalid user"); 53 54 $content = char_escape($content); 55 if ($content !~ /forbidden/i) # Good, it gave an error instead of forbidden 47 56 { 48 57 add_vulnerability( … … 55 64 ); 56 65 } 57 } 66 $apacheusers=1; 67 } 68 69 # If we can't enumerate users then return 70 return unless ($apacheusers == 1); 71 # If we haven't been asked to enumerate users then return 72 return unless (defined $parameters->{'enumerate'} && 73 $parameters->{'enumerate'} == 1); 74 75 # Now we can attempt to enumerate the users 76 my ($url, $dictfile, $size); 77 my @cgiwraps; 78 my @cfgcgi = split(/ /, $VARIABLES{"\@CGIDIRS"}); 79 80 if (defined $parameters->{'dictionary'}) { 81 $dictfile = $parameters->{'dictionary'}; 82 } 83 if (defined $parameters->{'size'}) { 84 $size = $parameters->{'size'}; 85 } 86 87 # Set the URL according to the parameters 88 if (defined $parameters->{'cgiwrap'}) { 89 90 # Check for existence of cgiwrap 91 foreach my $cgidir (@CFGCGI) { 92 my $curl = "$cgidir" . "cgiwrap"; 93 (my $result, $content) = 94 nfetch($mark, $curl, "GET", "", "", "", "user_enum_apache: cgiwrap"); 95 if ($content =~ /check your URL/i) { 96 push(@cgiwraps, "$curl"); 97 } 98 } 99 100 foreach my $cgiwrap (@cgiwraps) { 101 $url = "$cgiwrap/~"; 102 103 # First check whether we use a dictionary attack of brute force it 104 if (defined $dictfile) { 105 106 # We have options - assume it is a dictionary attack 107 nikto_user_enum_apache_dictionary($url, $mark, $dictfile); 108 } 109 else { 110 nikto_user_enum_apache_brute($url, $mark, $size); 111 } 112 } 113 } 114 else { 115 # Assume we're using ~ if not told to use cgiwrap 116 $url = "/~"; 117 118 # First check whether we use a dictionary attack of brute force it 119 if (defined $dictfile) { 120 121 # We have options - assume it is a dictionary attack 122 nikto_user_enum_apache_dictionary($url, $mark, $dictfile); 123 } 124 else { 125 nikto_user_enum_apache_brute($url, $mark, $size); 126 } 127 } 128 } 129 130 sub nikto_user_enum_apache_brute { 131 132 # Note1: This script only generates names with letters A-Z (no numbers) 133 # 134 # Note2: this script will generate SUM(26^n)(n=$min to $max) 135 # it's probably faster to write this to a file than to generate it 136 # on the fly BTW. 137 # 138 # Of course, it could be optimized to skip some "strange" 139 # combinations of usernames, but hey, then it wouldn't 140 # be 'brute force' would it? (jfs) 141 142 my ($url, $mark, $size) = @_; 143 $size = 5 if ($size eq ""); 144 nprint("- Enumerating Apache users (1 to $size characters).", "v"); 145 146 my $text = "a"; 147 my $ctr = 0; 148 my $message = "Valid users found via Apache enumeration: "; 149 my ($result, $content); 150 my @foundusers = (); 151 while (length($text) <= $size) { 152 if (($ctr % 500) eq 0) { nprint("- User enumeration guess $ctr ($text)", "v"); } 153 ($result, $content) = 154 nfetch($mark, $url . $text, "HEAD", "", "", "", "user_enum_apache: enumeration"); 155 my $user = nikto_user_enum_apache_check($result, $text); 156 if (defined $user && $user ne "") { 157 push(@foundusers, $user); 158 } 159 $text++; 160 $ctr++; 161 } 162 if (scalar(@foundusers)) { 163 add_vulnerability($mark, $message . join(', ', @foundusers), 999997, "637", "HEAD", "/"); 164 } 165 166 } 167 168 sub nikto_user_enum_apache_dictionary { 169 my ($url, $mark, $filename) = @_; 170 my $message = "Valid users found via Apache enumeration: "; 171 my @foundusers = (); 172 my ($result, $content); 173 my $ctr = 0; 174 175 nprint("- Enumerating Apache users (using dictionary $filename).", "v"); 176 unless (open(IN, "<$filename")) { 177 nprint("+ ERROR: Unable to open dictionary file $filename: $!."); 178 } 179 180 # Now attempt on each entry 181 while (<IN>) { 182 chomp; 183 s/\#.*$//; 184 185 # remove preceding ~ just in case 186 s/^~//; 187 if ($_ eq "") { next } 188 if (($ctr % 500) == 0) { nprint("- User enumeration guess $ctr ($_)", "v"); } 189 ($result, $content) = 190 nfetch($mark, $url . $_, "HEAD", "", "", "", "user_enum_apache: dictionary"); 191 my $user = nikto_user_enum_apache_check($result, $_); 192 if ($user) { 193 push(@foundusers, $user); 194 } 195 $ctr++; 196 } 197 close(IN); 198 if (scalar(@foundusers)) { 199 add_vulnerability($mark, $message . join(', ', @foundusers), 999997, "637", "HEAD", "/"); 200 } 201 } 202 203 sub nikto_user_enum_apache_check { 204 (my $code, $user) = @_; 205 my $result = ""; 206 207 foreach my $found (split(/ /, $VARIABLES{"\@HTTPFOUND"})) { 208 if ($code eq $found) { 209 $result = $user; 210 last; 211 } 212 } 213 214 return $result; 58 215 } 59 216 60 217 1; 218 -
trunk/plugins/nikto_core.plugin
r385 r387 2579 2579 nprint(" $plugin->{'full_name'} - $plugin->{'description'}"); 2580 2580 nprint(" Written by $plugin->{'author'}, Copyright (C) $plugin->{'copyright'}"); 2581 if (defined $plugin->{'options'}) { 2582 nprint(" Options:"); 2583 while (my ($option, $description) = each(%{$plugin->{'options'}})) { 2584 nprint(" $option: $description"); 2585 } 2586 } 2581 2587 nprint("\n"); 2582 2588 } -
trunk/plugins/nikto_tests.plugin
r361 r387 22 22 ############################################################################### 23 23 sub nikto_tests_init { 24 my $id = { name => " Tests",24 my $id = { name => "tests", 25 25 full_name => "Nikto Tests", 26 26 author => "Sullo, Deity", … … 29 29 scan_method => \&nikto_tests, 30 30 scan_weight => 99, 31 options => { passfiles => "Flag to indicate whether to check for common password files", 32 all => "Flag to indicate whether to check all files with all directories" 33 } 31 34 }; 32 35 return $id;
Note: See TracChangeset
for help on using the changeset viewer.