Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local bin = require "bin"
- local comm = require "comm"
- local ldap = require "ldap"
- local shortport = require "shortport"
- local stdnse = require "stdnse"
- local table = require "table"
- description = [[
- Attempts to retrieve the Novell Universal Password for a user. You
- must already have (and include in script arguments) the username and password for an eDirectory server
- administrative account.
- ]]
- ---
- -- Universal Password enables advanced password policies, including extended
- -- characters in passwords, synchronization of passwords from eDirectory to
- -- other systems, and a single password for all access to eDirectory.
- --
- -- In case the password policy permits administrators to retrieve user
- -- passwords ("Allow admin to retrieve passwords" is set in the password
- -- policy) this script can retrieve the password.
- --
- -- @args ldap-novell-getpass.account The name of the account to retrieve the
- -- password for
- -- @args ldap-novell-getpass.username The LDAP username to use when connecting
- -- to the server
- -- @args ldap-novell-getpass.password The LDAP password to use when connecting
- -- to the server
- --
- -- @usage
- -- nmap -p 636 --script ldap-novell-getpass --script-args \
- -- 'ldap-novell-getpass.username="CN=admin,O=cqure", \
- -- ldap-novell-getpass.password=pass1234, \
- -- ldap-novell-getpass.account="CN=paka,OU=hr,O=cqure"'
- --
- -- @output
- -- PORT STATE SERVICE REASON
- -- 636/tcp open ldapssl syn-ack
- -- | ldap-novell-getpass:
- -- | Account: CN=patrik,OU=security,O=cqure
- -- |_ Password: foobar
- --
- -- Version 0.1
- -- Created 05/11/2010 - v0.1 - created by Patrik Karlsson <patrik@cqure.net>
- author = "Patrik Karlsson"
- license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
- categories = {"discovery", "safe"}
- portrule = shortport.port_or_service({389,636}, {"ldap","ldapssl"})
- function action(host,port)
- local username = stdnse.get_script_args("ldap-novell-getpass.username")
- local password = stdnse.get_script_args("ldap-novell-getpass.password") or ""
- local account = stdnse.get_script_args("ldap-novell-getpass.account")
- if ( not(username) ) then
- return "\n ERROR: No username was supplied (ldap-novell-getpass.username)"
- end
- if ( not(account) ) then
- return "\n ERROR: No account was supplied (ldap-novell-getpass.account)"
- else
- -- do some basic account validation
- if ( not(account:match("^[Cc][Nn]=.*,") ) ) then
- return "\n ERROR: The account argument should be specified as:\n" ..
- " \"CN=name,OU=orgunit,O=org\""
- end
- end
- -- In order to discover what protocol to use (SSL/TCP) we need to send a
- -- few bytes to the server. An anonymous bind should do it
- local anon_bind = bin.pack("H", "300c020101600702010304008000" )
- local socket, _, opt = comm.tryssl( host, port, anon_bind, nil )
- if ( not(socket) ) then
- return "\n ERROR: Failed to connect to LDAP server"
- end
- local status, errmsg = ldap.bindRequest( socket, {
- version = 3,
- username = username,
- password = password
- }
- )
- if ( not(status) ) then return errmsg end
- -- Start encoding the NMAS Get Password Request
- local NMASLDAP_GET_PASSWORD_REQUEST = "2.16.840.1.113719.1.39.42.100.13"
- local NMASLDAP_GET_PASSWORD_RESPONSE = "2.16.840.1.113719.1.39.42.100.14"
- -- Add a trailing zero to the account name
- local data = ldap.encode( account .. '\0' )
- -- The following section could do with more documentation
- -- It's based on packet dumps from the getpass utility available from Novell Cool Solutions
- -- encode the account name as a sequence
- data = ldap.encode( { _ldaptype = '30', bin.pack("H", "020101") .. data } )
- data = ldap.encode( { _ldaptype = '81', data } )
- data = ldap.encode( { _ldaptype = '80', NMASLDAP_GET_PASSWORD_REQUEST } ) .. data
- data = ldap.encode( { _ldaptype = '77', data } )
- -- encode the whole extended request as a sequence
- data = ldap.encode( { _ldaptype = '30', bin.pack("H", "020102") .. data } )
- status = socket:send(data)
- if ( not(status) ) then return "ERROR: Failed to send request" end
- status, data = socket:receive()
- if ( not(status) ) then return data end
- socket:close()
- local _, response = ldap.decode(data)
- -- make sure the result code was a success
- local rescode = ( #response >= 2 ) and response[2]
- local respname = ( #response >= 5 ) and response[5]
- if ( rescode ~= 0 ) then
- local errmsg = ( #response >= 4 ) and response[4] or "An unknown error occured"
- return "\n ERROR: " .. errmsg
- end
- -- make sure we get a NMAS Get Password Response back from the server
- if ( respname ~= NMASLDAP_GET_PASSWORD_RESPONSE ) then return end
- local universal_pw = ( #response >= 6 and #response[6] >= 3 ) and response[6][3]
- if ( universal_pw ) then
- local output = {}
- table.insert(output, ("Account: %s"):format(account))
- table.insert(output, ("Password: %s"):format(universal_pw))
- return stdnse.format_output(true, output)
- else
- return "\n ERROR: No password was found"
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement