Nmap Security Scanner Ref Guide Security Lists Security Tools Site News Advertising About/Contact Credits Sponsors |
Intro | Reference Guide | Book | Install Guide
Download | Changelog | Zenmap GUI | Docs
Bug Reports | OS Detection | Propaganda | Related Projects
In the Movies | In the News
Example Scripts
| Chapter 9. Nmap Scripting Engine |
## Example Scripts This section should probably provide 2–3 scripts which show a diverse and interesting set of NSE features. Each script should probably have its own sect2 containing a brief description of the script and anything noteworthy about it, followed by the script itself with annotations (lineannotation tag) as you can see, for example, at http://nmap.org/vscan/vscan-technique-demo.html DT: perhaps include an optional version field ### Finger-Test Script The finger script (`finger.nse`) is a perfect example of how short typical NSE scripts are. first the information fields are filled out, note that the `id` field is kept short, this is important since it is printed in Nmap's output. A detailed description of what the script actually does should go in the `description` field.
    id="Finger Results"

    description="attempts to get a list of usernames via the finger service"

    author = "Eddie Bell <ejlbell@gmail.com>"

    license = "See nmaps COPYING for licence"
The `categories` field is a table containing all the categories the script belongs to—These are used for script selection through the `--script` option.
    categories = {"discovery"}
You can use the facilities provided by the nselib (the section called “Lua Extensions”) by `requiring` them. Here we want to use shorter port rules.
    require "shortport"
We want to check whether the service behind the port is finger, or whether it runs on finger's well known port 79. Through this we can use the information gathered during the version scan (if finger runs on a non-standard port) or still run against at least the port we expect it, should the version detection information not be available.
    portrule = shortport.port_or_service(79, "finger")

    action = function(host, port)
      local socket = nmap.new_socket()
      local results = ""
      local status = true
The function `err_catch()` will be called for clean up, through NSE's exception handling mechanism. Here it only closes the previously opened socket (which should be enough in most cases).
    local err_catch = function()
      socket:close()
    end
The clean up function gets registered for exception handling via a call to `nmap.new_try()`
      local try = nmap.new_try(err_catch())
The script sets a timeout of 5000, which is equivalent to 50 seconds. Should any operation require more time we'll receive a `TIMEOUT` error message.
      socket:set_timeout(5000)
For actually using exception handling we need to wrap calls to functions, which may return an error inside `try()`
      try(socket:connect(host.ip, port.number, port.protocol))
      try(socket:send("\n\r"))
The call to `receive_lines()` is not wrapped in `try()`, because we don't want to abort the script just because we didn't receive the data we expected. Note that there is less data than requested (100 lines), we still receive it and the status is `true` —consequent calls would yield a `false` status.
      status, results = socket:receive_lines(100)
      socket:close()
The script returns a string only if we got the data we wanted, otherwise `nil` is returned (automatically, since scripts return one result).
      if not(status) then
        return results
      end
    end
### Service Owner Lookup via Identd `showOwner.nse` demonstrates the flexibility of the NSE, which is unmatched by other parts of Nmap. If the target is running an `identd` daemon it connects to it for each running service and tries to identify its owner.
    id = "Service owner"

    description = "Opens a connection to the scanned port, opens a connection to \
    port 113, queries the owner of the service on the scanned port and prints it."

    author = "Diman Todorov <diman.todorov@gmail.com>"

    license = "See nmaps COPYING for licence"

    categories = {"safe"}
Portrules are not restricted to those provided by the short-port module (the section called “Short Portrules”). They can be any function taking a host- and a porttable as argument and returning a boolean.
    portrule = function(host, port)
      local identd, decision
In order to determine the state of a port, which is not provided as argument we just have to construct a table describing the port (i.e. its number and the protocol it's using) and pass it to `nmap.get_port_state()` which returns a table filled with the information Nmap has about the port.
      local auth_port = { number=113, protocol="tcp" }
      identd = nmap.get_port_state(host, auth_port)

      if
        identd ~= nil
        and identd.state == "open"
      then
        decision = true
      else
        decision = false
      end

      return decision
    end

    action = function(host, port)
      local owner = ""
Scripts can open any number of connection they want.
      local client_ident = nmap.new_socket()
      local client_service = nmap.new_socket()

      local catch = function()
        client_ident:close()
        client_service:close()
      end

      local try = nmap.new_try(catch)

      try(client_ident:connect(host.ip, 113))
      try(client_service:connect(host.ip, port.number))

      local localip,localport,remoteip,remoteport = try(client_service:get_info())

      local request = port.number .. ", " .. localport .. "\n"

      try(client_ident:send(request))

      owner = try(client_ident:receive_lines(1))

      if string.match(owner, "ERROR") then
        owner = nil
      else
        owner = string.match(owner, "USERID : .+ : (.+)\n", 1)
      end

      try(client_ident:close())
      try(client_service:close())

      return owner
    end
Version Detection using NSE |  | Implementation
| [ Nmap | Sec Tools | Mailing Lists | Site News | About/Contact | Advertising | Privacy ]