Nmap Development mailing list archives

Re: [NSE] new features: script arguments and buffered reading


From: "Eddie Bell" <ejlbell () gmail com>
Date: Thu, 9 Aug 2007 11:49:21 +0100

hi Stoiko, nice work ;)

Passing arguments to scripts was always going to be hard. I think
maybe we should enforce (as a coding standard) that all script
arguments should be in their own namespace to avoid confusion. I.E.

anonFtp={user='x',pass='y'},SSHv1_Support={algo='blah'}

Otherwise we are going to end up with a lot of values for user, pass,
host etc. It could cause subtle behavioural errors such as one script
having a mandatory argument and another having an optional argument
with the same name. The user may wish to set the mandatory argument
without realising an optional argument will be also set for a
different script.

Another problem, which may be out of the scope of this patch, is how
to know what options are available. If a script has a mandatory
argument how does the user know this without running a scan in verbose
mode and seeing the error? If a script has optional arguments how can
the user know these exist with out reading and understanding the
script?

Perhaps the best place to tell the user about arguments would be umit.
It could eventually have a nse interface where script options can be
viewed and set graphically.

Anyway these are not issues with your patch, just things to bare in mind

thanks
 - eddie

On 07/08/07, Stoiko Ivanov <stoiko () xover htu tuwien ac at> wrote:
1) arguments to nse-scripts
   can be passed via the --script-args option it takes a string as
   argument, which is interpreted as a lua-tableconstructor (with a
   slightly different syntax):
   i.e.
   --script-args foo=bar,user=baz,ftp={srv=192.168.1.1,pass=droz}
   results in a table containing the following entries:
   t={foo="bar",user="baz", ftp={srv="192.168.1.1",pass="droz"}}
   (note that the keys (e.g. user) are strings (i.e. you can access
   "baz" either as t.user or as t["user"]) ).
   I've allowed for subtables to be part of the script-arguments, since
   this gives the opportunity to override arguments for certain scripts
   (e.g. if script foo.nse should be provided with another user-name than
   the others it simply gets its own subtable).

   script-arguments (both key and values) may contain any characters,
   apart from '{', '}', '=' and ',' (should those be needed - I'll find
   a workaround). However since the arguments are processed by the shell,
   they have to be put inside '"' (or escaped), if they contain spaces
   (or other special characters, including the brackets for sub-tables).

   The argument-string is checked wheter it contains exactly as many
   '{' as '}' as a sort of simple tampering prevention (should be enough
   since only a '}' closes the table-constructor, which would make it
   possible to do damage) - until now I haven't found a way to bypass
   it, but I guess there may be some possibilities - maybe anyone of you
   has an idea?
   The argument-table is then saved inside the nmap.registry with the
   name "args". Thus l = nmap.registry.args.ftp.pass (with the above
   --script-args string) would assign "droz" to l.


2) buffered network I/O
   a new function inside NSE's nsock buffer allows to parse data incoming
   through a socket: sd:receive_buf() (I actually don't think the name
   fits - so suggestions about alternatives would be appreciated)
   it takes two arguments. The first one is either a string or a function.
   If it is a string it is passed to lua's string.find() function for
   parsing the data and the prefix until the match is returned with the
   remains being saved inside a buffer for later calls to receive_buf(). If
   the argument is a function it is called instead of string.find(). The
   provided function has to take one argument (the buffer) and its return
   values have to be as those of string.find(). The second parameter is a
   boolean indicating wheter the delimiter should be returned along with
   the prefix (defaulting to true).
   For example with a buffer of: "some data ab some more data"
   the first call to sd:receive_buf("ab",false) would return:
   "some data "
   and the second call would return
   " some more data"
   whereas a call to sd:receive_buf("ab") would return:
   "some data ab" the first time.

   If no match is found receive_buf() tries to fetch more data.
   From the script-developers point of view receive_buf() behaves exactly
   like the other receive_*() functions: It returns two values (status and
   val).

   I've also added a new nselib-module (match.lua) which contains functions
   to be used as first parameter to receive_buf().
   Currently there are two functions:
   regex("pcre-pattern") - uses the provided pcre-lua-module to match for a
   delimiter and numbytes(number) which works similarily to the
   unbuffered receive_bytes(), it returns however exactly the requested
   number of bytes leaving the rest inside the buffer for later processing.

   I took most inspiration for receive_buf() from doug's make_buffer, which
   is inside the stdnse nselib module.


I would be grateful for testing and reviewing (especially wheter someone finds
a way to tamper with the --script-args).

cheers
stoiko

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org


Current thread: