remmons-r7 (21)

Last Login: June 14, 2024
Assessments
5
Score
21

remmons-r7's Latest (5) Contributions

Sort by:
Filter by:
3
Ratings
  • Attacker Value
    Medium
  • Exploitability
    Low
Technical Analysis

This deserialization vulnerability piqued my interest after I saw it had received a “patch reissue” a couple of weeks after it was initially patched. I was curious whether the secondary patch was necessary or more of a prophylactic measure. Due to time and software limitations, this assessment doesn’t include PoC and is mostly based on static analysis; the primary goal of this is to provide more information about the risk of the vulnerability, as well as to document some information I’ve learned about the suite for researchers.

Software Overview

CVE-2024-29212 targets Veeam Service Provider Console (“VSPC”), which is a rather niche product. From what I’ve learned, it’s exclusively meant for managed service providers that resell Veeam “backups as a service”. Despite not managing the Veeam infrastructure themselves, clients of these service providers still prefer having their own dashboard for backups. In that scenario, the service provider would set up VSPC and its bundled Web UI as an interface for those customers to manage backups and transmit their data to the centralized server.

VSPC itself, which is predominantly written in C# .NET, is fairly complex, with many different services and communication channels. The ecosystem is primarily hosted by the service provider, and agent software continuously runs on the customer’s managed systems. As shown in the diagram linked above, the client agent connects to the Veeam Cloud Gateway intermediary service via TCP port 6180. In turn, the Gateway service communicates this data to the Veeam Service Provider Console Server (“VSPC Server”) over port 9999. VSPC Server also receives TCP data on port 1989 from the dedicated Web UI service back end, and the front-facing Web UI service listens on port 1280.

Exploitation Potential

The public attack surface for this specialized Veeam product appears to be minimal, based on Shodan queries; less than 100 VSPC Web UI servers were observed to be public-facing at the time of research. The vulnerability itself is also noted to be authenticated, which further lessens the likelihood of exploitation. Analysis appears to indicate that an attacker would need to acquire agent credentials from a managed system’s client to target the service provider’s VSPC system with a serialized payload. As a result, and considering the fact that this vulnerability was patched a few months back, CVE-2024-29212 appears to be at lower risk of widespread exploitation.

Patch Analysis

The most obvious security-related changes in the first patch are in a SerializationBinder class, BinarySerializerVulnerabilityFilter, within the BindToType method. This method is called during deserialization, and it sources the resulting object’s type from the data passed to it. The unpatched code is shown below. It includes a security check that throws an exception if the target assembly is a forbidden type AND the assembly name does not contain the string “Veeam”.

	public override Type BindToType(string assemblyName, string typeName)
	{
		int num = typeName.IndexOf(",", StringComparison.Ordinal);
		if (num > 0)
		{
			typeName = typeName.Substring(0, num);
		}
		if (!assemblyName.ContainsIgnoreCase("Veeam") && _forbiddenTypes.Any((string t) => typeName.EndsWith(t, StringComparison.OrdinalIgnoreCase)))
		{
			throw new ArgumentException("Deserialization of type " + typeName + " is prohibited.");
		}
		return _wrappedBinder?.BindToType(assemblyName, typeName);
	}

The _forbiddenTypes list, which was not changed, is as follows:
"AxHost+State", "DelegateSerializationHolder", "DataSet", "PSObject", "ResourceSet", "RolePrincipal", "SessionSecurityToken", "SessionViewStateHistoryItem", TextFormattingRunProperties", "WindowsClaimsIdentity", "WindowsIdentity", "ClaimsIdentity", "DataTable", "ObjRef", "ToolboxItemContainer".

The first of the two patches improved BindToType to remove the “Veeam” string allowlisting. This, and the lack of new forbidden entries, seems to indicate that the string “Veeam” is leveraged by the exploit’s serialized payload to take advantage of the string exclusion. There’s also a call to Type.GetType, though it’s unclear what purpose it serves in the initial patch.

	public override Type BindToType(string assemblyName, string typeName)
	{
		int num = typeName.IndexOf(",", StringComparison.Ordinal);
		if (num > 0)
		{
			typeName = typeName.Substring(0, num);
		}
		if (Array.Exists(_forbiddenTypes, (string t) => typeName.EndsWith(t, StringComparison.OrdinalIgnoreCase)))
		{
			throw new ArgumentException("Deserialization of type " + typeName + " is prohibited.");
		}
		Type.GetType(typeName + ", " + assemblyName);
		return _wrappedBinder?.BindToType(assemblyName, typeName);
	}

Next, we’ll take a look at the content of the “patch reissue”. In this example, Type.GetType is now used by the fullName variable, which is then used to check more comprehensively for forbidden types. This improved function also verifies that fullName is not null. Notably, the exception being thrown also now includes a debugging message that prints how typeName was parsed. This seems to indicate that the first patch may have been bypassed by confusing the parser.

	public override Type BindToType(string assemblyName, string typeName)
	{
		string fullName = Type.GetType(typeName + ", " + assemblyName)?.FullName;
		if (fullName == null || Array.Exists(_forbiddenTypes, (string t) => fullName.EndsWith(t, StringComparison.OrdinalIgnoreCase)))
		{
			throw new ArgumentException("Deserialization of type '" + typeName + "' (parsed as '" + fullName + "') is prohibited.");
		}
		return _wrappedBinder?.BindToType(assemblyName, typeName);
	}

Based on the content of the secondary patch, it seems likely it was implemented in response to a patch bypass, not just to use Type.GetType and harden the application. The excellent CODE WHITE research linked above outlines some .NET type parsing quirks when using serialization binders, which is probably the kind of thing this patch is trying to harden against.

The filter outlined above is referenced only by Veeam.MBP.AgentManager\Veeam.AC.AgentManagement\ReceiverWrapper.cs, where it’s used within SetupSerializationBinder and scoped for ChannelHostReceiver and MultiplexedStreamReceiver receiver types.

private void SetupSerializationBinder(ChannelHostReceiver receiver)
{
	if (receiver.MessageSerializer is NetBinarySerializer netBinarySerializer)
	{
		netBinarySerializer.CustomSerializationBinder = BinarySerializerVulnerabilityFilter.Wrap(netBinarySerializer.CustomSerializationBinder);
	}
}

private void SetupSerializationBinder(MultiplexedStreamReceiver receiver)
{
	if (receiver.MessageSerializer is NetBinarySerializer netBinarySerializer)
	{
		netBinarySerializer.CustomSerializationBinder = BinarySerializerVulnerabilityFilter.Wrap(netBinarySerializer.CustomSerializationBinder);
	}
}

The first patch also included a handful of changes in various areas of the code base that return early if entity nodes of the type BackupObject are encountered. For example, within Veeam.MBP.EntityImpl\Veeam.MBP.EntityImpl.EntityExtension\DataModelEntityExtension.cs, the application now checks if entities are of the type BackupObject before updating and adding child nodes.

	public static void UpdateTraverse<T>(this T entity, T newEntity) where T : EntityDataModelDbNode
	{
+		if (entity is BackupObject)
+		{
+			return;
+		}
		if (entity == null)
		{
			throw new ArgumentNullException("entity");
		}
		try
		{
			UpdateCurrentNode(entity, newEntity);
			AddOrUpdateChildNodes(entity, newEntity);
		}
		catch (Exception e)
		{
			Log.Error(e);
			throw;
		}
	}

[..]

	private static void AddOrUpdateChildNodes<T>(T oldEntity, T newEntity) where T : EntityDataModelDbNode
	{
		List<BaseEntity> childEntitiesClone = newEntity.ChildEntitiesClone;
		IDictionary<string, EntityDataModelDbNode> dictionary = childEntitiesClone.OfType<EntityDataModelDbNode>().DistinctBySystemNameToDictionary();
		foreach (EntityDataModelDbNode oldChild in oldEntity.ChildEntitiesClone.OfType<EntityDataModelDbNode>())
		{
+			if (oldChild is BackupObject)
+			{
+				continue;
+			}
			if (dictionary.TryGetValue(oldChild.SystemName, out var value))
			{
				dictionary.Remove(oldChild.SystemName);
				oldChild.UpdateTraverse(value);
				continue;
			}
			bool alwaysAlive = oldChild.GetTypeSystemName().AlwaysAlive;
			bool flag = childEntitiesClone.Any((BaseEntity a) => a.GetType() == oldChild.GetType());
			if (!alwaysAlive || flag)
			{
				oldChild.Delete();
			}
		}
		foreach (KeyValuePair<string, EntityDataModelDbNode> item in dictionary)
		{
			EntityDataModelDbNode value2 = item.Value;
			Log.Verbose("{0} was added", value2.SystemName);
			value2.CloneNode(oldEntity);
		}
	}

Summarizing Exploitation

Based on what we’ve seen in static analysis, the exploitation flow probably looks something like this:

  • Authenticate to the server as a client or hijack an existing authenticated agent connection.
  • Target the backup server (managed by the provider) with a serialized payload, scoped to be handled by the receiver’s custom BinarySerializerVulnerabilityFilter. VSPC Server deserializes client-provided data in a number of different places and relies on the filtering to catch unsafe types, so there are likely multiple possible deserialization sinks.
  • Before the first patch, the serialized payload’s type will likely contain the string “Veeam” and be related to the BackupObject type.
  • After the second patch, if exploitation is still viable, exploit attempts will likely attempt to confuse .NET type name parsing to get a malicious object deserialized.

Interacting with VSPC Server

As an addendum, though most of this analysis is based on static code review, I also want to summarize some information I’ve learned about the VSPC communication protocol for TCP ports 1989 and 9999. When VSPC Server receives a new connection from the client, it expects two bytes, a Veeam “type” byte and a “version” byte, followed by some XML data with the XML string length prepended as a 7-bit integer. The XML object, which should be a Connector for the first interaction, can specify a connectTo receiver, as well as a gate to interact with. For example, opening a new channel can be performed by decoding and sending the following data to port 1989.

AgXTAQo8Q29ubmVjdG9yPgo8Y29ubmVjdFRvIHJlY2VpdmVyPSJSZWNlaXZlclY0Ij4KPGdhdGUgbmFtZT
0iQXV0aGVudGljYXRlZCIgdGltZW91dD0iMTIwMDAwIi8+CjwvY29ubmVjdFRvPgo8ZW5kcG9pbnQ+Cjx2
ZXJzaW9uPjU8L3ZlcnNpb24+CjwvZW5kcG9pbnQ+Cjxjb25uZWN0aW9uVHlwZT5Ob3JtYWw8L2Nvbm5lY3
Rpb25UeXBlPgo8ZGF0YS8+CjwvQ29ubmVjdG9yPgo

Decoded, the XML string included above defines an XML Connector object, which specifies a ReceiverV4 receiver for post-authenticated interactions. This type seems to be affiliated with ReceiverWrapper, which is the class that sets up the custom serialization filter that was patched.

<Connector>
<connectTo receiver="ReceiverV4">
<gate name="Authenticated" timeout="120000"/>
</connectTo>
<endpoint>
<version>5</version>
</endpoint>
<connectionType>Normal</connectionType>
<data/>
</Connector>

With a new connection open, the server should return a response containing a GUID for a new channel.

<Response status="Ok"><attributes><attr name="channelId" value="f9f1ab9c-b78f-46ed-b28b-be6b012e0afd" /><attr name="protocolVersion" value="5" /></attributes></Response>

The server will then upgrade the unencrypted connection to an encrypted connection and perform a handshake and authentication flow.

3
Ratings
Technical Analysis

So far, 2024 has seen a few notable vulnerabilities, such as CVE-2024-1709, that attack setup wizard flows for authentication bypass. This vulnerability, discovered by researcher Sina Kheirkhah, falls into the same group. By exploiting an access control vulnerability in the administrator setup wizard, unauthenticated attackers gain high-privileged access to Telerik Report Server. With the newly-acquired administrator account, another new Report Server vulnerability, tracked as CVE-2024-1800, can be leveraged for remote code execution on the host system.

Exploitation

The initial administrator setup code in Telerik.ReportServer.Web.dll!Telerik.ReportServer.Web.Controllers.StartupController.Register does not check if setup has already been completed. As a result, the attacker can manually perform the web request to create a new administrator account. Per Sina’s public proof of concept, the authentication bypass vulnerability can be exploited with a single request:
curl 'http://TARGET_HERE/Startup/Register' -d 'Username=USERNAME_HERE&Password=PASSWORD_HERE&ConfirmPassword=PASSWORD_HERE&Email=backdoor%40admin.com&FirstName=backdoor&LastName=user'

Public Exposure

It’s worth mentioning that Shodan only appears to return a few hundred public-facing Telerik Report Server instances. However, due to the unauthenticated RCE impact, organizations running the Report Server would be wise to patch with urgency. The Progress Knowledge Base contains guidance on how to remediate this vulnerability.

3
Ratings
Technical Analysis

On May 28, 2024, Check Point published an advisory for an unauthenticated information disclosure vulnerability affecting Check Point Security Gateway devices configured with either the “IPSec VPN” or “Mobile Access” software blade. This vulnerability was stated as being a vulnerability impacting devices with password-only authentication enabled on some accounts. However, upon analysis, CVE-2024-24919 was discovered to be an unauthenticated arbitrary file read as root. Though attackers may steal credential files to crack account password hashes, CVE-2024-24919 also impacts systems that are not configured for password-only authentication.

This vulnerability should be urgently addressed by anyone running a Check Point Security Gateway with the IPSec VPN or Mobile Access blades enabled. Additionally, organizations should reference the Rapid7 blog post for this vulnerability for remediation and detection recommendations. As of May 30, 2024, CVE-2024-24919 has been added to CISA’s KEV catalog.

4
Ratings
Technical Analysis

CVE-2024-4040 was discovered by Simon Garrelou, of Airbus CERT, and it’s a server-side template injection vulnerability for the CrushFTP managed file transfer suite. The vulnerability was reported to CrushFTP on Friday, April 19, 2024. That same day, it was patched and announced via the vendor’s security mailing list, though a CVE wasn’t assigned until Monday, April 22, 2024. The vulnerability impact is primarily unauthenticated arbitrary high-privilege file disclosure, and it can result in full compromise of CrushFTP instances via multiple paths. Additionally, Rapid7 has confirmed that it’s possible to establish remote code execution as a result of the file disclosure primitive.

Anyone running CrushFTP should patch with urgency. When the patch is applied, check for the IOCs outlined in the official Rapid7 analysis to identify any prior successful exploitation. As noted in the analysis, defenders should be aware that exploitation may be masked in logs via mangled exploit web requests.

3
Ratings
Technical Analysis

CVE-2024-3400, which is technically a chain of two vulnerabilities, is an unauthenticated remote code execution exploit for software with a broad public attack surface. This vulnerability was discovered when it was used by a suspected nation state actor in the wild for initial access; needless to say, this is a bad one. Though some early communication indicated that turning off telemetry or enforcing threat signature detection might prevent exploitation, patching PAN-OS is necessary. Remediation of CVE-2024-3400 should be a high priority for organizations. When patches are applied, check for the IOCs outlined in the official Rapid7 analysis to identify any prior successful exploitation.