4.3. Nikto Under the Hood
This section traces the logic flow of the entire Nikto program, and
discusses the routines available through
nikto_core and LibWhisker. The Nikto program
structure is modular. Most of Nikto's actual
functionality lies within external plug-ins
,
which you can find in the plugins/ directory
where the Nikto source code was uncompressed.
|
It is a good idea to browse the source of existing plug-ins to better
understand how they work. Execute the following Linux command from
the Nikto root directory to generate a tag file for the source tree:
find . -name "*.pl" -o -name "*.pm" -o -name "*.plugin" | xargs ctags
--language-force=perl
|
|
4.3.1. Nikto's Program Flow
At 200
lines of code the Nikto.pl file is relatively
small. The following paragraphs briefly discuss what the program does
on a macro level.
At the start of the program, you'll notice a series
of global
variables. To avoid namespace collisions, plug-in developers
shouldn't use these
variable names. Next,
load_configs( ) parses the configuration file
config.txt and initializes
%CONFIG. Then the find_plugins( )
routine searches expected directories for the
plug-in file, and sets appropriate values in
%FILES. The nikto_core
plug-in and LibWhisker are included with
the require keyword, which makes all routines from
LW.pm and nikto_core.plugin
available to the rest of nikto.pl as well as to
its plug-ins. The general_config() routine parses the command-line options and
sets %CLI appropriately. Next,
LibWhisker's http_init_request( )
initializes LibWhisker's
%request with default values.
The proxy_setup( )
function sets the
appropriate values in %request, depending upon the
proxy settings in the configuration file. The open_output() function opens a file handle for
writing program output, only if an output file was
specified on the command line. Next, set_targets( )
populates %TARGETS with
the hostname or IP address of the target, along with specified ports.
The load_scan_items( )
function loads the
vulnerability checks found from
servers.db,
scan_database.db, and
user_scan_database.db (if the file exists) into
global arrays.
Finally, the main loop for the vulnerability checks is reached. For
each item in %TARGETS the following actions are
taken: first, dump_target_info( )
displays the target information. Next,
check_responses( )
verifies that valid and invalid requests
return the HTTP status codes 200 and
404. In addition, this function sets any HTTP
Basic authentication credentials specified by the user. The
check_cgi( ) function is called to verify the
existence of common CGI directories (these can be set in the
configuration file). The set_scan_items() function is called to process
scan db arrays and to perform macro replacement on
the checks. Next, run_plugins( ) is called to
execute the plug-ins on the current target host and port. Finally,
test_target( ) is called to perform the actual checks found
in the scan db arrays.
4.3.2. Nikto's Plug-in Interface
Nikto's
plug-in interface is relatively
simple. The plug-ins are Perl programs executed by
Nikto's run_plugins( )
function. For a plug-in to be executed
correctly, it must meet three requirements. First, the plug-in file
should use the naming convention
nikto_foo.plugin,
where foo is the name of the plug-in.
Second, the plug-in should have an initialization routine with the
same name as the plug-in. And third, the plug-in should have an entry
in the file nikto_plugin_order.txt. This file
controls which plug-ins run, and in what order. As an example, a line
could be added to the file that simply states nikto_foo.
This would call the routine nikto_foo( )
within the file nikto_foo.plugin. To keep the
plug-ins portable, you should not use additional modules, but instead
copy the needed code into the plug-in itself.
A side effect of the chosen plug-in execution method is that the
plug-ins and Nikto share the global namespace. This is why you
don't need use statements to
access Nikto or LibWhisker routines. This simplifies the plug-ins.
Plug-in developers should make sure their variable and routine names
don't conflict with any of Nikto's
global variables.
|