The road to a skilled white hat is paved with many milestones, one of which teaches you how to do a simple Nmap scan. A little further down is the more advanced sampling, along with the use of a powerful Nmap feature called the Nmap Scripting Engine. Below we learn how to modify scripts for NSE and write what we will do today.
The Nmap script engine is one of Nmap's most robust yet underutilized features, with a wide range of scripts to automate tasks beyond port scans and basic network discovery. Some of these tasks include scripts for detecting vulnerabilities, detecting advanced versions, detecting malware, fuzzing, and even exploiting them.
Nmap can use the command-line argument -sC to execute a standard set of scripts. However, this can be very loud, as some of these scripts are quite intrusive. Users can also specify which script or scripts to use with the script argument. You can submit individual scripts as well as entire categories of scripts.
One of the most important aspects of NSE, however, is the ability for users to optimize and modify scripts to better meet their needs scripts from scratch. All scripts used by NSE are written in an embedded scripting language called Lua.
Lua is an efficient, dynamically typed scripting language that is both powerful and lightweight. It is very flexible because it supports procedural, functional and object-oriented programming. Lua is meant to be portable, so it can be easily embedded into other applications with a C API. It can run on almost any platform, including Unix, Windows, mobile devices, and embedded microprocessors like ARM. Lua has been used in many popular applications, including Adobe Photoshop Lightroom and Garry's Mod.
Let's go over some basics to get a feel for the language. Comments begin with a double hyphen and run to the end of the line:
- This is a comment in Lua
In the tradition of learning a new programming language is the classic "Hello World!" Program can be written as:
print ("Hello world!")
Global variables do not have to be declared, and unlike some languages, there is no error accessing a variable that is not initialized nil returned. Local variables, on the other hand, are assigned the local keyword:
print (a) - returns nil locally b = 5 print (b) - returns 5
Control flow in Lua consists of if and if … else statements for conditionals and while repeat and for loops for iteration. Some examples follow:
if condition then statement otherwise statement End
while doing condition statement Repeat end
statement to condition
for i = x, y, z do statement end
Functions in Lua work much like other languages and require a function name, a return statement, and an end statement. The following is an example of a simple function that returns the larger of the two numbers:
function max (a, b) if (a> b) then greater = a otherwise greater = b The End come back bigger End
A complete tutorial on Lua goes beyond the scope of this article, but more detailed information can be found on Lua's page. Now that we have the basics of the language, we can start interacting with some NSE scripts.
Writing a Basic Script
- The header contains mainly metadata such as author, description, category, and other relevant information about the script
- The Rule section defines conditions that enable the script to execute. This section must contain at least one of the following functions that determine when the script will execute: prerule, hostrule, portrule, or postrule.
- The action section executes the main function of the script. All logic and instructions are covered in this section.
For demonstration purposes, we create a simple script that determines if a particular port is open and outputs a relevant message. Let's start with the head. For now we can give a short description and leave it at that:
- HEAD - Description = [[ This is a simple script example that determines if a port is open. ]] author = "zero byte"
Next we can turn to the rule section. Let's define a portrel to see if a particular port is open or not:
- RULE - Portrule = function (host, port) Return port.protocol == "tcp" and port.state == "open" end
Now we can define the actual script logic in the action area. Have the script display a message for any open port:
- ACTION - action = function (host, port) back "This port is open!" End
The entire script should now look something like this:
- HEAD - Description = [[ This is a simple script example that determines if a port is open. ]] author = "zero byte" - RULE - Portrule = function (host, port) Return port.protocol == "tcp" and port.state == "open" The End - ACTION - action = function (host, port) back "This port is open!" end
From here we should be able to run our script to see if it works. Save the file as example-script.nse and copy it to / usr / share / nmap / scripts . We can just keep it simple and use localhost to test our script. We also need to pass a port, so run service apache2 restart in the terminal to make sure the web server is running, and we can now use port 80 . Finally, let's run the script:
nmap --script example-script localhost -p 80 Starting Nmap 7.70 (https://nmap.org) at 2018-09-12 13:08 CDT Nmap Scan report for localhost (127.0.0.1) Host is active (0.000087s latency). Other addresses for localhost (not scanned): :: 1 Port State Service 80 / TCP open http | _example-script: This port is open! Nmap finished: 1 IP address (1 host-up) scanned in 0.30 seconds
We can see that port 80 is open on localhost and the script displays our message. This is just a rudimentary example of what NSE scripts actually can do, but basic functionality makes it easy to modify existing scripts for custom requests or to write even more robust scripts from scratch.
Other NSE Scripts
The Nmap Scripting Engine is a powerful feature of Nmap that extends the functionality of the core tool. In this guide, we learned about Lua, the programming language that powers NSE, and how to structure and write a simple script for our own use. We barely scratched the surface of what Nmap scripts really do, so I encourage you to get involved and get your hands dirty so you can take full advantage of NSE.
Do not miss: How to Easily Recognize CVEs with Nmap Scripts