Nmap Development mailing list archives

Re: brute.lua, unpwdb.lua, custom iterators and flexibility


From: Aleksandar Nikolic <nikolic.alek () gmail com>
Date: Sat, 7 Jul 2012 17:42:56 +0200

Hi all,

while I'm doing some changes to the way brute lib works, something
caught my eye.

For example, what I see happening is that from time to time the script
won't get a valid response from the server. That would cause the
script to retry, which would increase the retry counter. Now,
sometimes, after the retry , the script does get a valid reply and
should continue the execution, but the retry counter stays the same.
So, what I would like to do is add a way for a script to reset the
retry counter
when it gets the valid reply. That way the script would continue
running even if we sometimes do get invalid replies, and would stop if
we get blocked by the server.

Any objections to this reasoning?


Aleksandar


On Wed, Jun 27, 2012 at 6:09 PM, David Fifield <david () bamsoftware com> wrote:
On Wed, Jun 27, 2012 at 05:11:16PM +0200, Aleksandar Nikolic wrote:
Hi all,

I have a small report here about some ideas regarding brute scripts.

After some discussion, we came to the conclusion that it would
be nice to be able to add a specific username to try when bruteforcing.
For example, I want to add a username "ftp" to ftp-brute along with the rest
of the usernames and passwords form unpwdb.

Now, there are three logical options:
1) Add custom usernames and password pairs
2) Adding just username to test against all passwords form unpwdb
3) Prepend or append username(s) to the list of usernames from unpwdb

I think that (3) is definitely what we want. My ideal API would look
something like this (using semi-pseudocode):

users = concat_iterators(table_iterator({"ftp"}), brute.usernames_iterator())
engine.setUsernameIterator(users)

Here concat_iterators is a made-up function that does what you expect,
it returns a new iterator that runs over each of its constituent
iterators in turn, like itertools.chain from Python.
brute.usernames_iterator is a function returning the brute library's
default user name iterator, the one that gets used by default if you
don't call setUsernameIterator.

Naturally, there would be an independent setPasswordIterator. The
usefulness of the current brute addIterator is limited, because as
you've seen, it is asking for an iterator that returns (user, pass)
pairs. That means if you want to add just an additional user name, you
have to duplicate the password loop and all the other machinery from the
brute library in your custom iterator.

Here's another example of how caller-provided iterators allow greater
flexibility. Let's say you're testing a service that you know doesn't
allow passwords longer than six characters. You could do something like
this:

pass = filter_iterator(brute.passwords_iterator(), function (x) return #x <= 6 end)
engine.setPasswordIterator(pass)

This is why I don't think the programmer interface should not be limited
to only appending or prepending to the default lists, even if that's the
most common use case. We can even provide convenience options to do
prepending, but I believe it should be implemented using iterator
concatenation as above.

There can still be a setIterator method that yields (user, pass) pairs,
for callers who need ultimate control. I think that concat_iterators
makes addIterator unnecessary.

One small implementation problem is that concat_iterators and
filter_iterator need to understand the "reset" convention at each level.
They should probably live in unpwdb and be called from there.

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


Current thread: