Last updated at Wed, 27 Sep 2017 21:16:14 GMT

If you write auxiliary Metasploit modules, you are no doubt familiar with the venerable report_auth_note() -- this is the function you call in your module to let your database know about all your awesome new credentials. Well, it's been changed. More specifically, the database schema has changed. We now treat cracked credentials with all due deference and get them out of the notes table ghetto, and into a new table all their own, as befitting their stature (as of revision r10034).

Why do I say the notes table is a ghetto? Well, notes are great because they're flexible and you can stuff basically anything you want in there. But, that flexibility came with some ugly costs -- all that freewheeling data is really hard to work with outside of Metasploit. Go ahead and do a select data from notes; and you'll see what I mean. Any client has to go and un-base64 it, then parse out all the fields, and even then nothing is really guaranteed. So, while notes are great for, well, internal notes, they're not so great for making useful things like cracked credentials more available to your other pen-testing gear.

The schema and API change has made report_auth_note() (now aliased to report_creds()) a little more strict, in order to ensure that you can actually use those hard-earned credentials. The new API requires all credentials to be associated with to a specific service (denoted by a :port) on a specific IP address (denoted by :host). There are a few other fields you can populate -- here's a typical example of its use, courtesy of the ssh_login auxiliary module:

def do_report(ip,user,pass,port,proof)
  report_auth_info(
    :host => ip,
    :port => rport,
    :sname => 'ssh',
    :user => user,
    :pass => pass,
    :proof => proof,
    :active => true
  )
end

The most notes-like of these is the :proof field -- this is where you can stash a blob of text that proves that the login was good (usually the output of a uname -a or somesuch), but it's not serialized, so you can still read it later. The fields :user and :pass are what you'd expect, and :sname is the name of the service (in case you haven't registered it yet through report_service()). :active is intended to indicate that a credential was good the last time you tried it; if your victim changes his password and you don't know it anymore, you can set :active to false instead of deleting the credential.

Not shown in this example is the use of :type. Basically, this field lets you denote passwords that aren't strictly passwords; for example, smb_login can set it to "smb_hash," and ssh_pubkey_login sets it to "ssh_key" and populates the :pass field with a file path to the ssh_key in question.

Two new commands, db_creds and db_add_creds, allow for quick access to the credentials table for reading and updating credentials, and they are shockingly easy to use.

So, why is any of this important? Well, credential gathering is pretty awesome. Metasploit has thirty modules already that deal with credential gathering, covering all of the popular Internet protocols (I know this because I just touched them all to conform to the new API).

More to the point, writing bruteforce modules is tons of fun. In many ways, it's a lot easier to crack credentials than it is to get shells via exploits. As long as you have a good handle on how an authentication protocol works, it's usually straightforward to write a bruteforce module. And as a bonus, your attack will live a lot longer, since it's pretty hard to patch for weak passwords.

If you happen to notice a gap in our bruteforce coverage, and we don't cover your favorite auth protocol, please feel free to get to work on implementing a new auxiliary module to get the job done. Or, if you're feeling lazy and you hate doing fun things, file a feature request and let someone else take a crack at it.