Lab 2.3: NSE

Objectives

  • To analyze the categories of Nmap Scripting Engine (NSE) scripts
  • To run some of the most useful NSE scripts
  • To gather and analyze web server robots.txt files
  • To gather SMB information from a target Windows machine, including the hostname and a VERY useful list of users on the box
  • To scan a target environment to find SSH servers that speak the older, weaker SSH protocol version 1
  • To compare how Nmap behaves when NSE scripts are run with and without version scanning

Table of Contents

 

Lab Setup

Ensure that you can ping 10.10.10.10 in the 560 target environment.

$ ping 10.10.10.10

Root Access

You will need root access for the majority of the lab. This is a reminder to be aware of the prompts. If you see a prompt containing #, it means the command is run as root. To become root, type the following command.

sec560@slingshot:~$ sudo su -
root@slingshot:~#  

 

Lab – Step-by-Step Instructions

1. The script.db File

We will now look at the functionality of the Nmap Scripting Engine. Start by opening up the file that contains the inventory of all the scripts that have been defined for NSE:

$ gedit /usr/local/share/nmap/scripts/script.db

If you don’t like gedit, a simple WYSIWYG editor, you can use another Linux/UNIX editor with which you are familiar, such as vi, emacs, nano, and so on.

script.db file

This script.db file has a simple format, essentially just mapping script categories, such as "safe", "intrusive", and "vulnerability", to the specific script files, which end in .nse. Note that some scripts are in multiple categories, such as dns-zone-transfer.nse, which is in the discovery and intrusive categories.

Let’s count the number of scripts in some of the categories by sending the script.db file through the wc (word count) command with the -l (where that lowercase L stands for line count) option:

sec560@slingshot:~$ cd /usr/local/share/nmap/scripts
sec560@slingshot:/opt/nmap/scripts$ cat script.db | grep safe | wc -l
335
sec560@slingshot:/opt/nmap/scripts$ cat script.db | grep discovery | wc -l
303
sec560@slingshot:/opt/nmap/scripts$ cat script.db | grep intrusive | wc -l
210

2. The http-robots.txt.nse Script

Let’s experiment with the http-robots.txt.nse script. This script pulls the robots.txt file from target web servers. The robots.txt file tells well-behaved web crawlers (such as those from the major search engines that are attempting to find new pages on the World Wide Web) to ignore given directories or pages on a website because they have information that the website owner doesn’t want to be included in search engines. In other words, robots.txt tells well-behaved crawlers what to ignore, possibly because it is sensitive. Attackers often focus on the directories and files listed in robots.txt because they may include some juicy information. As penetration testers, we’d like to have a copy of the robots.txt files from all web servers in our target range. Note that robots.txt is a file readable by anyone who accesses the website and is usually included in the document root of the web server. Thus, it isn’t a security feature; it merely helps keep things out of search engines that shouldn’t be there. But it is also a red flag indicating where more interesting parts of a website might be located in the file system structure.

The Nmap script http-robots.txt.nse pulls robots.txt files from target machines. Let’s test it by invoking it as follows:

$ nmap -n --script=http-robots.txt.nse 10.10.10.60 -p 80

Note that because we have specified a given script with the --script= syntax, we do not have to specify -sC. Indicating a specific script implies that we want to invoke a script scan, so -sC is not required. The results of the nmap command above should look like this:

$ nmap -n --script=http-robots.txt.nse 10.10.10.60 -p 80

Starting Nmap 7.70 ( https://nmap.org )
Nmap scan report for 10.10.10.60
Host is up (0.0012s latency).

PORT   STATE SERVICE
80/tcp open  http
| http-robots.txt: 4 disallowed entries
| /images /cgi-bin /stuff/folder/personal/fred/files
|_/sensitive_stuff

Nmap done: 1 IP address (1 host up) scanned in 0.30 seconds

Note that we are having the script focus on just TCP port 80 to save time. During a more comprehensive scan, we would have invoked it with -sV and possibly with scanning all target TCP ports 1-65535 (-p 1-65535).

In the Nmap output, you should see the directories that are listed in the robots.txt file of the target website.

3. The nbstat.nse Script

Next, let’s explore the Nmap nbstat.nse script. This script works like the nbtstat.exe command included in some versions of Windows, which pulls NetBIOS-over-TCP statistics, including machine names, MAC addresses, and usernames. Note that although the Windows command (which is included on some but not all versions of Windows) is nbtstat.exe (with a t), the Nmap script is called nbstat.nse, without the t between the b and the s characters.

On a Linux terminal window, run Nmap against 10.10.10.10, configured to run the nbstat.nse script:

$ nmap -n --script=nbstat.nse 10.10.10.10

Your output will look similar to this:

$ nmap -n --script=nbstat.nse 10.10.10.10

Starting Nmap 7.70 ( https://nmap.org )
Nmap scan report for 10.10.10.10
Host is up (0.00054s latency).
Not shown: 983 closed ports
PORT      STATE SERVICE
25/tcp    open  smtp
42/tcp    open  nameserver
80/tcp    open  http
135/tcp   open  msrpc
139/tcp   open  netbios-ssn
445/tcp   open  microsoft-ds
49152/tcp open  unknown
49153/tcp open  unknown
49154/tcp open  unknown
49155/tcp open  unknown
49156/tcp open  unknown
49157/tcp open  unknown
49158/tcp open  unknown
49159/tcp open  unknown
49160/tcp open  unknown
49161/tcp open  unknown
49163/tcp open  unknown

Host script results:
|_nbstat: NetBIOS name: TRINITY, NetBIOS user: <unknown>, NetBIOS MAC: 00:0c:29:ce:b4:fe (VMware)

Nmap done: 1 IP address (1 host up) scanned in 2.17 seconds

Look specifically at the result of the scripts:

Host script results:
|_nbstat: NetBIOS name: TRINITY, NetBIOS user: <unknown>, NetBIOS MAC: 00:0c:29:ce:b4:fe (VMware)

As Nmap runs, look at its output. Notice anything interesting? Nmap is doing a port scan of the target machine, analyzing the interesting ports on the box. Even though we told it to run only the nbstat.nse script, it does a port scan. Why? Because it needs to know which ports are open so that it can determine if the service(s) the script tests are available. A SYN stealth scan (a "half-open" scan) has been run. Then if the appropriate ports are open (TCP ports 135, 139, or 445), Nmap runs the nbstat.nse script against the target, showing the results in its output. You should see, at the bottom of your Nmap output, a line that says "NBSTAT: NetBIOS name:" and so on, with the results from the nbstat.nse script.

4. SMB Scripts

Next, let’s look at the Server Message Block (SMB) scripts included with Nmap, many of which were written by Ron Bowes. First, we’ll look at the name of all the SMB NSE scripts included with this version of Nmap:

$ ls /usr/local/share/nmap/scripts/smb*.nse
/opt/nmap/scripts/smb2-capabilities.nse
/opt/nmap/scripts/smb2-security-mode.nse
/opt/nmap/scripts/smb2-time.nse
/opt/nmap/scripts/smb2-vuln-uptime.nse
/opt/nmap/scripts/smb-brute.nse
/opt/nmap/scripts/smb-double-pulsar-backdoor.nse
/opt/nmap/scripts/smb-enum-domains.nse
... truncated for brevity ...

Here you can see scripts that let us perform brute force password guessing (smb-brute.nse), check for common vulnerabilities (smb-check-*), and plunder the target for information (smb-enum-domains, groups, processes, and more).

In addition, the smb-psexec script allows us to provide a username and password in the administrators group as well as one or more commands we want to run in a configuration file, and this script will attempt to cause any targets that it discovers communicating using SMB to run the commands. It operates in a fashion similar to the Microsoft Sysinternals’ psexec command. The Nmap option looks like this:

--script-args=smbuser=[AdminUser],smbpass=[AdminPass],config=[ConfigFileName]

Let's try the smb-enum-users.nse script using the command below:

$ nmap -n --script=smb-enum-users.nse -p 139 10.10.10.10

You should see output similar to this:

$ nmap -n --script=smb-enum-users.nse -p 139 10.10.10.10

Starting Nmap 7.70 ( https://nmap.org )
Nmap scan report for 10.10.10.10
Host is up (0.00049s latency).

PORT    STATE SERVICE
139/tcp open  netbios-ssn
MAC Address: 00:0C:29:CE:B4:FE (VMware)

Host script results:
| smb-enum-users:
|   TRINITY\Administrator (RID: 500)
|     Description: Built-in account for administering the computer/domain
|     Flags:       Normal user account
|   TRINITY\dizzy (RID: 1009)
|     Flags:       Normal user account
|   TRINITY\Falken (RID: 1001)
|     Full name:   Falken
|     Flags:       Normal user account, Password does not expire
|   TRINITY\George (RID: 1006)
|     Full name:   George
|     Flags:       Normal user account, Password does not expire
|   TRINITY\Guest (RID: 501)
|     Description: Built-in account for guest access to the computer/domain
|     Flags:       Normal user account, Password does not expire, Account disabled, Password not required
|   TRINITY\Monk (RID: 1003)
|     Full name:   Monk
|     Flags:       Normal user account, Password does not expire
|   TRINITY\skodo (RID: 1024)
|     Flags:       Normal user account
|   TRINITY\Susan (RID: 1005)
|     Full name:   Susan
|_    Flags:       Normal user account, Password does not expire

Nmap done: 1 IP address (1 host up) scanned in 0.92 seconds

In the output, you can see the results of the port scan, indicating that the given port is open. Then you can see a list of users and their Relative Identifiers (RIDs), which is the unique portion of each user’s Security Identifier (SID), in the output. We’ll look at the technical mechanisms used by this script later in the course to iterate through a series of RIDs to find usernames.

If you have extra time, you can try the other SMB NSE scripts in this directory.

5. The sshv1 Script

Next, we use an NSE script to test whether machine 10.10.10.60 supports SSH protocol version 1, an older form of the Secure Shell protocol that is subject to man-in-the-middle attacks. SSH protocol version 2 is far stronger. We can measure whether the server has this issue by invoking Nmap as follows:

$ nmap -n --script=sshv1 --script-trace 10.10.10.60 -p 22

This command tells Nmap to run the script called sshv1.nse and to display the trace of the script’s activity to the screen (--script-trace), running against target 10.10.10.60 and using TCP port 22. Note that we are measuring only TCP port 22 for this example to keep things focused and quick. TCP port 22 is the port commonly associated with SSH.

Your output will look similar to this:

$ nmap -n --script=sshv1 --script-trace 10.10.10.60 -p 22

Starting Nmap 7.70 ( https://nmap.org )
NSOCK INFO [0.1940s] nsock_iod_new2(): nsock_iod_new (IOD #1)
NSOCK INFO [0.4240s] nsock_connect_tcp(): TCP connection requested to
10.10.10.60:22 (IOD #1) EID 8
NSOCK INFO [0.4240s] nsock_trace_handler_callback(): Callback: CONNECT
SUCCESS for EID 8 [10.10.10.60:22]
NSE: TCP 10.10.75.102:57422 > 10.10.10.60:22 | CONNECT
NSOCK INFO [0.4240s] nsock_readlines(): Read request for 1 lines from
IOD #1 [10.10.10.60:22] EID 18
NSOCK INFO [0.4330s] nsock_trace_handler_callback(): Callback: READ
SUCCESS for EID 18 [10.10.10.60:22] (41 bytes): SSH-1.99-OpenSSH_6.6.1p1
Ubuntu-2ubuntu2.
NSE: TCP 10.10.75.102:57422 < 10.10.10.60:22 | SSH-1.99-OpenSSH_6.6.1p1
Ubuntu-2ubuntu2

NSE: TCP 10.10.75.102:57422 > 10.10.10.60:22 | SSH-1.5-NmapNSE_1.0

After you run this command, look through its output carefully. Can you get a sense of what the script is doing? Note that the --script-trace option makes Nmap put a lot of details in its output. Normally, you wouldn’t run Nmap with this option. Still, for debugging, troubleshooting, or fine-grained analysis, this option is helpful.

So, does 10.10.10.60 support SSH protocol version 1? The answer should be yes based on the indications at the bottom of the output of your most recent Nmap command. Specifically, these lines of output identify the server as supporting SSHv1:

PORT   STATE SERVICE
22/tcp open  ssh
|_sshv1: Server supports SSHv1

6. Examining the sshv1 Script

Now that we’ve got a feel for what these scripts can do, let’s look at them in more detail so that we can avoid some common mistakes in their usage. Let’s return to the sshv1.nse file, opening it in an editor to look at an important setting in each script:

$ gedit /usr/local/share/nmap/scripts/sshv1.nse

Now look for portrule = shortport.port_or_service(22, "ssh").

This line tells Nmap that it should run only this script if it finds TCP port 22 listening on a target machine, or if a version scan finds that the ssh service is listening. That’s good, but what happens if an sshd is listening on a port other than TCP port 22? We need to know. PLEASE DO NOT CHANGE THIS PORT VALUE OF 22 IN THE sshv1.nse FILE!

sshv1.nse

Let’s reconfigure our sshd on our own Linux systems to listen on TCP ports 22 and 23 and to allow SSHv1. You can do this by opening the file /etc/ssh/sshd_config:

$ sudo gedit /etc/ssh/sshd_config

In the sshd_config file (NOT THE ssv1.nse file), find the line that says Port 22. Add a new line below it that says:

Port 23

Next, find the line that says Protocol 2. Append to that line a comma followed by a 1 so that it says:

Protocol 2,1

The resulting file should look like this:

Updated sshd_config file

Save the file. The changes will make SSH run on TCP ports 22 and 23 and support SSH versions 1 and 2.

Now, make your sshd reread its configuration file by restarting SSH:

$ sudo service ssh restart

We can look at the listening services by using lsof -Pni. The -i option indicates that we want to see network usage, whereas the -P modifier makes lsof display port numbers, not service names.

Verify that your sshd is listening on TCP port 23 by running:

$ sudo lsof -Pi | grep 23
mongod     1231     mongodb    7u  IPv4   17244      0t0  TCP localhost:27017 (LISTEN)
ntpd       2104         ntp   16u  IPv6   22132      0t0  UDP *:123
ntpd       2104         ntp   17u  IPv4   22135      0t0  UDP *:123
ntpd       2104         ntp   18u  IPv4   22139      0t0  UDP localhost:123
ntpd       2104         ntp   19u  IPv4   22141      0t0  UDP 10.10.75.102:123
ntpd       2104         ntp   20u  IPv6   22143      0t0  UDP localhost:123
ntpd       2104         ntp   21u  IPv6   22145      0t0  UDP [fe80::20c:29ff:fee6:f3df]:123
exim4      2389 Debian-exim    4u  IPv4   22447      0t0  TCP localhost:25 (LISTEN)
exim4      2389 Debian-exim    5u  IPv6   22448      0t0  TCP localhost:25 (LISTEN)
nmbd       2395        root   16u  IPv4   22617      0t0  UDP *:137
nmbd       2395        root   17u  IPv4   22618      0t0  UDP *:138
nmbd       2395        root   18u  IPv4   22620      0t0  UDP 10.10.75.102:137
nmbd       2395        root   19u  IPv4   22621      0t0  UDP 10.10.255.255:137
nmbd       2395        root   20u  IPv4   22622      0t0  UDP 10.10.75.102:138
nmbd       2395        root   21u  IPv4   22623      0t0  UDP 10.10.255.255:138
sshd      13466        root    3u  IPv4 1811105      0t0  TCP *:23 (LISTEN)
sshd      13466        root    4u  IPv6 1811107      0t0  TCP *:23 (LISTEN)

If you see a line of output mentioning sshd and TCP 23, you are ready to go. You should see a line similar to this:

sshd      2865        root    3u  IPv4  34035      0t0  TCP *:23 (LISTEN)

If you don't see the above line, make sure to make the correct changes to the sshd_config file and that you restarted the SSH server.

Now run Nmap with the sshv1.nse script against your localhost:

$ nmap -n --script=sshv1 127.0.0.1

Your output should look like this:

$ nmap -n --script=sshv1 127.0.0.1

Starting Nmap 7.70 ( https://nmap.org )
Nmap scan report for 127.0.0.1
Host is up (0.000054s latency).
Not shown: 992 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
|_sshv1: Server supports SSHv1
23/tcp   open  telnet
25/tcp   open  smtp
80/tcp   open  http
631/tcp  open  ipp
3306/tcp open  mysql
5432/tcp open  postgresql

Nmap done: 1 IP address (1 host up) scanned in 0.23 seconds

Do you see any output from the script (not Nmap overall, but the script itself) commenting on whether SSH protocol version 1 is in use? It shows that version 1 is in use on port 22, but not on port 23. Also, it shows port 23 as telnet. Port 23 is actually running SSH (remember, we added Port 23 to the sshd_config file). Nmap performed only a TCP connect scan, discovering that TCP 23 was open but not realizing that it spoke SSH. Instead, it just looked up the "normal" service associated with that port, which is telnet. It never measured whether a telnet service was listening there because we didn’t do a version scan. Instead, it just looked up that service in the nmap-services file. Also, the sshv1.nse script’s portrule that checks for 22 or "ssh" service couldn’t see that TCP 23 spoke ssh, so it didn’t try to measure the SSH protocol version.

Let’s try it again, but this time telling Nmap to perform a version scan in addition to running the script:

$ nmap -n --script=sshv1 127.0.0.1 -sV

You should see output similar to this:

$ nmap -n --script=sshv1 127.0.0.1 -sV

Starting Nmap 7.70 ( https://nmap.org )
Nmap scan report for 127.0.0.1
Host is up (0.000054s latency).
Not shown: 992 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh        OpenSSH 7.2 (protocol 1.99)
|_sshv1: Server supports SSHv1
23/tcp   open  ssh        OpenSSH 7.2 (protocol 1.99)
|_sshv1: Server supports SSHv1
25/tcp   open  smtp
80/tcp   open  http
... truncated for brevity ...

Now you should see in your output that the listener on TCP port 23 not only speaks SSH but that it also uses SSH protocol version 1. Our script ran properly this time because the version scan detected that TCP 23 spoke the Secure Shell protocol.

So what is the point of this component of this lab? It’s actually twofold.

First, Nmap, when configured to run a script, performs a port scan of the target machine. It needs to do so, or the script cannot determine whether it should run against the target machine because it doesn’t know whether the port(s) that the script is interested in is available. The -p option can help tailor this, making Nmap check a smaller number of ports rather than all interesting ports.

Second, Nmap’s scripts without a version scan may miss important services listening on nonstandard ports. Thus, when running a script from within Nmap, you are likely better served by making sure that you run a version scan (-sV) along with the script invocation (-sC or --script).

These are important lessons for network penetration testers and ethical hackers who want to make the most out of NSE functionality.

7. Wrapping It Up

To finish with that piece of the lab, restore your sshd settings to their original values, making sshd listen on TCP port 22. Open the sshd configuration:

$ sudo gedit /etc/ssh/sshd_config

Remove the line that says Port 23. And make sure you remove the ,1 from the Protocol so that your sshd will speak only ssh protocol version 2, the stronger form of ssh protocol.

Save the file, and then send the restart sshd to make it reread its configuration:

$ sudo service ssh restart

 

Conclusion

In this lab, we’ve explored several very useful Nmap Scripting Engine scripts, including those associated with web server robots.txt files, SMB attacks against Windows machines, and SSH protocol version 1 detection. The Nmap Scripting Engine is one of the most dynamic and useful features of Nmap, as it opens Nmap up to all kinds of vulnerability scanning and checking options across a large-scale environment.