Skip to content

Commit

Permalink
Fix disallow-unsafe-type Akka.NET settings and harden unsafe type det…
Browse files Browse the repository at this point in the history
…ection (#301)

* Fix disallow-unsafe-type Akka.NET settings and harden unsafe type detection

* Fix linux validation to ignore NetFX

* Fix build script

* Fix build script

* Fix build script

* Update linux vmimage

* Embed NetFX .dlls in test project

* Fix build script
  • Loading branch information
Arkatufus authored Mar 23, 2022
1 parent 6486308 commit 82f3347
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 19 deletions.
15 changes: 12 additions & 3 deletions build-system/pr-validation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,19 @@ jobs:
vmImage: 'windows-2019'
scriptFileName: build.cmd
scriptArgs: all

- template: azure-pipeline.template.yaml
parameters:
name: 'linux_pr'
displayName: 'Linux PR Validation'
name: 'linux_pr_net_core'
displayName: 'Linux PR Validation (netcoreapp3.1)'
vmImage: 'ubuntu-16.04'
scriptFileName: ./build.sh
scriptArgs: all
scriptArgs: runTestsNetCore

- template: azure-pipeline.template.yaml
parameters:
name: 'linux_pr_net_5'
displayName: 'Linux PR Validation (net5.0)'
vmImage: 'ubuntu-16.04'
scriptFileName: ./build.sh
scriptArgs: runTestsNet
15 changes: 12 additions & 3 deletions build-system/windows-pr-validation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,19 @@ jobs:
vmImage: 'windows-2019'
scriptFileName: build.cmd
scriptArgs: all

- template: azure-pipeline.template.yaml
parameters:
name: 'linux_pr'
displayName: 'Linux PR Validation'
name: 'linux_pr_net_core'
displayName: 'Linux PR Validation (netcoreapp3.1)'
vmImage: 'ubuntu-18.04'
scriptFileName: ./build.sh
scriptArgs: all
scriptArgs: runTestsNetCore

- template: azure-pipeline.template.yaml
parameters:
name: 'linux_pr_net_5'
displayName: 'Linux PR Validation (net5.0)'
vmImage: 'ubuntu-18.04'
scriptFileName: ./build.sh
scriptArgs: runTestsNet
2 changes: 2 additions & 0 deletions build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ Target "Clean" (fun _ ->

CleanDirs !! "./**/bin"
CleanDirs !! "./**/obj"

CreateDir "bin/nuget"
)

Target "AssemblyInfo" (fun _ ->
Expand Down
73 changes: 73 additions & 0 deletions src/Hyperion.Akka.Integration.Tests/IntegrationSpec.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security.Claims;
using System.Security.Principal;
using System.Threading.Tasks;
using Akka.Actor;
using Akka.Configuration;
using Akka.Serialization;
using Xunit;
using Akka.TestKit;
using Akka.TestKit.Xunit2;
using FluentAssertions;
using Hyperion.Internal;
using Xunit.Abstractions;
using AkkaSerializer = Akka.Serialization.Serializer;

Expand Down Expand Up @@ -72,6 +80,71 @@ public void Bugfix263_Akka_HyperionSerializer_should_serialize_ActorPath_list()
deserialized.Destinations[0].Should().Be(deserialized.Destinations[1]);
}

[Fact]
public async Task CanDeserializeANaughtyTypeWhenAllowed()
{
var config = ConfigurationFactory.ParseString(@"
akka {
serialize-messages = on
actor {
serializers {
hyperion = ""Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion""
}
serialization-bindings {
""System.Object"" = hyperion
}
serialization-settings.hyperion.disallow-unsafe-type = false
}
}");
var system = ActorSystem.Create("unsafeSystem", config);

try
{
var serializer = system.Serialization.FindSerializerForType(typeof(DirectoryInfo));
var di = new DirectoryInfo(@"c:\");

var serialized = serializer.ToBinary(di);
var deserialized = serializer.FromBinary<DirectoryInfo>(serialized);
}
finally
{
await system.Terminate();
}
}

[Fact]
public async Task CantDeserializeANaughtyTypeByDefault()
{
var config = ConfigurationFactory.ParseString(@"
akka {
serialize-messages = on
actor {
serializers {
hyperion = ""Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion""
}
serialization-bindings {
""System.Object"" = hyperion
}
serialization-settings.hyperion.disallow-unsafe-type = true # this is the default value
}
}");
var system = ActorSystem.Create("unsafeSystem", config);

try
{
var serializer = system.Serialization.FindSerializerForType(typeof(DirectoryInfo));
var di = new DirectoryInfo(@"c:\");

var serialized = serializer.ToBinary(di);
var ex = Assert.Throws<SerializationException>(() => serializer.FromBinary<DirectoryInfo>(serialized));
ex.InnerException.Should().BeOfType<EvilDeserializationException>();
}
finally
{
await system.Terminate();
}
}

private class MyActor: ReceiveActor
{

Expand Down
45 changes: 41 additions & 4 deletions src/Hyperion.Tests/Hyperion.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,54 @@
<DefineConstants>$(DefineConstants);NETFX</DefineConstants>
</PropertyGroup>


<ItemGroup Condition="'$(TargetFramework)' == '$(NetFrameworkTestVersion)'">
<Reference Include="System.Drawing">
<Private>true</Private>
</Reference>
<Reference Include="System.Web">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
<Reference Include="System.Web.Mobile">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
<Reference Include="System.Windows.Forms">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
<Reference Include="PresentationFramework">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
<Reference Include="Microsoft.VisualStudio.Text.UI.Wpf">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
<Reference Include="System.Drawing.Design">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
<Reference Include="System.Drawing">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
<Reference Include="System.IdentityModel">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
<Reference Include="System.Activities.Presentation">
<HintPath>./lib</HintPath>
<Private>true</Private>
</Reference>
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' != '$(NetFrameworkTestVersion)'">
<PackageReference Include="System.Management.Automation" Version="6.2.7" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="$(FluentAssertionsVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" />
<PackageReference Include="xunit" Version="$(XunitVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitRunnerVersion)" />
</ItemGroup>
Expand Down
90 changes: 88 additions & 2 deletions src/Hyperion.Tests/UnsafeDeserializationExclusionTests.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
using System;
using System.Collections.Generic;
using System.IO;
using Hyperion.Extensions;
using System.Runtime.InteropServices;
using Hyperion.Internal;
using Xunit;
using FluentAssertions;
using Hyperion.Extensions;
using Xunit.Abstractions;

namespace Hyperion.Tests
{
public class UnsafeDeserializationExclusionTests
{
private readonly ITestOutputHelper _output;

public UnsafeDeserializationExclusionTests(ITestOutputHelper output)
{
_output = output;
}

[Fact]
public void CantDeserializeANaughtyType()
{
//System.Diagnostics.Process p = new Process();
var serializer = new Hyperion.Serializer();
var di =new System.IO.DirectoryInfo(@"c:\");

Expand All @@ -25,6 +34,73 @@ public void CantDeserializeANaughtyType()
}
}

[Theory]
[MemberData(nameof(DangerousObjectFactory))]
public void DetectNaughtyTypesByDefault(Type dangerousType)
{
_output.WriteLine($"Testing for dangerous type [{dangerousType.AssemblyQualifiedName}]");
TypeEx.IsDisallowedType(dangerousType).Should().BeTrue();
}
/*
X "System.Security.Principal.WindowsIdentity",
X "System.Security.Principal.WindowsPrincipal",
X "System.Security.Claims.ClaimsIdentity",
X "System.Web.Security.RolePrincipal",
X "System.Windows.Forms.AxHost.State",
X "System.Windows.Data.ObjectDataProvider",
X "System.Management.Automation.PSObject",
X "System.IO.FileSystemInfo",
X "System.IO.FileInfo",
X "System.IdentityModel.Tokens.SessionSecurityToken",
X "SessionViewStateHistoryItem",
X "TextFormattingRunProperties",
X "ToolboxItemContainer",
X "System.CodeDom.Compiler.TempFileCollection",
X "System.Activities.Presentation.WorkflowDesigner",
X "System.Windows.ResourceDictionary",
X "System.Windows.Forms.BindingSource",
X "System.Diagnostics.Process",
"System.Management.IWbemClassObjectFreeThreaded" // Need to have sharepoint installed, simulated
"Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider", // Need to have ?Exchange? installed, simulated
??? "System.Security.Principal.WindowsClaimsIdentity", // This FQCN seemed to not exist in the past
*/
public static IEnumerable<object[]> DangerousObjectFactory()
{
var isWindow = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);

yield return new object[]{ typeof(System.IO.FileInfo) };
yield return new object[]{ typeof(System.IO.FileSystemInfo) };
yield return new object[]{ typeof(System.Security.Claims.ClaimsIdentity)};
yield return new object[]{ typeof(System.Diagnostics.Process)};
yield return new object[]{ typeof(System.CodeDom.Compiler.TempFileCollection)};
yield return new object[]{ typeof(System.Management.IWbemClassObjectFreeThreaded)}; // SIMULATED
yield return new object[]{ typeof(Microsoft.Exchange.Management.SystemManager.WinForms.ExchangeSettingsProvider)}; // SIMULATED
#if !NETFX
yield return new object[]{ typeof(System.Management.Automation.PSObject)};
#endif

if (isWindow)
{
yield return new object[]{ typeof(System.Security.Principal.WindowsIdentity) };
yield return new object[]{ typeof(System.Security.Principal.WindowsPrincipal)};
#if NETFX
var ass = typeof(System.Web.Mobile.MobileCapabilities).Assembly;
var type = ass.GetType("System.Web.UI.MobileControls.SessionViewState+SessionViewStateHistoryItem");
yield return new object[]{ type };

yield return new object[]{ typeof(System.Drawing.Design.ToolboxItemContainer)};
yield return new object[]{ typeof(System.Activities.Presentation.WorkflowDesigner)};
yield return new object[]{ typeof(Microsoft.VisualStudio.Text.Formatting.TextFormattingRunProperties)};
yield return new object[]{ typeof(System.IdentityModel.Tokens.SessionSecurityToken)};
yield return new object[]{ typeof(System.Web.Security.RolePrincipal) };
yield return new object[]{ typeof(System.Windows.Forms.AxHost.State)};
yield return new object[]{ typeof(System.Windows.Data.ObjectDataProvider)};
yield return new object[]{ typeof(System.Windows.ResourceDictionary)};
yield return new object[]{ typeof(System.Windows.Forms.BindingSource)};
#endif
}
}

internal class ClassA
{ }

Expand Down Expand Up @@ -84,4 +160,14 @@ public void TypeFilterShouldThrowOnNaughtyType()
}
}
}
}

namespace System.Management
{
public interface IWbemClassObjectFreeThreaded{ }
}

namespace Microsoft.Exchange.Management.SystemManager.WinForms
{
public class ExchangeSettingsProvider { }
}
Binary file not shown.
Binary file added src/Hyperion.Tests/lib/PresentationFramework.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added src/Hyperion.Tests/lib/System.Drawing.dll
Binary file not shown.
Binary file added src/Hyperion.Tests/lib/System.IdentityModel.dll
Binary file not shown.
Binary file added src/Hyperion.Tests/lib/System.Web.Mobile.dll
Binary file not shown.
Binary file added src/Hyperion.Tests/lib/System.Web.dll
Binary file not shown.
Binary file added src/Hyperion.Tests/lib/System.Windows.Forms.dll
Binary file not shown.
Loading

0 comments on commit 82f3347

Please sign in to comment.