|
Hi,
Here is one of the more technical
articles covering NASL writing within the customer portal. This was
written by a Tenable Customer Support (TCS) engineer with the
assistance of the Tenable's Research team. TCS borrowed
information from the Nessus Network Auditing book, ISBN: 1-931836-08-6, various
articles of information in house at Tenable, team discussions, etc.
It's one of several that TCS compiles to assist customers with specific subjects
that are covered in many online and printed documentations like the book above
(shameless plug here for Renaud's book) but the information may be in more than
one place.
I am pasting it below, as is in html, I
hope everyone can see it properly.
Warning, another shameless plug.
Currently there are about 217 KB online articles on Tenable products available
to Tenable customers, 81 of which deal with Nessus. We add to them when
ever we see recurrent configuration questions, articles we believe are helpful
to trouble shooting various issues, technical articles that may not exist or are
found in several sources of documentation.
Shameless plugs for Tenable
complete. Please see the NASL doc below.
Regards,
| ARTICLE SUMMARY: |
What is
NASL?
|
| SYMPTOMS: |
NASL (Nessus Attack Scripting Language) is a language designed
after having written ~ 100 (or 200?) Nessus plugins in C. Its initial aim
was to "factorize" all the network operations done by the plugins to have
a single point where to tune scripts (if every plugin was written in C,
then they could each decide to enforce some timeout or not, etc...), and
to speed up the development of new scripts. In particular, NASL has no
concept of memory management (not even pointers), and lets you manipulate
strings in the same way you would manipulate integers. While initially a
script would mainly do something like build buffer / send / recv / process
result, the initial NASL functionality allowed to do more. NASL has
support for() and while() loops since day one, as well as user-defined
functions.
As time went by, NASL scripts have become more complex.
NASL2 (16 times faster than NASL1) solved a lot of the problems we had met
between 1999 and 2002. It also extended the language significantly, by
adding the support for arrays, a real parser, etc.... NASL3 is a rewrite
of the NASL2 engine, but the parser is mostly the same. As a result, NASL3
extends the language capabilities a little, but less than NASL2 extended
NASL1. |
| RESOLUTION: |
The NASL syntax
The NASL syntax is mostly
inspired from the C language. It also looks similar to PHP without the
useless '$' character in front of variables. Just as in C/PHP/BASH/PERL, a
control block starts with a { and ends with a }
~ ~ ~ ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~
Variables
Variables do not need to be
pre-declared in NASL, except when you want them to be a function local
variable. The following is legal :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ a = 42; ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
By default, every
variable is global unless if explicitly stated otherwise. Therefore
:
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ function
some_function() { a = 42; } ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
In the code above, the function some_function() declares and
modifies the value of the global variable 'a'. This often leads to fun and
late-night debugging exercises such as in the code below :
~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ function myFunc() { for ( i = 0 ; i <
10 ; i ++ ) display("i = ", i, "\n"); }
for ( i = 0 ; i < 5 ;
i ++ ) myFunc(); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
In the example
above, one would naively expect myFunc() to be called 5 times. This does
not happen because myFunc() modifies the variable i, so it ends up being
called only once.
The solution to this problem is to use the
local_var keyword :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ function
myFunc() { local_var i;
for ( i = 0 ; i < 10 ; i ++ )
display("i = ", i, "\n"); }
for ( i = 0 ; i < 5 ; i ++ )
myFunc(); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
In the case above, the
code works as expected.
By convention, every NASL function should
declare all its local variables, so avoid the problem above. The command
nasl -W script.nasl will warn the user about global variables defined in a
local function, but won't notice the re-use of a global variable inside of
a local function.
Some historical notes
:
* NASL1 did
not have any support for local variables. As a result, it was not uncommon
to have scripts which used variable names such as ____i to make sure they
were not stepping on any other i variable out there. * NASL2 had some
kind of variables inheritance. That is, if you call the function foo()
which declares the variable 'x' and then calls the function bar() which
uses the variable x without declaring it, then bar() would modify foo's x.
This behavior has been removed in NASL3.
NASL is very lax'ist
when it comes to variable types (in the same way PHP is). The following
three types exist :
* integers * strings * arrays/hash
tables
In some cases you may want to explicitly convert one type to
the other using the string(), int() or make_list() functions.
~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
String manipulation
Since
most NASL scripts end up sending and receiving data, handling strings is
fairly easy. Strings can be manipulated the same way as integers -- they
can be added or subtracted :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ x =
"hello"; y = "world"; z = x + y; ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
See the chapter on string functions for more information about
string handling.
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
Named/Anonymous arguments
One big difference is
the concept of anonymous and named variables for some functions. For
instance, imagine the following C function :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ ~ ~ ~ int make_smb_request(int soc, char * pipe, int fid, int pid,
int mid, char * message) ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
This
function is a bit complex. Some arguments may not be necessary (and would
therefore set to NULL when used), while some others are important. As the
function is complex, one has to remember the order of the arguments. That
is, if I want to call make_smb_request() in my C program, I would probably
have to look it up to see what is the order of the arguments and so forth.
So your function call would be :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ e
= make_smb_request(soc, "\\PIPE", -1, 42, 4096, NULL); ~ ~ ~ ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~
I solved this problem by introducing named
arguments in NASL. Basically, you'd prefix each argument of the function
by its name. So if we had the following NASL function (equivalent to the C
function above) :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ function
make_smb_request(socket, pipe, fid, pid, mid, message) ~ ~ ~ ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~
Then you would call it by prefixing each
argument with its name :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ e =
make_smb_request(socket:soc, pipe:"\\PIPE", fid:-1, pid:42, mid:4096,
message:NULL); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
The good thing is
that you can skip the arguments you don't use. If in the function above
message and fid are optional, you could very well call :
~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ e = make_smb_request(socket:soc, pipe:"\\PIPE",
pid:42, mid:4096); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
And that would
work just as perfectly (fid and message would then be set to NULL in the
function itself).
The order of the arguments does not matter either
-- the following call is equivalent to the previous one :
~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ e = make_smb_request(pid:42, mid:4096, socket:soc,
pipe:"\\PIPE"); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
A lot of functions
have such a prototype. We call them named functions. At the opposite, a
function which does prefix the arguments by their name is called an
anonymous function. For instance :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ display(1,2,3); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
In anonymous
functions, the order of the arguments does matter.
Finally, some
functions are mixed (open_sock_tcp() is a good example) -- that is, they
take named AND anonymous arguments.
In general, functions with
anonymous arguments either only take one argument, or an infinite number
of arguments of the same kind. Some functions are an exception to confirm
that rule.
I thought I was the first one to come up with this
concept, but it turns out that Objective C
(http://en.wikipedia.org/wiki/Objective_C) did it before (however all the
variables are mandatory and their order must be respected). Perl also
supports the same kind of notation when passing a hash table as arguments
to a function. So I did not invent anything at all in the
end.
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
User-defined
functions
One can easily define his own functions using the
function keyword. One can define named functions or anonymous functions
:
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ function
my_named_function(fist_name, last_name) { display("Hello ",
first_name, " ", last_name, "\n"); return 0; } ~ ~ ~ ~ ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~
The arguments passed to a function are copied.
Therefore modifying them within the function does not affect the caller
:
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ function
func(i) { i++; }
j = 42; func(i:j); display(j,
"\n"); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
An anonymous function is
defined as below :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ function
myFunc() { display(_FCT_ANON_ARGS[0]); }
myFunc(1); ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
That is, by using the local array
_FCT_ANON_ARGS, which is a reserved variable name, one can access the
anonymous arguments passed to the function. _FCT_ANON_ARGS[0] returns the
first argument passed to the function, _FCT_ANON_ARGS[1] returns the
second one, etc...
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
includes
One can include scripts by calling the
include() function. Note that this is not really a function but a
pre-processor macro, which means that it will ALWAYS be
evaluated.
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ include("foobar.inc"); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
If the
included file does not exist, then a warning is displayed but the script
is executed anyways.
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
Control structures ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
NASL supports several control structures :
if() ... else
...
NASL supports C-style if/else statements, which do not require
braces (at the opposite of perl which forces the user to write unreadable
code) :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ if ( a != b )
display("OK"); else display("Not OK");
if ( a < 42 )
{ display("OK\n"); } else display("Not OK\n");
if ( a ) a
= 42; ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
for()
C
style for() loops are supported, however a condition MUST be defined as a
second argument. Once again, braces are not mandatory :
~ ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ for ( i = 0 ; i < 42 ; i ++ )
display("OK\n");
i = 0; for ( ; i < 42 ; ) i ++; ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~
The following is not valid, as no condition is
defined :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ for ( ;; ) ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~
while()
C style while() loops
are supported, and once again the braces are not mandatory : ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~
i = 0; while ( i < 42 ) i
++;
while ( j < 1000 ) { j ++; } ~ ~ ~ ~ ~ ~ ~ ~ ~
~ ~ ~ ~ ~ ~
repeat...until
The syntax is repeat
BLOCK until CONDITION. 'BLOCK' must start and end with braces :
~ ~
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ i = 0; repeat { display("Hello
World\n"); i ++; } until i > 42; ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
foreach()
foreach() iterates through an array
an copies each of its element into a variable :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~ ~ ~ ~ ~ array = make_list("This", "is", "a", "wonderful",
"world");
foreach word (array) { display(word, "
"); } display("\n"); ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
~
x
The 'x' operator repeats the function call
before it N times :
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ display("Hello
World\n") x 10; ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Note that this
operator is considered deprecated and may therefore be removed in the
future. |
-----Original Message----- From: nessus-bounces@list.nessus.org
[mailto:nessus-bounces@list.nessus.org]
On Behalf Of Jason Chambers Sent: Friday, May 18, 2007 03:45 To: George A.
Theall Cc: nessus@list.nessus.org Subject: Re: NASL DOCS
George A.
Theall wrote: > As far as I know, those are the most up-to-date versions,
at least > that are generally available. > > > I expected
to find some >> documentation on the web site, but
nada... > > If others are interested in this, please let me know and
I'll see what > can be done.
I'm interested as
well.
Regards, -- Jason
Chambers UCLA jchambers@ucla.edu 310-206-5603
_______________________________________________
Nessus mailing list
Nessus@list.nessus.org
http://mail.nessus.org/mailman/listinfo/nessus
|