diff --git a/CHANGELOG b/CHANGELOG index 8b59d65cc..446085e6d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ # Nmap Changelog ($Id$); -*-text-*- +o [NSE] Added probe for Apple iPhoto (DPAP) and the dpap-brute script that + performs password guessing against a shared iPhoto library. [Patrik] + o [NSE] Fixed http.validate_options when handling a cookie table. [Sebastian Prengel] diff --git a/nmap-service-probes b/nmap-service-probes index 52bf5946d..9bdca6a01 100644 --- a/nmap-service-probes +++ b/nmap-service-probes @@ -9990,3 +9990,12 @@ ports 1414-1420 match ibm-mqseries m|^TSH\x20\0\0\0\xec\x02\x01\x02\0\0\0\0\0\0\0\0\0\x11\x01\0\0\xb5\x01\0\0ID\x20\x20\n&\0\x90\0\0\0\0\xf6\x7f\0\0\0\0@\0\0\0\0\0([^\s]*)\s*Q\0\xb5\x01([^\s]*)\s*,\x01\0\0\0\0\0\0\0\xff\0\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\0\0\0\0\0\0\n\0\0\0\0\0\0\0..\0\0.\0\0\0.\0\0\0[^\s]*\s*$| p/IBM Websphere MQ/ i/Queue manager: $2, Channel: $1/ v/7.0/ softmatch ibm-mqseries m|^TSH\x20\0\0\0| p/IBM Websphere MQ/ + +##############################NEXT PROBE############################## +# Queries iPhoto for the /server-info url containing the shared library name +# +Probe TCP apple-iphoto q|GET /server-info HTTP/1.1\r\nClient-DPAP-Version: 1\.1\r\nUser-Agent: iPhoto/9.1.1 (Macintosh; N; PPC)\r\n\r\n| +rarity 8 +ports 8770 + +match apple-iphoto m|^HTTP/1\.1 200 OK\r\nDate: .*\r\nDPAP-Server: iPhoto/(.*)\r\nContent-Type: application/x-dmap-tagged\r\nContent-Length: \d+\r\n\r\nmsrv\0\0\0\x83mstt\0\0\0\x04\0\0\0\xc8mpro\0\0\0\x04\0\x02\0\0ppro\0\0\0\x04\0\x01\0\x01minm\0\0\0.(.*)mslr\0\0\0\x01\0mstm\0\0\0\x04\0\0\x07\x08msal\0\0\0\x01\0msau\0\0\0\x01\x02msas\0\0\0\x01\x03msix\0\0\0\x01\0msdc\0\0\0\x04\0\0\0\x01$| p/Apple iPhoto/ v/$1/ i/Library name: $2/ diff --git a/scripts/dpap-brute.nse b/scripts/dpap-brute.nse new file mode 100644 index 000000000..a890a05b6 --- /dev/null +++ b/scripts/dpap-brute.nse @@ -0,0 +1,123 @@ +description = [[ +Performs password guessing against an iPhoto Library +]] + + +--- +-- @usage +-- nmap --script dpap-brute -p 8770 +-- +-- @output +-- 8770/tcp open apple-iphoto syn-ack +-- | dpap-brute: +-- | Accounts +-- | secret => Login correct +-- | Statistics +-- |_ Perfomed 5007 guesses in 6 seconds, average tps: 834 +-- +-- +-- Version 0.1 +-- Created 24/01/2011 - v0.1 - created by Patrik Karlsson +-- + +author = "Patrik Karlsson" +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" +categories = {"intrusive", "auth"} + +require("base64") +require("shortport") +require("brute") + +portrule = shortport.port_or_service(8770, "apple-iphoto") + +Driver = { + + new = function(self, host, port) + local o = {} + setmetatable(o, self) + self.__index = self + o.host = host + o.port = port + return o + end, + + connect = function( self ) + self.socket = nmap.new_socket() + self.socket:set_timeout(5000) + return self.socket:connect(self.host, self.port, "tcp") + end, + + login = function( self, username, password ) + local data = "GET dpap://%s:%d/login HTTP/1.1\r\n" .. + "User-Agent: iPhoto/9.1.1 (Macintosh; N; PPC)\r\n" .. + "Host: %s\r\n" .. + "Authorization: Basic %s\r\n" .. + "Client-DPAP-Version: 1.1\r\n" .. + "\r\n\r\n" + + local creds = base64.enc("nmap:" .. password) + data = data:format( self.host.ip, self.port.number, self.host.ip, creds ) + + local status = self.socket:send( data ) + if ( not(status) ) then + local err = brute.Error:new( "Failed to send data to DPAP server" ) + err:setRetry( true ) + return false, err + end + + status, data = self.socket:receive() + if ( not(status) ) then + local err = brute.Error:new( "Failed to receive data from DPAP server" ) + err:setRetry( true ) + return false, err + end + + if ( data:match("^HTTP/1.1 200 OK") ) then + return true, brute.Account:new(username, password, "OPEN") + end + + return false, brute.Error:new( "Incorrect password" ) + end, + + disconnect = function( self ) + self.socket:close() + end, + +} + +local function checkEmptyPassword(host, port) + local d = Driver:new(host, port) + local status = d:connect() + + if ( not(status) ) then + return false + end + + status = d:login("", "") + d:disconnect() + + return status +end + + +action = function(host, port) + + if ( checkEmptyPassword(host, port) ) then + return "Library has no password" + end + + local status, result + local engine = brute.Engine:new(Driver, host, port ) + + engine.options.firstonly = true + engine.options:setOption( "passonly", true ) + + status, result = engine:start() + + return result +end + + + + + diff --git a/scripts/script.db b/scripts/script.db index 460019f0b..e9ab3b34e 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -34,6 +34,7 @@ Entry { filename = "dns-zone-transfer.nse", categories = { "default", "discovery Entry { filename = "domcon-brute.nse", categories = { "auth", "intrusive", } } Entry { filename = "domcon-cmd.nse", categories = { "auth", "intrusive", } } Entry { filename = "domino-enum-users.nse", categories = { "auth", "intrusive", } } +Entry { filename = "dpap-brute.nse", categories = { "auth", "intrusive", } } Entry { filename = "drda-brute.nse", categories = { "auth", "intrusive", } } Entry { filename = "drda-info.nse", categories = { "discovery", "safe", "version", } } Entry { filename = "finger.nse", categories = { "default", "discovery", "safe", } }