Nmap mqtt-subscribe NSE Script


This page contains detailed information about how to use the mqtt-subscribe NSE script. For list of all NSE scripts, visit the Nmap NSE Library.

Select:
Overview
Error Messages

Script Overview


Script source code: https://github.com/nmap/nmap/tree/master/scripts/mqtt-subscribe.nse
Script categories: safe, discovery, version
Target service / protocol: mqtt, secure-mqtt, tcp
Target network port(s): 1883, 8883
List of CVEs: -

Script Description


The mqtt-subscribe.nse script dumps message traffic from MQTT brokers.

This script establishes a connection to an MQTT broker and subscribes to the requested topics. The default topics have been chosen to receive system information and all messages from other clients. This allows Nmap, to listen to all messages being published by clients to the MQTT broker.

For additional information:

Mqtt-subscribe NSE Script Arguments


This is a full list of arguments supported by the mqtt-subscribe.nse script:

mqtt-subscribe.client-id

MQTT client identifier, defaults to nmap with a random suffix.

mqtt-subscribe.listen-msgs

Number of PUBLISH messages to receive, defaults to 100. A value of zero forces this script to stop only when listen-time has passed.

mqtt-subscribe.listen-time

Length of time to listen for PUBLISH messages, defaults to 5s. A value of zero forces this script to stop only when listen-msgs PUBLISH messages have been received.

mqtt-subscribe.password

Password for MQTT brokers requiring authentication.

mqtt-subscribe.protocol-level

MQTT protocol level, defaults to 4.

mqtt-subscribe.protocol-name

MQTT protocol name, defaults to MQTT.

mqtt-subscribe.topic

Topic filters to indicate which PUBLISH messages we'd like to receive.

mqtt-subscribe.username

Username for MQTT brokers requiring authentication.

- - -
To use these script arguments, add them to the Nmap command line using the --script-args arg1=value,[arg2=value,..] syntax. For example:

nmap --script=mqtt-subscribe --script-args mqtt-subscribe.client-id=value,mqtt-subscribe.listen-msgs=value <target>

Mqtt-subscribe NSE Script Example Usage


Here's an example of how to use the mqtt-subscribe.nse script:

nmap -p 1883 --script mqtt-subscribe <target>

Mqtt-subscribe NSE Script Example Output


Here's a sample output from the mqtt-subscribe.nse script:

PORT     STATE SERVICE                 REASON
1883/tcp open  mosquitto version 1.4.8 syn-ack
| mqtt-subscribe:
|   Topics and their most recent payloads:
|     $SYS/broker/load/publish/received/5min: 0.27
|     $SYS/broker/publish/messages/received: 7
|     $SYS/broker/heap/current: 39240
|     $SYS/broker/load/messages/sent/15min: 21.54
|     $SYS/broker/load/bytes/sent/5min: 647.13
|     $SYS/broker/clients/disconnected: 40
|     $SYS/broker/clients/connected: 1
|     $SYS/broker/subscriptions/count: 40
|     $SYS/broker/load/publish/received/15min: 0.46
|     $SYS/broker/clients/inactive: 40
|     $SYS/broker/messages/sent: 2318
|     $SYS/broker/load/publish/sent/1min: 2.48
|     $SYS/broker/load/sockets/1min: 0.09
|     $SYS/broker/load/connections/15min: 0.41
|     $SYS/broker/load/bytes/sent/15min: 822.79
|     $SYS/broker/load/sockets/15min: 0.81
|     $SYS/broker/version: mosquitto version 1.4.8
|     $SYS/broker/load/messages/received/5min: 1.24
|     $SYS/broker/load/publish/sent/15min: 20.39
|     $SYS/broker/uptime: 225478 seconds
|     $SYS/broker/load/publish/received/1min: 0.05
|     $SYS/broker/publish/messages/dropped: 0
|     $SYS/broker/retained messages/count: 47
|     $SYS/broker/messages/received: 293
|     $SYS/broker/load/connections/5min: 0.28
|     $SYS/broker/load/messages/sent/1min: 2.78
|     $SYS/broker/bytes/sent: 83026
|     $SYS/broker/load/bytes/received/5min: 13.98
|     $SYS/broker/load/messages/received/1min: 0.35
|     $SYS/broker/messages/stored: 47
|     $SYS/broker/publish/messages/sent: 2070
|     $SYS/broker/load/sockets/5min: 0.53
|     $SYS/broker/clients/active: 1
|     $SYS/broker/timestamp: Sun, 14 Feb 2016 15:48:26 +0000
|     $SYS/broker/load/bytes/received/15min: 17.83
|     $SYS/broker/publish/bytes/received: 49
|     $SYS/broker/load/publish/sent/5min: 16.03
|     $SYS/broker/publish/bytes/sent: 9752
|     $SYS/broker/load/bytes/sent/1min: 100.49
|     $SYS/broker/load/bytes/received/1min: 2.72
|     $SYS/broker/load/connections/1min: 0.06
|     $SYS/broker/clients/expired: 0
|     $SYS/broker/load/messages/received/15min: 1.49
|     $SYS/broker/load/messages/sent/5min: 17.00
|     $SYS/broker/bytes/received: 2520
|     $SYS/broker/heap/maximum: 41992
|_    $SYS/broker/clients/total: 41

Mqtt-subscribe NSE Script Example XML Output


Here's a sample XML output from the mqtt-subscribe.nse script produced by providing the -oX <file> Nmap option:

 <table key="Topics and their most recent payloads">
   <elem key="$SYS/broker/load/messages/sent/15min">23.48</elem>
   <elem key="$SYS/broker/bytes/received">2469</elem>
   <elem key="$SYS/broker/load/sockets/5min">0.63</elem>
   <elem key="$SYS/broker/messages/sent">2268</elem>
   <elem key="$SYS/broker/load/publish/sent/15min">22.25</elem>
   <elem key="$SYS/broker/load/publish/received/1min">0.05</elem>
   <elem key="$SYS/broker/load/bytes/sent/1min">626.45</elem>
   <elem key="$SYS/broker/publish/messages/received">7</elem>
   <elem key="$SYS/broker/load/connections/15min">0.39</elem>
   <elem key="$SYS/broker/heap/current">38864</elem>
   <elem key="$SYS/broker/load/sockets/1min">0.36</elem>
   <elem key="$SYS/broker/messages/stored">47</elem>
   <elem key="$SYS/broker/load/bytes/sent/15min">897.46</elem>
   <elem key="$SYS/broker/version">mosquitto version 1.4.8</elem>
   <elem key="$SYS/broker/clients/inactive">39</elem>
   <elem key="$SYS/broker/subscriptions/count">39</elem>
   <elem key="$SYS/broker/timestamp">Sun, 14 Feb 2016 15:48:26 +0000</elem>
   <elem key="$SYS/broker/uptime">225280 seconds</elem>
   <elem key="$SYS/broker/publish/bytes/sent">9520</elem>
   <elem key="$SYS/broker/publish/messages/sent">2023</elem>
   <elem key="$SYS/broker/load/bytes/received/1min">10.58</elem>
   <elem key="$SYS/broker/load/connections/5min">0.31</elem>
   <elem key="$SYS/broker/load/messages/received/15min">1.58</elem>
   <elem key="$SYS/broker/publish/messages/dropped">0</elem>
   <elem key="$SYS/broker/clients/connected">1</elem>
   <elem key="$SYS/broker/load/messages/received/5min">1.51</elem>
   <elem key="$SYS/broker/retained messages/count">47</elem>
   <elem key="$SYS/broker/load/bytes/received/15min">18.78</elem>
   <elem key="$SYS/broker/messages/received">289</elem>
   <elem key="$SYS/broker/clients/disconnected">39</elem>
   <elem key="$SYS/broker/load/publish/received/15min">0.46</elem>
   <elem key="$SYS/broker/load/sockets/15min">0.82</elem>
   <elem key="$SYS/broker/load/publish/sent/5min">21.44</elem>
   <elem key="$SYS/broker/bytes/sent">81121</elem>
   <elem key="$SYS/broker/publish/bytes/received">49</elem>
   <elem key="$SYS/broker/load/connections/1min">0.18</elem>
   <elem key="$SYS/broker/load/messages/received/1min">1.45</elem>
   <elem key="$SYS/broker/clients/expired">0</elem>
   <elem key="$SYS/broker/load/publish/received/5min">0.27</elem>
   <elem key="$SYS/broker/load/messages/sent/5min">22.63</elem>
   <elem key="$SYS/broker/load/bytes/received/5min">16.53</elem>
   <elem key="$SYS/broker/load/messages/sent/1min">16.80</elem>
   <elem key="$SYS/broker/clients/total">40</elem>
   <elem key="$SYS/broker/clients/active">1</elem>
   <elem key="$SYS/broker/load/publish/sent/1min">15.57</elem>
   <elem key="$SYS/broker/load/bytes/sent/5min">863.85</elem>
   <elem key="$SYS/broker/heap/maximum">41992</elem>
 </table>

Author


References


See Also


Visit Nmap NSE Library for more scripts.

The mqtt-subscribe.nse script may fail with the following error messages. Check for the possible causes by using the code snippets highlighted below found in the script source code. This can often times help in identifying the root cause of the problem.

protocol-level argument must be a number.


Here is a relevant code snippet related to the "protocol-level argument must be a number." error message:

157:	  local protocol_level = stdnse.get_script_args(SCRIPT_NAME .. '.protocol-level')
158:	  if protocol_level then
159:	    -- Sanity check the value from the user.
160:	    protocol_level = tonumber(protocol_level)
161:	    if type(protocol_level) ~= "number" then
162:	      return false, "protocol-level argument must be a number."
163:	    elseif protocol_level < 0 or protocol_level > 255 then
164:	      return false, "protocol-level argument must be in range between 0 and 255 inclusive."
165:	    end
166:	  else
167:	    -- Indicate to the library that it should choose this on its own.

protocol-level argument must be in range between 0 and 255 inclusive.


Here is a relevant code snippet related to the "protocol-level argument must be in range between 0 and 255 inclusive." error message:

159:	    -- Sanity check the value from the user.
160:	    protocol_level = tonumber(protocol_level)
161:	    if type(protocol_level) ~= "number" then
162:	      return false, "protocol-level argument must be a number."
163:	    elseif protocol_level < 0 or protocol_level > 255 then
164:	      return false, "protocol-level argument must be in range between 0 and 255 inclusive."
165:	    end
166:	  else
167:	    -- Indicate to the library that it should choose this on its own.
168:	    protocol_level = false
169:	  end

protocol-name argument must be a string.


Here is a relevant code snippet related to the "protocol-name argument must be a string." error message:

171:	
172:	  local protocol_name = stdnse.get_script_args(SCRIPT_NAME .. '.protocol-name')
173:	  if protocol_name then
174:	    -- Sanity check the value from the user.
175:	    if type(protocol_name) ~= "string" then
176:	      return false, "protocol-name argument must be a string."
177:	    end
178:	  else
179:	    -- Indicate to the library that it can choose this on its own.
180:	    protocol_name = false
181:	  end

listen-msgs argument must be a number.


Here is a relevant code snippet related to the "listen-msgs argument must be a number." error message:

191:	  local max_msgs = stdnse.get_script_args(SCRIPT_NAME .. '.listen-msgs')
192:	  if max_msgs then
193:	    -- Sanity check the value from the user.
194:	    max_msgs = tonumber(max_msgs)
195:	    if type(max_msgs) ~= "number" then
196:	      return false, "listen-msgs argument must be a number."
197:	    elseif max_msgs < 0 then
198:	      return false, "listen-msgs argument must be non-negative."
199:	    end
200:	  else
201:	    -- Many brokers have ~50 $SYS/# messages, so we double that number

listen-msgs argument must be non-negative.


Here is a relevant code snippet related to the "listen-msgs argument must be non-negative." error message:

193:	    -- Sanity check the value from the user.
194:	    max_msgs = tonumber(max_msgs)
195:	    if type(max_msgs) ~= "number" then
196:	      return false, "listen-msgs argument must be a number."
197:	    elseif max_msgs < 0 then
198:	      return false, "listen-msgs argument must be non-negative."
199:	    end
200:	  else
201:	    -- Many brokers have ~50 $SYS/# messages, so we double that number
202:	    -- for how many messages we'll receive.
203:	    max_msgs = 100

Unable to parse listen-time: %s


Here is a relevant code snippet related to the "Unable to parse listen-time: %s" error message:

208:	  if max_time then
209:	    -- Convert the time specification from the CLI to seconds.
210:	    local err
211:	    max_time, err = stdnse.parse_timespec(max_time)
212:	    if not max_time then
213:	      return false, ("Unable to parse listen-time: %s"):format(err)
214:	    elseif max_time < 0 then
215:	      return false, "listen-time argument must be non-negative."
216:	    elseif args.max_msgs == 0 and max_time == 0 then
217:	      return false, "listen-time and listen-msgs may not both be zero."
218:	    end

listen-time argument must be non-negative.


Here is a relevant code snippet related to the "listen-time argument must be non-negative." error message:

210:	    local err
211:	    max_time, err = stdnse.parse_timespec(max_time)
212:	    if not max_time then
213:	      return false, ("Unable to parse listen-time: %s"):format(err)
214:	    elseif max_time < 0 then
215:	      return false, "listen-time argument must be non-negative."
216:	    elseif args.max_msgs == 0 and max_time == 0 then
217:	      return false, "listen-time and listen-msgs may not both be zero."
218:	    end
219:	  else
220:	    max_time = 5

listen-time and listen-msgs may not both be zero.


Here is a relevant code snippet related to the "listen-time and listen-msgs may not both be zero." error message:

212:	    if not max_time then
213:	      return false, ("Unable to parse listen-time: %s"):format(err)
214:	    elseif max_time < 0 then
215:	      return false, "listen-time argument must be non-negative."
216:	    elseif args.max_msgs == 0 and max_time == 0 then
217:	      return false, "listen-time and listen-msgs may not both be zero."
218:	    end
219:	  else
220:	    max_time = 5
221:	  end
222:	  args.max_time = max_time

A password cannot be given without also giving a username.


Here is a relevant code snippet related to the "A password cannot be given without also giving a username." error message:

229:	
230:	  local password = stdnse.get_script_args(SCRIPT_NAME .. '.password')
231:	  if password then
232:	    -- Sanity check the value from the user.
233:	    if not username then
234:	      return false, "A password cannot be given without also giving a username."
235:	    end
236:	  else
237:	    password = false
238:	  end
239:	  args.password = password

Received control packet type '%s' instead of 'CONNACK'.


Here is a relevant code snippet related to the "Received control packet type '%s' instead of 'CONNACK'." error message:

276:	  })
277:	  if not status then
278:	    output.ERROR = response
279:	    return output, output.ERROR
280:	  elseif response.type ~= "CONNACK" then
281:	    output.ERROR = ("Received control packet type '%s' instead of 'CONNACK'."):format(response.type)
282:	    return output, output.ERROR
283:	  elseif not response.accepted then
284:	    output.ERROR = ("Connection rejected: %s"):format(response.reason)
285:	    return output, output.ERROR
286:	  end

Connection rejected: %s


Here is a relevant code snippet related to the "Connection rejected: %s" error message:

279:	    return output, output.ERROR
280:	  elseif response.type ~= "CONNACK" then
281:	    output.ERROR = ("Received control packet type '%s' instead of 'CONNACK'."):format(response.type)
282:	    return output, output.ERROR
283:	  elseif not response.accepted then
284:	    output.ERROR = ("Connection rejected: %s"):format(response.reason)
285:	    return output, output.ERROR
286:	  end
287:	
288:	  -- Build a list of topic filters.
289:	  local filters = {}

Every topic filter was rejected.


Here is a relevant code snippet related to the "Every topic filter was rejected." error message:

315:	      stdnse.debug3("Topic filter '%s' was rejected.", topic)
316:	    end
317:	  end
318:	
319:	  if not success then
320:	    output.ERROR = "Every topic filter was rejected."
321:	    return output, output.ERROR
322:	  end
323:	
324:	  -- We are now in a position to receive PUBLISH messages for at least
325:	  -- one of our topic filters. We will record the topic of every

Received error while listening for PUBLISH messages: %s


Here is a relevant code snippet related to the "Received error while listening for PUBLISH messages: %s" error message:

363:	
364:	  -- We're not going to error out if the last response was an error if
365:	  -- there were successful responses before it, but we will log it.
366:	  if not status then
367:	    if #keys > 0 then
368:	      stdnse.debug3("Received error while listening for PUBLISH messages: %s", response)
369:	    else
370:	      output.ERROR = response
371:	      return output, output.ERROR
372:	    end
373:	  end

Version


This page has been created based on Nmap version 7.92.

Go back to menu.