Using the Nikto Web Application Vulnerability Scanner
Nikto is an extremely popular web application vulnerability scanner. Web application vulnerability scanners are designed to examine a web server to find security issues. Identifying security problems proactively, and fixing them, is an important step towards ensuring the security of your web servers. Nikto checks for a number of dangerous conditions and vulnerable software. Running Nikto on a regular basis will ensure that you identify common problems in your web server or web applications. Because most web servers host a number of web applications, with new software deployed over time, it is a good idea to run a scanner like Nikto against your servers on a routine basis.
Nikto is completely open source and is written in Perl. Nikto is a quite venerable (it was first released in 2001) part of many application security testers' toolkit for several reasons. In addition to being written in Perl, which makes it highly portable, Nikto is a non-invasive scanner. Running a Nikto scan won't exploit any vulnerabilities that are identified and therefor is safe to run against production servers. Because Nikto is written in Perl it can run anywhere that Perl with run, from Windows to Mac OS X to Linux.
Nikto runs at the command line, without any graphical user interface (GUI). While this might be considered a disadvantage, Nikto's use of the command line interface (CLI) to it is ideal for running the tool remotely over SSH connections. Nikto's architecture also means that you don't need GUI access to a system in order to install and run Nikto. The CLI also allows Nikto to easily interface with shell scripts and other tools. Nikto makes liberal use of files for configuration and direction as well, which also eases integration with other tools. For instance, you could schedule a scan via a shell script, gather a list of targets by querying a database and writing the results to a file, then have Nikto scan the targets specified in the file on a routine basis and report the results via e-mail.
How Nikto Works
Nikto operates by doing signature matching to known vulnerable web services, including dynamic web applications, CGI scripts, and web server configurations. Nikto does this by making requests to the web server and evaluating responses. Nikto includes a number of options that allow requests to include data such as form posts or header variables and does pattern matching on the returned responses.
Nikto uses a database of URL's for its scan requests. Nikto queries this database and makes calls to resources that indicate the presence of web application or server configurations. This detection technique is quite reliable, but is far from stealthy. Notably, this discovery technique results in an extremely large number of 404 responses (404 is the HTTP response code for "requested resource not found"). Additionally, all though this can be modified, the User Agent string sent in each request clearly identifies Nikto as the source of the requests.
In addition to URL discovery Nikto will probe web servers for configuration problems. Things like directory listings, debugging options that are enabled, and other issues are quickly identified by Nikto. Nikto will even probe HTTP and HTTPS versions of sites and can be configured to scan non-standard ports (such as port 8080 where many Java web servers listen by default).
Nikto is also capable of sending data along with requests to servers (such as URL data, known as GET variables, or form data, known as POST data). Nikto examines the full response from servers as well. This allows Nikto to perform testing for vulnerabilities such as cross site scripting (XSS) or even SQL injection.
Nikto will also search for insecure files as well as default files. This can reveal problems with web applications such as forgotten backups, left over installation files, and other artifacts that could jeopardize the security of a server. Like the detection of known vulnerable, or outdated, web applications this process is passive and won't cause any harm to servers.
Installing Nikto - Perl
The first step to installing Nikto is to ensure that you have a working version of Perl. Perl is a scripting language, which means programs are stored as plain text and then run through an interpreter at execution time. The Perl interpreter consumes plain text Perl programs and compiles a machine readable binary which is then run by the operating system. There are a number of advantages and disadvantages to this approach. Portability is one big advantage. Perl source code can run on any machine with a Perl interpreter (sort of like how Java can run on any machine with Java installed). Because Perl is compiled every time it is run it is also very easy to change programs. Perl's plain text format makes it ideal for open source projects because it is so easy to open and read the source code. The one major disadvantage to this approach is that it is somewhat slower than pre-compiled software.
Installing Nikto - Windows
On Windows machines this can be little more troublesome than other operating systems. Perl.org, the official site for Perl recommends two distributions of Perl for Windows: Strawberry Perl and ActiveState Perl. ActiveState has a longer history of supporting Perl on Windows, and offers commercial support, but both should be sufficient.
Fig 1: Perl.org Download Site
For the purposes of this article I will demonstrate Nikto on Windows XP using ActiveState, however the process is nearly identical for all versions of Windows. To begin Be sure to select the version of Perl that fits your architecture (32 (x86) or 64 bit).
Fig 2: ActiveState.com Perl Download Site
The download from ActiveState consists of a Microsoft installer (.msi) package that you can run directly from the download.
Fig 3: ActiveState's MSI download of Perl
Running the MSI will prompt you to answer a few questions about the installation. Using the defaults for answers is fine. You may wish to consider omitting the installation of Examples if you have limited space, however.
Fig 4: ActiveState Installer
Once installed you can check to make sure Perl is working properly by invoking the Perl interpreter at the command line. To do this open a command prompt (Start -> All Programs -> Accessories -> Command Prompt) and typing:
The '-v' flag causes the interpreter to display version information. Assuming the interpreter prints out version information then Perl is installed and you can proceed to install Nikto's dependencies.
Fig 5: Perl version information in Windows command prompt
Installing Nikto - Windows Dependencies
In order for Nikto to function properly you first need to install Secure Socket Layer (SSL) extensions to Perl. This is required in order to run Nikto over HTTPS, which uses SSL. ActiveState includes a graphical package manager that can be used to install the necessary libraries. You can find the Perl Package Manager under Start -> All Programs -> ActivePerl -> Perl Package Manager. Once you open this program you'll notice the search box in the top center. Type 'ssl' into this search box and hit enter. You should see the Net-SSLeay package. Check the 'Installed' column of the display to ensure the package is installed.
Fig 6: ActiveState Perl Package Manager showing the Net-SSLeay package
The Nikto distribution can be downloaded in two compressed formats. Bzip2 and Gz are the available options. Neither is standard on Windows so you will need to install a third party unzipping program, like 7-zip (http://www.7-zip.org/download.html).
Download and Install - Windows
Download the Nikto source code from http://www.cirt.net/nikto2. The download link is the first line of text under the tabs and is easy to miss. Click on the 'gz' link to download the gzip format source code.
Fig 7: Cirt.net Nikto download site
Save the source code file on your machine. The best place to do this is under C:Program Files so you will be able to find it easily. Next, open up a file browser (click on My Computer or the like) and navigate to the C:Program Files directory. You'll see the downloaded Nikto source, but more than likely Windows doesn't have the '.tar.gz' file extension associated with any programs. Right click on the source and select '7-zip' from the options menu, then 'Extract Here' to extract the program.
Fig 8: Extracting the Nikto source
This will unzip the file, but it is still in a .tar, or Tape ARchive format. Repeat the process of right clicking, selecting '7-zip' and choosing 'Extract Here' to expose the source directory.
Now that the source code is uncompressed you can begin using Nikto. Test to ensure that Nikto is running completely by navigating to the source code directory in a command prompt and typing the command 'nikto.pl -Version' and ensuring that the version output displays.
Fig 9: Nikto on Windows displaying version information
Installing Nikto - Linux
Installing Nikto on Linux is an extremely straightforward process. Ensure that Perl and OpenSSL are installed using the package management system on your distribution. On a CentOS, Red Hat, or Fedora system simply use:
$ sudo yum install -y perl perl-Net-SSLeay
once installed you can download the Nikto source using:
$ wget http://www.cirt.net/nikto/nikto-2.1.5.tar.gz; tar -xvzf nikto-2.1.5.tar.gz
Then you should test to ensure Nikto is installed properly using:
$ perl nikto.pl -Version
Nikto is fairly straightforward tool to use. Extensive documentation is available at http://cirt.net/nikto2-docs/. The first thing to do after installing Nikto is to update the database of definitions. This can be done using the command:
perl nikto.pl -update
The simplest way to start up Nikto is to point it at a specific IP address. For instance, to test the sites at 192.168.0.110 simply use:
perl nikto.pl -h 192.168.0.110
This will produce fairly verbose output that may be somewhat confusing at first. Take the time to read through the output to understand what each advisory means. Many of the alerts in Nikto will refer to OSVDB numbers. These are Open Source Vulnerability Database (http://osvdb.org/) designations. You can search on OSVDB for further information about any vulnerabilities identified.
Fig 10: Nikto running on Windows
The default output becomes unwieldy, however, as soon as you begin testing more than a single site. In order to make output more manageable it is worthwhile to explore Nikto's various reporting formats. One helpful format for parsing is the XML output format. To specify that Nikto write it's results to an XLM output file simply use:
perl nikto.pl -h 192.168.0.110 -output results.xml
Tests and Creating Custom Tests
Nikto tests are run against URL's defined in the Nikto databases. These databases are actually nothing more than comma separated value (CSV) lists in the various files found under the Nikto install directory in the databases directory. The files are properly formatted Perl files that are included dynamically by Nikto at run time. The dictionary definitions consist of OSVDB id number (if any), a server string, a URL corresponding with the vulnerability, the method to fetch the URL (GET or POST), pattern matching details, a summary of the rule and any additional HTTP data or header to be sent during the test (such as cookie values or form post data). Understanding this simple format makes it quite easy to extend rules, customize them, or write new rules for emerging vulnerabilities.
Writing a custom test should begin with choosing a private OSVDB ID and a test id in the reserved range from 400,000 to 499,999. Doing so will prevent collisions with updates that may be applied at a later date. If developing a test that you believe will be of wider use to the Nikto community you are encouraged to send them to email@example.com.
Recently a vulnerability was released (http://www.madirish.net/543) concerning the Hotblocks module for the Drupal content management system. Writing a test to determine if a server was running the vulnerable version of Hotblocks is quite easy. To test for the vulnerability we need to call the URL:
Which is the plain text file in the module that defines the version of the module. If the server responds with a page we can try to match the string:
version = "6.x-1.7"
which would indicate a vulnerable version. To do this we would simply append the following line to the bottom of db_tests file in the Nikto databases directory:
"400000","84750","4","/sites/all/modules/hotblocks/hotblocks.info","GET","version = "6.x-1.7","","","","","Drupal Hotblocks vulnerable to XSS","",""
The first field is the rule id, which we set to 400,000 to indicate it is a custom rule. The second field is the OSVDB ID number, which corresponds to the OSVDB entry for this vulnerability (http://osvdb.org/show/osvdb/84750). We could use 0 for this number if there were no entry. The next field refers to the tuning option. In our case we choose 4, which corresponds to injection flaws. The next field is the URL that we wish to test. The following field is the HTTP method (GET or POST). The next field is a string to match in the result that will indicate a positive test. The next four fields are further tests to match or not match. The next field is a summary and the final two fields are any HTTP data that should be sent for POST tests and headers to be sent. You can find detailed documentation on writing custom rules at http://cirt.net/nikto2-docs/expanding.html.
Running the rule against a vulnerable server does indeed report that the vulnerability exists:
Fig 11: Nikto custom rule identifying a vulnerability
Casting a Broader Net
Web application infrastructure is often complex and inscrutable. Web servers can be configured to answer to different domain names and a single open web port (such as 80,443, or 8080) could indicate a host of applications running on a server. Scanning by IP address is of limited value. In order to ensure that the broadest surface of a server is tested be sure to first determine all the domain names that resolve to a server in addition to the IP address. The '-h' or '-host' flag can specify an IP address, a hostname, or a test file full of host names and IP addresses. Determining all of the host names that resolve to an IP address can be tricky, and may involve other tools.
In addition to web servers configured to serve various virtual hosts for separate domain names, a single domain name or IP address may support any number of web applications under various directories. For instance, a host 192.168.0.10 might have a WordPress instance installed at 192.168.0.10/blog and a webmail application installed at 192.168.0.10/mail. Nikto tests for vulnerable applications assuming they are installed at the document root of a web server. By way of example, if the Drupal instance tested above was installed at http://192.168.0.10/drupal then the custom module we wrote would not find it (since it would search for http://192.168.0.10/sites/all/modules... instead of http://192.168.0.10/drupal/sites/all/modules...). Because combining all manner of potential prefix directories with all the tests in Nikto would be excessive a different approach must be utilized.
Nikto includes a number of plugins by default. You can view these using the command:
perl nikto.pl -list-plugins
There is a dictionary plugin that will search for directories based on a user supplied file. If we create a file with the following entries:
admin blog drupal mail webmail
and save it as 'rootdirs.txt' we can scan for these directories using the dictionary plugin and the following command:
perl nikto.pl -h 192.168.0.109 -Plugins "dictionary(dictionary:rootdirs.txt)"
This will show any of the directories identified from our rootdirs.txt file. In the case that Nikto identifies Drupal you must then re-run Nikto against that specific base directory using the command:
perl nikto.pl -h http://192.168.0.109/drupal
In this manner the vulnerable Hotblocks module can be discovered in Drupal even though it is installed in a sub-directory. Nikto has a number of plugins like the dictionary plugin to perform a host of useful operations. It is worth perusing the -list-plugins output even if you don't initially plan to use any of the extended plugins.
If you experience trouble using one of the commands in Nikto, setting the display to verbose can help. Use the command:
perl nikto.pl -display V
to enable this output option. Enabling verbose output could help you spot an issue with the command you're attempting, such as a missing optional argument or the like.
Nikto offers a number of options for assistance. Simply issuing the Nikto command with the '-Help' flag will show you a short list of command line help. The aforementioned Nikto documentation site is also extremely useful. The Nikto distribution also includes documentation in the 'docs' directory under the install directory. This directory contains the full manual in HTML format so you can peruse it even if you don't have access to the Nikto website. Additionally Nikto maintains a mailing list with instructions for subscription at http://www.cirt.net/nikto-discuss. Generally the mailing list is low traffic, but an excellent source for answers from Nikto experts.
Nikto is an extremely lightweight, and versatile tool. Because of the fact that Nikto is written in Perl it can be run on almost any host operating system. This is especially handy if you're doing application testing from a remote platform over a command line protocol like SSH. Nikto is fast and accurate, although not particularly stealthy which makes it an ideal tool for defensive application assessment but keeps it out of the arsenal of attackers.
The fact that Nikto is open source and written in Perl means that it can easily be extended and customized. With a little knowledge of Perl and access to a text editor you can easily peruse and modify the source code to suite specific use cases. Extending Nikto by writing new rules is quick and easy, and because Nikto is supported by a broad open source community the vulnerability database it uses is frequently updated.
Given the ease of use, diverse output formats, and the non-invasive nature of Nikto it is undoubtedly worth utilizing in your application assessments. Nikto even has functionality to integrate into other penetration testing tools like Metasploit. The command line interface may be intimidating to novice users, but it allows for easy scripting and integration with other tools. It is quite easy to export targets to a file, feed that file to Nikto, then output results in a format that can be consumed by other tools.