summaryrefslogtreecommitdiffstats
path: root/scripts/afp-brute.nse
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/afp-brute.nse')
-rw-r--r--scripts/afp-brute.nse111
1 files changed, 111 insertions, 0 deletions
diff --git a/scripts/afp-brute.nse b/scripts/afp-brute.nse
new file mode 100644
index 0000000..960e5ae
--- /dev/null
+++ b/scripts/afp-brute.nse
@@ -0,0 +1,111 @@
+local afp = require "afp"
+local nmap = require "nmap"
+local shortport = require "shortport"
+local stdnse = require "stdnse"
+local string = require "string"
+local table = require "table"
+local unpwdb = require "unpwdb"
+
+-- we don't really need openssl here, but let's attempt to load it as a way
+-- to simply prevent the script from running, in case we don't have it
+local openssl = stdnse.silent_require("openssl")
+
+description = [[
+Performs password guessing against Apple Filing Protocol (AFP).
+]]
+
+---
+-- @usage
+-- nmap -p 548 --script afp-brute <host>
+--
+-- @output
+-- PORT STATE SERVICE
+-- 548/tcp open afp
+-- | afp-brute:
+-- |_ admin:KenSentMe => Valid credentials
+
+-- Information on AFP implementations
+--
+-- Snow Leopard
+-- ------------
+-- - Delay 10 seconds for accounts with more than 5 incorrect login attempts (good)
+-- - Instant response if password is successful
+--
+-- Netatalk
+-- --------
+-- - Netatalk responds with a "Parameter error" when the username is invalid
+--
+
+author = "Patrik Karlsson"
+license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
+categories = {"intrusive", "brute"}
+
+
+-- Version 0.3
+-- Created 01/15/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
+-- Revised 03/09/2010 - v0.2 - changed so that passwords are iterated over users
+-- - this change makes better sense as guessing is slow
+-- Revised 09/09/2011 - v0.3 - changed account status text to be more consistent with other *-brute scripts
+
+portrule = shortport.port_or_service(548, "afp")
+
+action = function( host, port )
+
+ local result, response, status = {}, nil, nil
+ local valid_accounts, found_users = {}, {}
+ local helper
+ local usernames, passwords
+
+ status, usernames = unpwdb.usernames()
+ if not status then return end
+
+ status, passwords = unpwdb.passwords()
+ if not status then return end
+
+ for password in passwords do
+ for username in usernames do
+ if ( not(found_users[username]) ) then
+
+ helper = afp.Helper:new()
+ status, response = helper:OpenSession( host, port )
+
+ if ( not(status) ) then
+ stdnse.debug1("OpenSession failed")
+ return
+ end
+
+
+ stdnse.debug1("Trying %s/%s ...", username, password)
+ status, response = helper:Login( username, password )
+
+ -- if the response is "Parameter error." we're dealing with Netatalk
+ -- This basically means that the user account does not exist
+ -- In this case, why bother continuing? Simply abort and thank Netatalk for the fish
+ if response:match("Parameter error.") then
+ stdnse.debug1("Netatalk told us the user does not exist! Thanks.")
+ -- mark it as "found" to skip it
+ found_users[username] = true
+ end
+
+ if status then
+ -- Add credentials for other afp scripts to use
+ if nmap.registry.afp == nil then
+ nmap.registry.afp = {}
+ end
+ nmap.registry.afp[username]=password
+ found_users[username] = true
+
+ table.insert( valid_accounts, string.format("%s:%s => Valid credentials", username, password:len()>0 and password or "<empty>" ) )
+ break
+ end
+ helper:CloseSession()
+ end
+ end
+ usernames("reset")
+ end
+
+ local output = stdnse.format_output(true, valid_accounts)
+
+ return output
+
+end