Monitoring Changes on Your Network over Time Using PBNJ
Joshua D. Abraham
Using Nmap to scan your network has become a security
standard. With the addition of OS detection and service version detection,
Nmap's features have expanded to the point where it is one of the most useful
security tools available today. Nevertheless, it is widely understood that Nmap
has several limitations, the chief one of which is the manner in which Nmap
processes information about changes. To be frank, it simply doesn't. When you
perform an Nmap scan of your network, what Nmap does do is present you with a
"snapshot in time "of your network.
The brilliance of Nmap is its capability to perform this
task quickly, reliably, and with precision. But as we all know, the only
constant in life is change. So when there are changes on your network and you
run your next scan, as far as Nmap is concerned, there is no history; there is
only the current scan.
Nmap does not provide a convenient method of monitoring
changes on the network so, until recently, the only way to actually determine
whether anything had changed was to perform another scan and compare the
results by hand. This is a very time-consuming process that is tedious and
prone to all the typical errors of such tasks. Sure, the *nix wizards would
just whip up a quick shell or Perl script to show the changes between two
scans, but again, this is still only comparing two snapshots in time.
A better solution is to store a history of the changes in a
common location, a database, as opposed to dealing with flat files created on
an ad hoc basis. This is exactly what PBNJ does: it parses, correlates, and
stores in a database all the information it harvests from Nmap about the
changes taking place on your network.
PBNJ
PBNJ is a suite of tools written in Perl. PBNJ calls Nmap to
perform a scan and then PBNJ correlates the information about the targets using
Nmap's result and the PBNJ database. PBNJ uses Nmap::Parser to extract the data
from Nmap's XML output. The default database of PBNJ is Sqlite3; however, PBNJ
also supports MySQL and Postgres.
Running Nmap
Here is an example of running Nmap with root privilege by
using sudo. The output of the file will be stored in the file.xml so that it
can be parsed later.
$ sudo ./nmap -A 127.0.0.1 -oX file.xml
Nmap has many different options and settings. If you want
more information about various options use the manpage, or just run "nmap -h".
Installing PBNJ and Its Prerequisites
Besides requiring Nmap::Parser, PBNJ also requires several other Perl modules.
The full requirements are:
- YAML
- DBI
- DBD::SQLite
- XML::Twig
- File::Which
- Text::CSV_XS
- File::HomeDir
- Nmap::Parser
All of these modules can be installed using CPAN interactive
shell or by using the package management system. The source for PBNJ can be
downloaded from the PBNJ site at:
http://pbnj.sf.net
Simply download the latest version and extract the files to
the desired location:
$ tar -jxvf pbnj-2.04.tar.bz2
Now you can proceed with the installation of PBNJ.
$ perl Makefile.PL
$ make
# make install (as root)
One quick method to make sure everything is set up properly
is to parse an Nmap output file. This is most useful for *nix administrators
who know exactly which arguments they want to pass Nmap -- those which are
optimal in their environment. Therefore, use PBNJ to simply extract the
information from the Nmap XML file.
$ scanpbnj -x nmap.xml
--------------------------------------
Starting Scan of 127.0.0.1
Inserting Machine
Inserting Service on 22:tcp ssh
Inserting Service on 25:tcp smtp
Scan Complete for 127.0.0.1
--------------------------------------
$ rm data.dbl
This shows that PBNJ is working properly. Here I removed the
database file to continue with explanation and examples.
PBNJ Files and Features
Once you have installed PBNJ, you will notice that there are
a few programs included. Each of these programs has a manpage, if you are
curious about learning more about the various options and configurations. The
following programs are included:
- ScanPBNJ (scanning and correlation)
- OutputPBNJ (querying and alerting)
- Genlist (ping scanner)
For this article, I will only talk about ScanPBNJ and
OutputPBNJ. The main program of PBNJ is ScanPBNJ, which performs the scanning,
parsing, and storing of the Nmap scans in the PBNJ database. OutputPBNJ
provides an easy method of accessing the data stored in the PBNJ database.
Single PBNJ Scan
PBNJ can be used to perform a scan of a target.
$ sudo scanpbnj 127.0.0.1
--------------------------------------
Starting Scan of 127.0.0.1
Inserting Machine
Inserting Service on 22:tcp ssh
Inserting Service on 25:tcp smtp
Scan Complete for 127.0.0.1
--------------------------------------
It is clear that this machine is running SSH and SMTP mail
server on ports 22 and 25. I will now stop SSH and then rescan the machine.
$ sudo /etc/init.d/ssh stop
* Stopping OpenBSD Secure Shell server... [ ok ]
$ sudo scanpbnj 127.0.0.1
--------------------------------------
Starting Scan of 127.0.0.1
Machine is already in the database
Checking Current Services
! Service 22:tcp ssh is down
= smtp:25 is (unknown version) Postfix smtpd
Scan Complete for 127.0.0.1
--------------------------------------
PBNJ shows that SSH on port 22 is now down. The various
types of changes that are tracked are either state changes or version changes.
State changes can be either "up" or "down". Version changes are a bit more
complicated. For example, when you first scan a machine, all the services that
are running on the target are inserted into the database.
Now, when the second scan occurs, ScanPBNJ will take the new
scan results and look up the latest information about each of the services for
that machine. If there is no service found in the database on a given port,
then that service is then inserted into the database. However, if there is a different version
running on the machine, ScanPBNJ extracts the information about the service and
inserts a new entry into the database with the state set to "down", and then
uses the new results and inserts it into the database with a state of "up".
OutputPBNJ Querying
Having direct output from a scanning tool is one thing, but
having a system that actually uses queries to extract the information that is
most useful to the user, is quite another. OutputPBNJ provides this
functionality. It does this by using a YAML configuration file that contains
queries for the PBNJ database. It is able to execute any of the queries in the
configuration file based on their name and print the result in various output
formats. Here is an example of a single query in the configuration file:
- name: latestinfo
desc: latest host and services info
sql: |-
select S.updated_on,M.host, S.service,S.state,S.version,S.protocol
from services as S,machines as M where updated_on = (select
updated_on from services ORDER BY updated_on DESC limit 1) and
M.mid = S.mid
This contains the name, the description, and the SQL for the
query. For now, the SQL isn't important. The only thing you need to know is
that it will return the latest changes that have occurred in the database.
Therefore, we can use this query to determine what is currently going on by
calling OutputPBNJ and simply passing the name of the query and the output
type. For this example, we will be using CSV, comma delimited, as the output
type for formatting reasons.
$ sudo ./outputpbnj --query latestinfo --type csv
Thu Oct 19 00:08:43 2006,localhost,ssh,down,4.2p1 Debian 7ubuntu3.1,tcp
Automating PBNJ Scans
Now that we have a brief understanding of how to use ScanPBNJ
and OutputPBNJ, we actually have the pieces in place to build an automated
alerting system. We will use ScanPBNJ to perform an automated scan and then use
OutputPBNJ to send the latest changes to an email address.
For this example, I will use a standard 192.168.10.x network
layout, which is a class C network for which I am the administrator. To begin,
open your favorite text editor and create /root/bin/scan.
#!/bin/sh
scanpbnj 192.168.10.0/24
outputpbnj -q latestinfo -t csv | mail -s "PBNJ LatestInfo `date`" root
The first line simply specifies that we are doing shell
programming. The second line performs a scan of the target IP range using the
default arguments. Note that we are not using ping for this scan. This will
make the scan more accurate because all IP addresses will be scanned regardless
of whether they respond to a ping.
The third line is a bit more complicated. The first part is
calling the "latestinfo" query, as we have seen, and the second part is simply
piping the output from OutputPBNJ into mail. This uses the output from
OutputPBNJ as the input to mail. We specify the subject line that contains the
program name, query name and the date data. Finally, we specify the user to
whom the email will be sent, which is the local root user.
Make sure the file is executable:
$ sudo chmod +x /root/bin/scan
We then add the script to the Cron scheduler. Add the following to your crontab:
# scan of 10 network every 2 hours and email the latest changes to root
#m h dom mon dow user command
16 */2 * * * root /root/bin/scan
Bam! Now you will have an automated scanning system with
alerting in place. It almost seems too good to be true!
Addition Features of PBNJ
PBNJ has several additional features that could not be
covered in this article:
- Adding/Removing Queries
- Modifying PBNJ's default Configs
- Using Genlist
Here are various topics that may be included in a follow-up article:
- Building Distributed Scanning Engines with MySQL or Postgres
- External monitoring
- Building custom Queries
PBNJ's Default Sqlite3 Schema
For the people who would like to build their own queries,
the SQL schema is built to be flexible. The three databases that are supported
are Sqlite3, MySQL, and Postgres. Sqlite3 is the default database, so I have
included the Sqlite3 schema below for reference.
CREATE TABLE machines (
mid INTEGER PRIMARY KEY AUTOINCREMENT,
ip TEXT,
host TEXT,
localh INTEGER,
os TEXT,
machine_created TEXT,
created_on TEXT);
CREATE TABLE services (
mid INTEGER,
service TEXT,
state TEXT,
port INTEGER,
protocol TEXT,
version TEXT,
banner TEXT,
machine_updated TEXT,
updated_on TEXT);
Recent Work
I gave a presentation about PBNJ at LinuxWorld August 2006 San Francisco. Also, PBNJ is
included in Backtrack, a well-known Security LiveCD. BackTrack has been dubbed
as the best Security Live CD today, and rated 1st in its category, and 32nd
overall in Insecure.org. Using a LiveCD is one of the easiest methods to try out PBNJ before you install
it. In addition, PBNJ is officially packaged for Debian, FreeBSD and Gentoo. I
recommend using package management regardless of whether you have a great deal
of *nix experience or not.
Installation on Debian (as root):
# apt-get install pbnj
Installation on FreeBSD (as root):
# cd /usr/ports/security/pbnj ; make install clean
Installation on Gentoo (as root):
# emerge pbnj
Conclusion
I hope that you have gained an understanding of the features
that PBNJ can provide when monitoring a network. By using PBNJ, you will be
letting Nmap focus on what it does best, which is providing a snapshot in time.
You will simultaneously be harnessing PBNJ to correlate the changes that occur,
to provide a flexible querying/alerting system -- one that you can
customize to fit in any environment.
Resources
PBNJ -- http://pbnj.sf.net
Nmap -- http://www.insecure.org/nmap
Author's Web site -- http://www.ccs.neu.edu/home/jabra
Backtrack -- http://www.remote-exploit.org
Joshua D. Abraham is a 4th-year Computer
Science student at Northeastern University. He has focused on various network
security-related projects such as PBNJ, IDS, and
Backtrack. He also works with the Volunteer Systems Group at his college, in
addition to working as a Security Professional.
|