Thursday, January 10, 2013

Distributed Port Scanning: Creating an Nmap Cluster Using DNmap

Introduction

When performing a security engagement, the information gathered from port scanning is crucial. However, these scans can take a substantial amount of time when we set a reasonable timeout in an attempt to be thorough. So what happens when we need to scan a large amount of hosts? Say, an entire continent? We need to find a way to distribute the bandwidth load to multiple hosts in parallel. Fortunately, a tool has been developed which will allow us to create and manage a cluster of hosts which each have its own bandwidth dedicated to port scanning.


What is DNmap?

Created by Sebastian Garcia in 2009 using the Twisted Python framework, DNmap provides the ability to create a distributed Nmap scanning network using a standard client-server architecture. DNmap is included by default in Backtrack, and can be installed easily on any system that has Python.

Note: Before you install and run DNmap, keep in mind that clients will execute any Nmap command given to them. DNmap was not designed to completely prevent abuse from the server host, so ensure that you trust the server you connect to!

Installing DNmap

DNmap requires Nmap, Python 2.7, and the following libraries to be installed:\

  • python-twisted
  • python-openssl
Though DNmap comes installed by default in Backtrack, here's how to install it in a Debian based system (in this case, Ubuntu):
jordan@pentest:~$ sudo apt-get install python-openssl python-twisted
jordan@pentest:~$ wget http://downloads.sourceforge.net/project/dnmap/dnmap_v0.6.tgz
jordan@pentest:~$ tar -xvzf dnmap_v0.6.tgz
view raw gistfile1.txt hosted with ❤ by GitHub
From here, all files are in the dnmap_v0.6/ directory.

DNmap Usage and Example

The DNmap architecture looks like the following:


For our example, we will consider the following topology:


As with any client/server architecture, we first need to setup the server. Let's take a look at the dnmap_server.py usage:

root@bt:/pentest/scanners/dnmap# python dnmap_server.py -h
+----------------------------------------------------------------------+
| dnmap_server Version 0.6 |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| Author: Garcia Sebastian, eldraco@gmail.com |
| www.mateslab.com.ar |
+----------------------------------------------------------------------+
usage: dnmap_server.py <options>
options:
-f, --nmap-commands Nmap commands file
-p, --port TCP port where we listen for connections.
-L, --log-file Log file. Defaults to /var/log/dnmap_server.conf.
-l, --log-level Log level. Defaults to info.
-v, --verbose_level Verbose level. Give a number between 1 and 5. Defaults to 1. Level 0 means be quiet.
-t, --client-timeout How many time should we wait before marking a client Offline. We still remember its values just in case it cames back.
-s, --sort Field to sort the statical value. You can choose from: Alias, #Commands, UpTime, RunCmdXMin, AvrCmdXMin, Status
-P, --pem-file pem file to use for TLS connection. By default we use the server.pem file provided with the server in the current directory.
dnmap_server uses a '<nmap-commands-file-name>.dnmaptrace' file to know where it must continue reading the nmap commands file. If you want to start over again,
just delete the '<nmap-commands-file-name>.dnmaptrace' file
As you can see, the server requires a file containing our Nmap commands to run. Let's use the following file called "commands.txt":
nmap -A -Pn -v -p1-1024 192.168.56.103
nmap -A -Pn -v -p1024-10000 192.168.56.103
view raw commands hosted with ❤ by GitHub
To show the ability to schedule multiple jobs, we add multiple Nmap commands to our file. Since we only have one target host, we are simply going to split up the port ranges between jobs. If we had more than one client in our cluster, these jobs would be distributed among the hosts, and it would be difficult for the target host administrator to tell that one attacker was behind the port scan.

So, with our Nmap commands file in place, let's start up the server:
root@bt:/pentest/scanners/dnmap# python dnmap_server.py -f ~/commands.txt
+----------------------------------------------------------------------+
| dnmap_server Version 0.6 |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| Author: Garcia Sebastian, eldraco@gmail.com |
| www.mateslab.com.ar |
+----------------------------------------------------------------------+
=| MET:0:00:30.015147 | Amount of Online clients: 0 |=
With our server started up and waiting for clients, let's take a quick look at the dnmap_client.py usage:
root@bt:/pentest/scanners/dnmap# python dnmap_client.py -h
+----------------------------------------------------------------------+
| dnmap Client Version 0.6 |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| Author: Garcia Sebastian, eldraco@gmail.com |
| www.mateslab.com.ar |
+----------------------------------------------------------------------+
usage: dnmap_client.py <options>
options:
-s, --server-ip IP address of dnmap server.
-p, --server-port Port of dnmap server. Dnmap port defaults to 46001
-a, --alias Your name alias so we can give credit to you for your help. Optional
-d, --debug Debuging.
-m, --max-rate Force nmaps commands to use at most this rate. Useful to slow nmap down. Adds the --max-rate parameter.
It looks like all we need to provide is a server address, port number, and an alias (or name) for our client. Let's call our client "minion1", connect to the server, and start running commands.
root@bt:/pentest/scanners/dnmap# python dnmap_client.py -s 192.168.56.101 -a minion1
+----------------------------------------------------------------------+
| dnmap Client Version 0.6 |
| This program is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2 of the License, or |
| (at your option) any later version. |
| |
| Author: Garcia Sebastian, eldraco@gmail.com |
| www.mateslab.com.ar |
+----------------------------------------------------------------------+
Client Started...
Nmap output files stored in 'nmap_output' directory...
Starting connection...
Client connected succesfully...
Waiting for more commands....
+ No -oA given. We add it anyway so not to lose the results. Added -oA 5807742
Command Executed: nmap -A -Pn -v -p1-1024 192.168.56.103 -oA 5807742
Sending output to the server...
Waiting for more commands....
+ No -oA given. We add it anyway so not to lose the results. Added -oA 71264162
Command Executed: nmap -A -Pn -v -p1024-10000 192.168.56.103 -oA 71264162
Sending output to the server...
Waiting for more commands....
^CConnection lost. Reason: Connection to the other side was lost in a non-clean fashion: Connection lost.
Trying to reconnect in 10 secs. Please wait...
Back on the server, we see the following status:
+ Client ID connected: 192.168.56.102:49747 (minion1)
=| MET:0:00:55.011100 | Amount of Online clients: 1 |=
Clients connected
-----------------
Alias #Commands Last Time Seen (time ago) UpTime Version IsRoot RunCmdXMin AvrCmdXMin Status
minion1 1 Jan 10 18:26:27 ( 0' 1") 0h 0m 0.6 True 0.0 0.0 Executing
=| MET:0:01:00.015067 | Amount of Online clients: 1 |=
Clients connected
-----------------
Alias #Commands Last Time Seen (time ago) UpTime Version IsRoot RunCmdXMin AvrCmdXMin Status
minion1 1 Jan 10 18:26:27 ( 0' 6") 0h 0m 0.6 True 0.0 0.0 Executing
=| MET:0:01:05.014816 | Amount of Online clients: 1 |=
Clients connected
-----------------
Alias #Commands Last Time Seen (time ago) UpTime Version IsRoot RunCmdXMin AvrCmdXMin Status
minion1 1 Jan 10 18:26:27 ( 0'11") 0h 0m 0.6 True 0.0 0.0 Executing
=| MET:0:01:10.010916 | Amount of Online clients: 1 |=
Clients connected
-----------------
Alias #Commands Last Time Seen (time ago) UpTime Version IsRoot RunCmdXMin AvrCmdXMin Status
minion1 2 Jan 10 18:26:43 ( 0' 0") 0h 0m 0.6 True 3.8 1.9 Executing
=| MET:0:01:20.014574 | Amount of Online clients: 1 |=
Clients connected
-----------------
Alias #Commands Last Time Seen (time ago) UpTime Version IsRoot RunCmdXMin AvrCmdXMin Status
minion1 2 Jan 10 18:26:43 ( 0'10") 0h 0m 0.6 True 3.8 1.9 Executing
=| MET:0:01:30.010685 | Amount of Online clients: 1 |=
Clients connected
-----------------
Alias #Commands Last Time Seen (time ago) UpTime Version IsRoot RunCmdXMin AvrCmdXMin Status
minion1 2 Jan 10 18:27:00 ( 0' 4") 0h 0m 0.6 True 3.6 2.5 Online
+ Connection lost for minion1 (192.168.56.102:49747).
=| MET:0:01:35.011836 | Amount of Online clients: 0 |=
Clients connected
-----------------
Alias #Commands Last Time Seen (time ago) UpTime Version IsRoot RunCmdXMin AvrCmdXMin Status
^Croot@bt:/pentest/scanners/dnmap# ls
dnmap_client.py dnmap_server.py nmap_results README server.pem
root@bt:/pentest/scanners/dnmap# cd nmap_results/
root@bt:/pentest/scanners/dnmap/nmap_results# ls
5807742.nmap 71264162.nmap
It looks like all of the commands have completed. The results by default are stored in a folder called nmap_results/. We can see that the results have indeed been sent back to our server.

Hopefully this short tutorial helped show the usage and helpfulness of distributing Nmap commands across multiple clients using DNmap. It's also important to note that you can always create multiple servers to host multiple clients.

A big thanks goes out to Sebastian for taking the time to create such a helpful tool. As always, if you ever have any questions or comments, let me know below!

- Jordan