This is an automated email from the ASF dual-hosted git repository.
havret pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-nms-amqp.git
The following commit(s) were added to refs/heads/main by this push:
new 2df35c5 AMQNET-849 Allow, deny types fix
2df35c5 is described below
commit 2df35c5b50a8dfb352a54b5c2f05d9b771764c57
Author: Havret <[email protected]>
AuthorDate: Wed Jun 25 00:26:48 2025 +0200
AMQNET-849 Allow, deny types fix
---
.../Policies/NmsDefaultDeserializationPolicy.cs | 6 +--
.../Provider/Amqp/Message/TrustedClassFilter.cs | 7 ++-
.../Apache-NMS-AMQP-Interop-Test.csproj | 1 +
.../NmsMessageConsumerTest.cs | 61 +++++++++++++++++++++-
.../NmsDefaultDeserializationPolicyTest.cs | 6 +--
5 files changed, 73 insertions(+), 8 deletions(-)
diff --git a/src/NMS.AMQP/Policies/NmsDefaultDeserializationPolicy.cs
b/src/NMS.AMQP/Policies/NmsDefaultDeserializationPolicy.cs
index 76d2d51..427be8c 100644
--- a/src/NMS.AMQP/Policies/NmsDefaultDeserializationPolicy.cs
+++ b/src/NMS.AMQP/Policies/NmsDefaultDeserializationPolicy.cs
@@ -43,15 +43,15 @@ namespace Apache.NMS.AMQP.Policies
/// </summary>
public const string CATCH_ALL_WILDCARD = "*";
- private IReadOnlyList<string> denyList = Array.Empty<string>();
- private IReadOnlyList<string> allowList = new[] { CATCH_ALL_WILDCARD };
+ private IReadOnlyList<string> denyList = [];
+ private IReadOnlyList<string> allowList = [CATCH_ALL_WILDCARD];
public bool IsTrustedType(IDestination destination, Type type)
{
var typeName = type?.FullName;
if (typeName == null)
{
- return true;
+ return false;
}
foreach (var denyListEntry in denyList)
diff --git a/src/NMS.AMQP/Provider/Amqp/Message/TrustedClassFilter.cs
b/src/NMS.AMQP/Provider/Amqp/Message/TrustedClassFilter.cs
index c761487..ae5200f 100644
--- a/src/NMS.AMQP/Provider/Amqp/Message/TrustedClassFilter.cs
+++ b/src/NMS.AMQP/Provider/Amqp/Message/TrustedClassFilter.cs
@@ -38,12 +38,17 @@ namespace Apache.NMS.AMQP.Provider.Amqp.Message
var name = new AssemblyName(assemblyName);
var assembly = Assembly.Load(name);
var type = FormatterServices.GetTypeFromAssembly(assembly,
typeName);
+ if (type == null)
+ {
+ throw new SerializationException($"Type {typeName} not found
in assembly {assemblyName}");
+ }
+
if (deserializationPolicy.IsTrustedType(destination, type))
{
return type;
}
- var message = $"Forbidden {type.FullName}! " +
+ var message = $"Forbidden {type.FullName ?? typeName}! " +
"This type is not trusted to be deserialized under
the current configuration. " +
"Please refer to the documentation for more
information on how to configure trusted types.";
throw new SerializationException(message);
diff --git
a/test/Apache-NMS-AMQP-Interop-Test/Apache-NMS-AMQP-Interop-Test.csproj
b/test/Apache-NMS-AMQP-Interop-Test/Apache-NMS-AMQP-Interop-Test.csproj
index 6c23620..f43f06d 100644
--- a/test/Apache-NMS-AMQP-Interop-Test/Apache-NMS-AMQP-Interop-Test.csproj
+++ b/test/Apache-NMS-AMQP-Interop-Test/Apache-NMS-AMQP-Interop-Test.csproj
@@ -19,6 +19,7 @@ under the License.
<RootNamespace>NMS.AMQP.Test</RootNamespace>
<AssemblyName>NMS.AMQP.Interop.Test</AssemblyName>
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>
+<!--
<EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization>-->
</PropertyGroup>
<ItemGroup>
diff --git a/test/Apache-NMS-AMQP-Interop-Test/NmsMessageConsumerTest.cs
b/test/Apache-NMS-AMQP-Interop-Test/NmsMessageConsumerTest.cs
index ff60deb..381c45a 100644
--- a/test/Apache-NMS-AMQP-Interop-Test/NmsMessageConsumerTest.cs
+++ b/test/Apache-NMS-AMQP-Interop-Test/NmsMessageConsumerTest.cs
@@ -60,7 +60,6 @@ namespace NMS.AMQP.Test
Assert.IsNull(messageConsumer.Receive(TimeSpan.FromSeconds(1)));
messageConsumer.Close();
-
}
[Test, Timeout(60_000)]
@@ -435,6 +434,33 @@ namespace NMS.AMQP.Test
_ = objectMessage.Body;
});
}
+
+ //
https://codewhitesec.blogspot.com/2022/06/bypassing-dotnet-serialization-binders.html
+ [Test, Timeout(20_000)]
+ public void TestShouldNotDeserializeMaliciousType()
+ {
+ Connection = CreateAmqpConnection(configureConnectionFactory:
factory =>
+ {
+ factory.DeserializationPolicy = new
CustomDeserializationPolicy();
+ });
+
+ Connection.Start();
+ var session =
Connection.CreateSession(AcknowledgementMode.AutoAcknowledge);
+ var queue = session.GetQueue(Guid.NewGuid().ToString());
+ var consumer = session.CreateConsumer(queue);
+ var producer = session.CreateProducer(queue);
+
+ var message = producer.CreateObjectMessage(new
MaliciousSerializable());
+ producer.Send(message);
+
+ var receivedMessage = consumer.Receive();
+ var objectMessage = receivedMessage as IObjectMessage;
+ Assert.NotNull(objectMessage);
+ Assert.Throws<SerializationException>(() =>
+ {
+ _ = objectMessage.Body;
+ });
+ }
}
[Serializable]
@@ -443,6 +469,39 @@ namespace NMS.AMQP.Test
public string Prop1 { get; set; }
}
+ [Serializable]
+ public class TrustedType
+ {
+ // ReSharper disable once UnusedMember.Global
+ public string Prop1 { get; set; }
+ }
+
+ [Serializable]
+ public class MaliciousSerializable : ISerializable
+ {
+ private readonly string _payloadData = "Injected Payload";
+
+ public MaliciousSerializable() { }
+
+ protected MaliciousSerializable(SerializationInfo info,
StreamingContext context)
+ {
+ _payloadData = info.GetString("InjectedValue");
+ }
+
+ public void GetObjectData(SerializationInfo info, StreamingContext
context)
+ {
+ Type type = typeof(TrustedType);
+
+ // Manipulate serialization info to trick deserialization
+ info.SetType(type);
+ info.FullTypeName = type.AssemblyQualifiedName; // This should
result in null
+ info.AssemblyName = "mscorlib, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089";
+
+ // Inject a fake property
+ info.AddValue("InjectedValue", _payloadData);
+ }
+ }
+
public class CustomDeserializationPolicy : INmsDeserializationPolicy
{
public bool IsTrustedType(IDestination destination, Type type)
diff --git
a/test/Apache-NMS-AMQP-Test/Policies/NmsDefaultDeserializationPolicyTest.cs
b/test/Apache-NMS-AMQP-Test/Policies/NmsDefaultDeserializationPolicyTest.cs
index 33645b1..207515f 100644
--- a/test/Apache-NMS-AMQP-Test/Policies/NmsDefaultDeserializationPolicyTest.cs
+++ b/test/Apache-NMS-AMQP-Test/Policies/NmsDefaultDeserializationPolicyTest.cs
@@ -31,7 +31,7 @@ namespace NMS.AMQP.Test.Policies
var destination = new NmsQueue("test-queue");
var policy = new NmsDefaultDeserializationPolicy();
- Assert.True(policy.IsTrustedType(destination, null));
+ Assert.False(policy.IsTrustedType(destination, null));
Assert.True(policy.IsTrustedType(destination, typeof(Guid)));
Assert.True(policy.IsTrustedType(destination, typeof(string)));
Assert.True(policy.IsTrustedType(destination, typeof(bool)));
@@ -40,7 +40,7 @@ namespace NMS.AMQP.Test.Policies
// Only types in System
policy.AllowList = "System";
- Assert.True(policy.IsTrustedType(destination, null));
+ Assert.False(policy.IsTrustedType(destination, null));
Assert.True(policy.IsTrustedType(destination, typeof(Guid)));
Assert.True(policy.IsTrustedType(destination, typeof(string)));
Assert.True(policy.IsTrustedType(destination, typeof(bool)));
@@ -50,7 +50,7 @@ namespace NMS.AMQP.Test.Policies
// Entry must be complete namespace name prefix to match
// i.e. while "System.C" is a prefix of "System.Collections", this
- // wont match the Queue class below.
+ // won't match the Queue class below.
policy.AllowList = "System.C";
Assert.False(policy.IsTrustedType(destination, typeof(Guid)));
Assert.False(policy.IsTrustedType(destination, typeof(string)));
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
For further information, visit: https://activemq.apache.org/contact