This is an automated email from the ASF dual-hosted git repository. havret pushed a commit to branch AMQNET-849 in repository https://gitbox.apache.org/repos/asf/activemq-nms-amqp.git
commit 8d152cd3234fc8ab157ff1e4f13fbf54321344b2 Author: Havret <[email protected]> AuthorDate: Wed Jun 25 00:26:48 2025 +0200 AMQNET-849 Allow, deny types fix --- .../Policies/NmsDefaultDeserializationPolicy.cs | 4 +- .../Provider/Amqp/Message/TrustedClassFilter.cs | 7 ++- .../Apache-NMS-AMQP-Interop-Test.csproj | 2 + .../NmsMessageConsumerTest.cs | 61 +++++++++++++++++++++- 4 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/NMS.AMQP/Policies/NmsDefaultDeserializationPolicy.cs b/src/NMS.AMQP/Policies/NmsDefaultDeserializationPolicy.cs index 76d2d51..5d37690 100644 --- a/src/NMS.AMQP/Policies/NmsDefaultDeserializationPolicy.cs +++ b/src/NMS.AMQP/Policies/NmsDefaultDeserializationPolicy.cs @@ -48,10 +48,10 @@ namespace Apache.NMS.AMQP.Policies public bool IsTrustedType(IDestination destination, Type type) { - var typeName = type?.FullName; + 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 07a722b..0402028 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 @@ -21,6 +21,7 @@ under the License. <RootNamespace>NMS.AMQP.Test</RootNamespace> <AssemblyName>NMS.AMQP.Interop.Test</AssemblyName> <LangVersion>7.3</LangVersion> + <EnableUnsafeBinaryFormatterSerialization>true</EnableUnsafeBinaryFormatterSerialization> </PropertyGroup> <ItemGroup> @@ -29,6 +30,7 @@ under the License. <PackageReference Include="NUnit" Version="3.12.0" /> <PackageReference Include="NUnit.Console" Version="3.10.0" /> <PackageReference Include="NUnit3TestAdapter" Version="3.13.0" /> + <PackageReference Include="System.Runtime.Serialization.Formatters" Version="9.0.6" /> </ItemGroup> <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) --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected] For further information, visit: https://activemq.apache.org/contact
