Land #9329, Add basic framework for interacting with MQTT
commit
8ea50572df
|
@ -20,6 +20,7 @@ PATH
|
||||||
metasploit-payloads (= 1.3.23)
|
metasploit-payloads (= 1.3.23)
|
||||||
metasploit_data_models
|
metasploit_data_models
|
||||||
metasploit_payloads-mettle (= 0.3.3)
|
metasploit_payloads-mettle (= 0.3.3)
|
||||||
|
mqtt
|
||||||
msgpack
|
msgpack
|
||||||
nessus_rest
|
nessus_rest
|
||||||
net-ssh
|
net-ssh
|
||||||
|
@ -192,6 +193,7 @@ GEM
|
||||||
method_source (0.9.0)
|
method_source (0.9.0)
|
||||||
mini_portile2 (2.3.0)
|
mini_portile2 (2.3.0)
|
||||||
minitest (5.10.3)
|
minitest (5.10.3)
|
||||||
|
mqtt (0.5.0)
|
||||||
msgpack (1.2.0)
|
msgpack (1.2.0)
|
||||||
multi_json (1.12.2)
|
multi_json (1.12.2)
|
||||||
multipart-post (2.0.0)
|
multipart-post (2.0.0)
|
||||||
|
|
|
@ -23,6 +23,7 @@ require 'msf/core/auxiliary/cisco'
|
||||||
require 'msf/core/auxiliary/kademlia'
|
require 'msf/core/auxiliary/kademlia'
|
||||||
require 'msf/core/auxiliary/llmnr'
|
require 'msf/core/auxiliary/llmnr'
|
||||||
require 'msf/core/auxiliary/mdns'
|
require 'msf/core/auxiliary/mdns'
|
||||||
|
require 'msf/core/auxiliary/mqtt'
|
||||||
require 'msf/core/auxiliary/nmap'
|
require 'msf/core/auxiliary/nmap'
|
||||||
require 'msf/core/auxiliary/natpmp'
|
require 'msf/core/auxiliary/natpmp'
|
||||||
require 'msf/core/auxiliary/iax2'
|
require 'msf/core/auxiliary/iax2'
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'msf/core/exploit'
|
||||||
|
require 'rex/proto/mqtt'
|
||||||
|
|
||||||
|
module Msf
|
||||||
|
module Auxiliary::MQTT
|
||||||
|
def initialize(info = {})
|
||||||
|
super
|
||||||
|
|
||||||
|
register_options(
|
||||||
|
[
|
||||||
|
Opt::RPORT(Rex::Proto::MQTT::DEFAULT_PORT)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
register_advanced_options(
|
||||||
|
[
|
||||||
|
OptString.new('CLIENT_ID', [false, 'The client ID to send if necessary for bypassing clientid_prefixes']),
|
||||||
|
OptInt.new('READ_TIMEOUT', [true, 'Seconds to wait while reading MQTT responses', 5])
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
register_autofilter_ports([Rex::Proto::MQTT::DEFAULT_PORT, Rex::Proto::MQTT::DEFAULT_SSL_PORT])
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup
|
||||||
|
fail_with(Failure::BadConfig, 'READ_TIMEOUT must be > 0') if read_timeout <= 0
|
||||||
|
|
||||||
|
client_id_arg = datastore['CLIENT_ID']
|
||||||
|
if client_id_arg && client_id_arg.blank?
|
||||||
|
fail_with(Failure::BadConfig, 'CLIENT_ID must be a non-empty string')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_timeout
|
||||||
|
datastore['READ_TIMEOUT']
|
||||||
|
end
|
||||||
|
|
||||||
|
def client_id
|
||||||
|
datastore['CLIENT_ID'] || 'mqtt-' + Rex::Text.rand_text_alpha(1 + rand(10))
|
||||||
|
end
|
||||||
|
|
||||||
|
# creates a new mqtt client for use against the connected socket
|
||||||
|
def mqtt_client
|
||||||
|
client_opts = {
|
||||||
|
client_id: client_id,
|
||||||
|
username: datastore['USERNAME'],
|
||||||
|
password: datastore['PASSWORD'],
|
||||||
|
read_timeout: read_timeout
|
||||||
|
}
|
||||||
|
Rex::Proto::MQTT::Client.new(sock, client_opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
def mqtt_connect(client)
|
||||||
|
client.connect
|
||||||
|
end
|
||||||
|
|
||||||
|
def mqtt_connect?(client)
|
||||||
|
client.connect?
|
||||||
|
end
|
||||||
|
|
||||||
|
def mqtt_disconnect(client)
|
||||||
|
client.disconnect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
#
|
||||||
|
# Support for MQTT
|
||||||
|
|
||||||
|
require 'rex/proto/mqtt/client'
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Proto
|
||||||
|
module MQTT
|
||||||
|
DEFAULT_PORT = 1883
|
||||||
|
DEFAULT_SSL_PORT = 8883
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,42 @@
|
||||||
|
# -*- coding: binary -*-
|
||||||
|
|
||||||
|
require 'mqtt'
|
||||||
|
|
||||||
|
##
|
||||||
|
# MQTT protocol support
|
||||||
|
##
|
||||||
|
|
||||||
|
module Rex
|
||||||
|
module Proto
|
||||||
|
module MQTT
|
||||||
|
class Client
|
||||||
|
|
||||||
|
def initialize(sock, opts = {})
|
||||||
|
@sock = sock
|
||||||
|
@opts = opts
|
||||||
|
end
|
||||||
|
|
||||||
|
def connect
|
||||||
|
connect_opts = {
|
||||||
|
client_id: @opts[:client_id],
|
||||||
|
username: @opts[:username],
|
||||||
|
password: @opts[:password]
|
||||||
|
}
|
||||||
|
connect = ::MQTT::Packet::Connect.new(connect_opts).to_s
|
||||||
|
@sock.put(connect)
|
||||||
|
res = @sock.get_once(-1, @opts[:read_timeout])
|
||||||
|
::MQTT::Packet.parse(res)
|
||||||
|
end
|
||||||
|
|
||||||
|
def connect?
|
||||||
|
connect.return_code.zero?
|
||||||
|
end
|
||||||
|
|
||||||
|
def disconnect
|
||||||
|
disconnect = ::MQTT::Packet::Disconnect.new().to_s
|
||||||
|
@sock.put(disconnect)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -123,6 +123,7 @@ Gem::Specification.new do |spec|
|
||||||
# Protocol Libraries
|
# Protocol Libraries
|
||||||
#
|
#
|
||||||
spec.add_runtime_dependency 'dnsruby'
|
spec.add_runtime_dependency 'dnsruby'
|
||||||
|
spec.add_runtime_dependency 'mqtt'
|
||||||
spec.add_runtime_dependency 'net-ssh'
|
spec.add_runtime_dependency 'net-ssh'
|
||||||
spec.add_runtime_dependency 'rbnacl', ['< 5.0.0']
|
spec.add_runtime_dependency 'rbnacl', ['< 5.0.0']
|
||||||
spec.add_runtime_dependency 'bcrypt_pbkdf'
|
spec.add_runtime_dependency 'bcrypt_pbkdf'
|
||||||
|
|
Loading…
Reference in New Issue