CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/lib/metasploit/framework/login_scanner/bavision_cameras.rb
Views: 1904
require 'metasploit/framework/login_scanner/http'1require 'digest'23module Metasploit4module Framework5module LoginScanner67class BavisionCamerasException < StandardError; end89class BavisionCameras < HTTP1011DEFAULT_PORT = 8012PRIVATE_TYPES = [ :password ]13LOGIN_STATUS = Metasploit::Model::Login::Status # Shorter name141516# Checks if the target is BAVision Camera's web server. The login module should call this.17#18# @return [String] Error message if target is not a BAVision camera, otherwise FalseClass19def check_setup20login_uri = normalize_uri("#{uri}")21res = send_request({'uri'=> login_uri})2223unless res && res.headers['WWW-Authenticate'] && res.headers['WWW-Authenticate'].match(/realm="IPCamera Login"/)24return "Unable to locate \"realm=IPCamera Login\" in headers. (Is this really a BAVision camera?)"25end2627false28end293031# Auth to the server using digest auth32def try_digest_auth(cred)33login_uri = normalize_uri("#{uri}")34res = send_request({35'uri' => login_uri,36'credential' => cred,37'DigestAuthIIS' => false,38'headers' => {'Accept'=> '*/*'}39})4041digest = digest_auth(cred.public, cred.private, res.headers)4243res = send_request({44'uri' => login_uri,45'headers' => {46'Authorization' => digest47}})4849if res && res.code == 200 && res.body =~ /hy\-cgi\/user\.cgi/50return {:status => LOGIN_STATUS::SUCCESSFUL, :proof => res.body}51end5253{:status => LOGIN_STATUS::INCORRECT, :proof => res.body}54end5556# The Rex HTTP Digest auth is making the camera server to refuse to respond for some reason.57# The API also fails to generate the CNONCE parameter (bug), which makes it unsuitable for58# our needs, therefore we have our own implementation of digest auth.59def digest_auth(user, password, response)60nonce_count = 161cnonce = Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))6263i = (response['www-authenticate'] =~ /^(\w+) (.*)/)6465# The www-authenticate header does not return in the format we like,66# so let's bail.67unless i68raise BavisionCamerasException, 'www-authenticate header is not in the right format'69end7071params = {}72$2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }7374a_1 = "#{user}:#{params['realm']}:#{password}"75a_2 = "GET:#{uri}"76request_digest = ''77request_digest << Digest::MD5.hexdigest(a_1)78request_digest << ':' << params['nonce']79request_digest << ':' << ('%08x' % nonce_count)80request_digest << ':' << cnonce81request_digest << ':' << params['qop']82request_digest << ':' << Digest::MD5.hexdigest(a_2)8384header = []85header << "Digest username=\"#{user}\""86header << "realm=\"#{params['realm']}\""87header << "qop=#{params['qop']}"88header << "uri=\"/\""89header << "nonce=\"#{params['nonce']}\""90header << "nc=#{'%08x' % nonce_count}"91header << "cnonce=\"#{cnonce}\""92header << "response=\"#{Digest::MD5.hexdigest(request_digest)}\""9394header * ', '95end969798# Attempts to login to the camera. This is called first.99#100# @param credential [Metasploit::Framework::Credential] The credential object101# @return [Result] A Result object indicating success or failure102def attempt_login(credential)103result_opts = {104credential: credential,105status: Metasploit::Model::Login::Status::INCORRECT,106proof: nil,107host: host,108port: port,109protocol: 'tcp'110}111112begin113result_opts.merge!(try_digest_auth(credential))114rescue ::Rex::ConnectionError, BavisionCamerasException => e115# Something went wrong during login. 'e' knows what's up.116result_opts.merge!(status: LOGIN_STATUS::UNABLE_TO_CONNECT, proof: e.message)117end118119Result.new(result_opts)120end121122end123end124end125end126127128129