未验证 提交 0c8bd9f0 编写于 作者: V vseanreesermsft 提交者: GitHub

Merging internal commits for release/6.0 (#7434)

* Change RestrictiveXamlXmlReader to use an allow list

- Removes the old deny list logic used by RestrictiveXamlXmlReader
- Provides an extensible (via registry) allow list mechanism

Ported from release/7.0 branch.
Fixes CVE-2022-41089.

* Merged PR 27600: [internal/release/6.0] Update dependencies from dnceng/internal/dotnet-winforms

This pull request updates the following dependencies

[marker]: <> (Begin:Coherency Updates)
## Coherency Updates

The following updates ensure that dependencies with a *CoherentParentDependency*
attribute were produced in a build used as input to the parent dependency's build.
See [Dependency Description Format](https://github.com/dotnet/arcade/blob/master/Documentation/DependencyDescriptionFormat.md#dependency-description-overview)

[DependencyUpdate]: <> (Begin)

- **Coherency Updates**:
  - **Microsoft.NETCore.ILDAsm**: from 6.0.11-servicing.22523.4 to 6.0.12-servicing.22566.2 (parent: Microsoft.Private.Winforms)
  - **Microsoft.NETCore.ILAsm**: from 6.0.11-servicing.22523.4 to 6.0.12-servicing.22566.2 (parent: Microsoft.Private.Winforms)
  - **Microsoft.NETCore.App.Ref**: from 6.0.11 to 6.0.12 (parent: Microsoft.Private.Winforms)
  - **Microsoft.NETCore.App.Runtime.win-x64**: from 6.0.11 to 6.0.12 (parent: Microsoft.Private.Winforms)
  - **VS.Redist.Common.NetCore.SharedFramework.x64.6.0**: from 6.0.11-servicing.22523.4 to 6.0.12-servicing.22566.2 (parent: Microsoft.Private.Winforms)

[DependencyUpdate]: <> (End)

[marker]: <> (End:Coherency Updates)

[marker]: <> (Begin:a88d6455-e128-4280-39b4-08d960f4ca81)
## From https://dev.azure.com/dnceng/internal/_git/dotnet-winforms
- **Subscription**: a88d6455-e128-4280-39b4-08d960f4ca81
- **Build**: 20221117.2
- **Date Produced**: November 17, 2022 4:27:14 PM UTC
- **Commit**: d4da6f214495396a4ec18fd6ac34194d75f790d1
- **Branch**: refs/heads/internal/release/6.0

[DependencyUpdate]: <> (Begin)

- **Updates**:
  - **Microsoft.Dotnet.WinForms.ProjectTemplates**: [from 6.0.12-servicing.22554.4 to 6.0.12-servicing.22567.2][1]
  - **Microsoft.Private.Winforms**: [from 6.0.12-servicing.22554.4 to 6.0.12-servicing.22567.2][1]
  - **Microsoft.NETCore.ILDAsm**: [from 6.0.11-servicing.22523.4 to 6.0.12-servicing.22566.2][2]
  - **Microsoft.NETCore.ILAsm**: [from 6.0.11-servicing.22523.4 to 6.0.12-servicing.22566.2][2]
  - **Microsoft.NETCore.App.Ref**: [from 6.0.11 to 6.0.12][2]
  - **Microsoft.NETCore.App.Runtime.win-x64**: [from 6.0.11 to 6.0.12][2]
  - **VS.Redist.Common.NetCore.SharedFramework.x64.6.0**: [from 6.0.11-servicing.22523.4 to 6.0.12-servicing.22566.2][2]

[1]: https://dev.azure.com/dnceng/internal/_git/dotnet-winforms/branches?baseVersion=GCcf9269e&targetVersion=GCd4da6f2&_a=files
[2]: https://dev.azure.com/dnceng/internal/_git/dotnet-runtime/branches?baseVersion=GC943474c&targetVersion=GC301f927&_a=files

[DependencyUpdate]: <> (End)

[marker]: <> (End:a88d6455-e128-4280-39b4-08d960f4ca81)

* Merged PR 27684: [internal/release/6.0] Update dependencies from dnceng/internal/dotnet-winforms

This pull request updates the following dependencies

[marker]: <> (Begin:Coherency Updates)
## Coherency Updates

The following updates ensure that dependencies with a *CoherentParentDependency*
attribute were produced in a build used as input to the parent dependency's build.
See [Dependency Description Format](https://github.com/dotnet/arcade/blob/master/Documentation/DependencyDescriptionFormat.md#dependency-description-overview)

[DependencyUpdate]: <> (Begin)

- **Coherency Updates**:
  - **Microsoft.NETCore.ILDAsm**: from 6.0.12-servicing.22566.2 to 6.0.12-servicing.22568.7 (parent: Microsoft.Private.Winforms)
  - **Microsoft.NETCore.ILAsm**: from 6.0.12-servicing.22566.2 to 6.0.12-servicing.22568.7 (parent: Microsoft.Private.Winforms)
  - **Microsoft.NETCore.App.Ref**: from 6.0.12 to 6.0.12 (parent: Microsoft.Private.Winforms)
  - **Microsoft.NETCore.App.Runtime.win-x64**: from 6.0.12 to 6.0.12 (parent: Microsoft.Private.Winforms)
  - **VS.Redist.Common.NetCore.SharedFramework.x64.6.0**: from 6.0.12-servicing.22566.2 to 6.0.12-servicing.22568.7 (parent: Microsoft.Private.Winforms)

[DependencyUpdate]: <> (End)

[marker]: <> (End:Coherency Updates)

[marker]: <> (Begin:a88d6455-e128-4280-39b4-08d960f4ca81)
## From https://dev.azure.com/dnceng/internal/_git/dotnet-winforms
- **Subscription**: a88d6455-e128-4280-39b4-08d960f4ca81
- **Build**: 20221118.10
- **Date Produced**: November 19, 2022 1:01:34 AM UTC
- **Commit**: bf70006b6e83a62167705431d633d1fd1ab49b34
- **Branch**: refs/heads/internal/release/6.0

[DependencyUpdate]: <> (Begin)

- **Updates**:
  - **Microsoft.Dotnet.WinForms.ProjectTemplates**: [from 6.0.12-servicing.22567.2 to 6.0.12-servicing.22568.10][1]
  - **Microsoft.Private.Winforms**: [from 6.0.12-servicing.22567.2 to 6.0.12-servicing.22568.10][1]
  - **Microsoft.NETCore.ILDAsm**: [from 6.0.12-servicing.22566.2 to 6.0.12-servicing.22568.7][2]
  - **Microsoft.NETCore.ILAsm**: [from 6.0.12-servicing.22566.2 to 6.0.12-servicing.22568.7][2]
  - **Microsoft.NETCore.App.Ref**: [from 6.0.12 to 6.0.12][2]
  - **Microsoft.NETCore.App.Runtime.win-x64**: [from 6.0.12 to 6.0.12][2]
  - **VS.Redist.Common.NetCore.SharedFramework.x64.6.0**: [from 6.0.12-servicing.22566.2 to 6.0.12-servicing.22568.7][2]

[1]: https://dev.azure.com/dnceng/internal/_git/dotnet-winforms/branches?baseVersion=GCd4da6f2&targetVersion=GCbf70006&_a=files
[2]: https://dev.azure.com/dnceng/internal/_git/dotnet-runtime/branches?baseVersion=GC301f927&targetVersion=GC02e45a4&_a=files

[DependencyUpdate]: <> (End)

[marker]: <> (End:a88d6455-e128-4280-39b4-08d960f4ca81)

* Merged PR 27903: [internal/release/6.0] Update dependencies from dnceng/internal/dotnet-winforms

This pull request updates the following dependencies

[marker]: <> (Begin:a88d6455-e128-4280-39b4-08d960f4ca81)
## From https://dev.azure.com/dnceng/internal/_git/dotnet-winforms
- **Subscription**: a88d6455-e128-4280-39b4-08d960f4ca81
- **Build**: 20221129.11
- **Date Produced**: November 29, 2022 9:00:18 PM UTC
- **Commit**: bd7407606f49c7bb9ee784c5a5a9c19127c0f081
- **Branch**: refs/heads/internal/release/6.0

[DependencyUpdate]: <> (Begin)

- **Updates**:
  - **Microsoft.Dotnet.WinForms.ProjectTemplates**: [from 6.0.12-servicing.22568.10 to 6.0.13-servicing.22579.11][1]
  - **Microsoft.Private.Winforms**: [from 6.0.12-servicing.22568.10 to 6.0.13-servicing.22579.11][1]

[1]: https://dev.azure.com/dnceng/internal/_git/dotnet-winforms/branches?baseVersion=GCbf70006&targetVersion=GCbd74076&_a=files

[DependencyUpdate]: <> (End)

[marker]: <> (End:a88d6455-e128-4280-39b4-08d960f4ca81)

* Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-winforms build 20221201.1

Microsoft.Dotnet.WinForms.ProjectTemplates , Microsoft.Private.Winforms
 From Version 6.0.13-servicing.22579.11 -> To Version 6.0.13-servicing.22601.1

Dependency coherency updates

Microsoft.NETCore.ILDAsm,Microsoft.NETCore.ILAsm,Microsoft.NETCore.App.Ref,Microsoft.NETCore.App.Runtime.win-x64,VS.Redist.Common.NetCore.SharedFramework.x64.6.0
 From Version 6.0.12-servicing.22568.7 -> To Version 6.0.13-servicing.22580.9 (parent: Microsoft.Private.Winforms
Co-authored-by: Ndotnet-bot <dotnet-bot@microsoft.com>
Co-authored-by: NLevi Broderick <levib@microsoft.com>
Co-authored-by: NDotNet Bot <dn-bot@microsoft.com>
上级 013b2e10
......@@ -5,6 +5,7 @@
<clear />
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
<!-- Begin: Package sources from dotnet-runtime -->
<add key="darc-int-dotnet-runtime-1af80ba" value="https://pkgs.dev.azure.com/dnceng/internal/_packaging/darc-int-dotnet-runtime-1af80ba0/nuget/v3/index.json" />
<!-- End: Package sources from dotnet-runtime -->
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
......@@ -18,6 +19,7 @@
<disabledPackageSources>
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
<!-- Begin: Package sources from dotnet-runtime -->
<add key="darc-int-dotnet-runtime-1af80ba" value="true" />
<!-- End: Package sources from dotnet-runtime -->
<!--End: Package sources managed by Dependency Flow automation. Do not edit the sources above.-->
</disabledPackageSources>
......
<?xml version="1.0" encoding="utf-8"?>
<Dependencies>
<ProductDependencies>
<Dependency Name="Microsoft.Private.Winforms" Version=" 6.0.12-servicing.22554.4 ">
<Dependency Name="Microsoft.Private.Winforms" Version="6.0.13-servicing.22601.1">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-winforms</Uri>
<Sha>cf9269e4b3f8f3d74a59e90c19ec6f8d390bcad4</Sha>
<Sha>5a262a681e41941ea7ef42f49c0ed3b27a05c259</Sha>
</Dependency>
<Dependency Name="Microsoft.Dotnet.WinForms.ProjectTemplates" Version=" 6.0.12-servicing.22554.4 ">
<Dependency Name="Microsoft.Dotnet.WinForms.ProjectTemplates" Version="6.0.13-servicing.22601.1">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-winforms</Uri>
<Sha>cf9269e4b3f8f3d74a59e90c19ec6f8d390bcad4</Sha>
<Sha>5a262a681e41941ea7ef42f49c0ed3b27a05c259</Sha>
</Dependency>
<Dependency Name="System.CodeDom" Version="6.0.0" CoherentParentDependency="Microsoft.Private.Winforms">
<Uri>https://github.com/dotnet/runtime</Uri>
......@@ -57,29 +57,29 @@
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>4822e3c3aa77eb82b2fb33c9321f923cf11ddde6</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.ILDAsm" Version="6.0.11-servicing.22523.4" CoherentParentDependency="Microsoft.Private.Winforms">
<Dependency Name="Microsoft.NETCore.ILDAsm" Version="6.0.13-servicing.22580.9" CoherentParentDependency="Microsoft.Private.Winforms">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>943474ca16db7c65ba6cff4a89c3ebd219dde3e5</Sha>
<Sha>1af80ba017f6f7644305e1781d8cc9845a92b5f8</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.ILAsm" Version="6.0.11-servicing.22523.4" CoherentParentDependency="Microsoft.Private.Winforms">
<Dependency Name="Microsoft.NETCore.ILAsm" Version="6.0.13-servicing.22580.9" CoherentParentDependency="Microsoft.Private.Winforms">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>943474ca16db7c65ba6cff4a89c3ebd219dde3e5</Sha>
<Sha>1af80ba017f6f7644305e1781d8cc9845a92b5f8</Sha>
</Dependency>
<Dependency Name="System.Resources.Extensions" Version="6.0.0" CoherentParentDependency="Microsoft.Private.Winforms">
<Uri>https://github.com/dotnet/runtime</Uri>
<Sha>4822e3c3aa77eb82b2fb33c9321f923cf11ddde6</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.App.Ref" Version="6.0.11" CoherentParentDependency="Microsoft.Private.Winforms">
<Dependency Name="Microsoft.NETCore.App.Ref" Version="6.0.13" CoherentParentDependency="Microsoft.Private.Winforms">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>943474ca16db7c65ba6cff4a89c3ebd219dde3e5</Sha>
<Sha>1af80ba017f6f7644305e1781d8cc9845a92b5f8</Sha>
</Dependency>
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="6.0.11" CoherentParentDependency="Microsoft.Private.Winforms">
<Dependency Name="Microsoft.NETCore.App.Runtime.win-x64" Version="6.0.13" CoherentParentDependency="Microsoft.Private.Winforms">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>943474ca16db7c65ba6cff4a89c3ebd219dde3e5</Sha>
<Sha>1af80ba017f6f7644305e1781d8cc9845a92b5f8</Sha>
</Dependency>
<Dependency Name="VS.Redist.Common.NetCore.SharedFramework.x64.6.0" Version="6.0.11-servicing.22523.4" CoherentParentDependency="Microsoft.Private.Winforms">
<Dependency Name="VS.Redist.Common.NetCore.SharedFramework.x64.6.0" Version="6.0.13-servicing.22580.9" CoherentParentDependency="Microsoft.Private.Winforms">
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-runtime</Uri>
<Sha>943474ca16db7c65ba6cff4a89c3ebd219dde3e5</Sha>
<Sha>1af80ba017f6f7644305e1781d8cc9845a92b5f8</Sha>
</Dependency>
</ProductDependencies>
<ToolsetDependencies>
......
......@@ -26,19 +26,19 @@
</PropertyGroup>
<!-- NuGet Package Versions -->
<PropertyGroup>
<MicrosoftPrivateWinformsVersion>6.0.11-servicing.22523.4</MicrosoftPrivateWinformsVersion>
<MicrosoftPrivateWinformsVersion>6.0.13-servicing.22601.1</MicrosoftPrivateWinformsVersion>
</PropertyGroup>
<!-- Packages that come from https://github.com/dotnet/coreclr -->
<PropertyGroup>
<MicrosoftNETCoreRuntimeCoreCLRVersion>5.0.0-alpha1.19562.1</MicrosoftNETCoreRuntimeCoreCLRVersion>
<MicrosoftNETCoreILDAsmVersion>6.0.11-servicing.22523.4</MicrosoftNETCoreILDAsmVersion>
<MicrosoftNETCoreILAsmVersion>6.0.11-servicing.22523.4</MicrosoftNETCoreILAsmVersion>
<MicrosoftNETCoreILDAsmVersion>6.0.13-servicing.22580.9</MicrosoftNETCoreILDAsmVersion>
<MicrosoftNETCoreILAsmVersion>6.0.13-servicing.22580.9</MicrosoftNETCoreILAsmVersion>
</PropertyGroup>
<!-- Packages that come from https://github.com/dotnet/core-setup -->
<PropertyGroup>
<VSRedistCommonNetCoreSharedFrameworkx6460PackageVersion>6.0.11-servicing.22523.4</VSRedistCommonNetCoreSharedFrameworkx6460PackageVersion>
<MicrosoftNETCoreAppRefVersion>6.0.11</MicrosoftNETCoreAppRefVersion>
<MicrosoftNETCoreAppRuntimewinx64Version>6.0.11</MicrosoftNETCoreAppRuntimewinx64Version>
<VSRedistCommonNetCoreSharedFrameworkx6460PackageVersion>6.0.13-servicing.22580.9</VSRedistCommonNetCoreSharedFrameworkx6460PackageVersion>
<MicrosoftNETCoreAppRefVersion>6.0.13</MicrosoftNETCoreAppRefVersion>
<MicrosoftNETCoreAppRuntimewinx64Version>6.0.13</MicrosoftNETCoreAppRuntimewinx64Version>
<MicrosoftNETCorePlatformsVersion>6.0.7</MicrosoftNETCorePlatformsVersion>
<SystemDrawingCommonVersion>6.0.0</SystemDrawingCommonVersion>
<SystemDirectoryServicesVersion>6.0.0</SystemDirectoryServicesVersion>
......
......@@ -2,58 +2,69 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// Description: This class provides a XamlXmlReader implementation that skips over some known dangerous
// types when calling into the Read method, this is meant to prevent WpfXamlLoader from instantiating.
//
// Description: This class provides a XamlXmlReader implementation that implements an allow-list of legal
// types when calling into the Read method, meant to prevent instantiation of unexpected types.
//
using System.Collections.Concurrent;
using Microsoft.Win32;
using System.Collections.Generic;
using System.Reflection;
using System.Xaml;
using System.Xml;
using System.Security;
namespace System.Windows.Markup
{
/// <summary>
/// Provides a XamlXmlReader implementation that that skips over some known dangerous types.
/// Provides a XamlXmlReader implementation that that implements an allow-list of legal types.
/// </summary>
internal class RestrictiveXamlXmlReader : System.Xaml.XamlXmlReader
{
/// <summary>
/// The RestrictedTypes in the _restrictedTypes list do not initially contain a Type reference, we use a Type reference to determine whether an incoming Type can be assigned to that Type
/// in order to restrict it or allow it. We cannot get a Type reference without loading the assembly, so we need to first go through the loaded assemblies, and assign the Types
/// that are loaded.
/// </summary>
static RestrictiveXamlXmlReader()
{
_unloadedTypes = new ConcurrentDictionary<string, List<RestrictedType>>();
private const string AllowedTypesForRestrictiveXamlContexts = @"SOFTWARE\Microsoft\.NETFramework\Windows Presentation Foundation\XPSAllowedTypes";
private static readonly HashSet<string> AllXamlNamespaces = new HashSet<string>(XamlLanguage.XamlNamespaces);
private static readonly Type DependencyObjectType = typeof(System.Windows.DependencyObject);
private static readonly HashSet<string> SafeTypesFromRegistry = ReadAllowedTypesForRestrictedXamlContexts();
// Go through the list of restricted types and add each type under the matching assembly entry in the dictionary.
foreach (RestrictedType type in _restrictedTypes)
private static HashSet<string> ReadAllowedTypesForRestrictedXamlContexts()
{
HashSet<string> allowedTypesFromRegistry = new HashSet<string>();
try
{
if (!String.IsNullOrEmpty(type.AssemblyName))
// n.b. Registry64 uses the 32-bit registry in 32-bit operating systems.
// The registry key should have this format and is consistent across netfx & netcore:
//
// [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\Windows Presentation Foundation\XPSAllowedTypes]
// "SomeValue1"="Contoso.Controls.MyControl"
// "SomeValue2"="Fabrikam.Controls.MyOtherControl"
// ...
//
// The value names aren't important. The value data should match Type.FullName (including namespace but not assembly).
// If any value data is exactly "*", this serves as a global opt-out and allows everything through the system.
using (RegistryKey hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64))
{
if(!_unloadedTypes.ContainsKey(type.AssemblyName))
if (hklm != null)
{
_unloadedTypes[type.AssemblyName] = new List<RestrictedType>();
}
_unloadedTypes[type.AssemblyName].Add(type);
}
else
{
// If the RestrictedType entry does not provide an assembly name load it from PresentationFramework,
// this is the current assembly so it's already loaded, just get the Type and assign it to the RestrictedType entry
System.Type typeReference = System.Type.GetType(type.TypeName, false);
if (typeReference != null)
{
type.TypeReference = typeReference;
using (RegistryKey xpsDangerKey = hklm.OpenSubKey(AllowedTypesForRestrictiveXamlContexts, false))
{
if (xpsDangerKey != null)
{
foreach (string typeName in xpsDangerKey.GetValueNames())
{
object value = xpsDangerKey.GetValue(typeName);
if (value != null)
{
allowedTypesFromRegistry.Add(value.ToString());
}
}
}
}
}
}
}
catch
{
// do nothing
}
return allowedTypesFromRegistry;
}
/// <summary>
......@@ -85,15 +96,15 @@ internal RestrictiveXamlXmlReader(XmlReader xmlReader, XamlSchemaContext schemaC
/// </returns>
public override bool Read()
{
bool result = false;
bool result;
int skippingDepth = 0;
while (result = base.Read())
{
if (skippingDepth <= 0)
{
if (NodeType == System.Xaml.XamlNodeType.StartObject &&
IsRestrictedType(Type.UnderlyingType))
if ((NodeType == System.Xaml.XamlNodeType.StartObject && !IsAllowedType(Type.UnderlyingType)) ||
(NodeType == System.Xaml.XamlNodeType.StartMember && Member is XamlDirective directive && !IsAllowedDirective(directive)))
{
skippingDepth = 1;
}
......@@ -104,14 +115,18 @@ public override bool Read()
}
else
{
if (NodeType == System.Xaml.XamlNodeType.StartObject ||
NodeType == System.Xaml.XamlNodeType.GetObject)
{
skippingDepth += 1;
}
else if (NodeType == System.Xaml.XamlNodeType.EndObject)
switch (NodeType)
{
skippingDepth -= 1;
case System.Xaml.XamlNodeType.StartObject:
case System.Xaml.XamlNodeType.StartMember:
case System.Xaml.XamlNodeType.GetObject:
skippingDepth += 1;
break;
case System.Xaml.XamlNodeType.EndObject:
case System.Xaml.XamlNodeType.EndMember:
skippingDepth -= 1;
break;
}
}
}
......@@ -120,128 +135,82 @@ public override bool Read()
}
/// <summary>
/// Determines whether an incoming type is either a restricted type or inheriting from one.
/// Determines whether an incoming directive is allowed.
/// </summary>
private bool IsRestrictedType(Type type)
private bool IsAllowedDirective(XamlDirective directive)
{
if (type != null)
// If the global opt-out switch is enabled, all directives are allowed.
if (SafeTypesFromRegistry.Contains("*"))
{
// If an incoming type is already in the set we can just return false, we've verified this type is safe.
if (_safeTypesSet.Contains(type))
{
return false;
}
// Ensure that the restricted type list has the latest information for the assemblies currently loaded.
EnsureLatestAssemblyLoadInformation();
return true;
}
// Iterate through our _restrictedTypes list, if an entry has a TypeReference then the type is loaded and we can check it.
foreach (RestrictedType restrictedType in _restrictedTypes)
// If this isn't a XAML directive, allow it through.
// This allows XML directives and other non-XAML directives through.
// This largely follows the logic at XamlMember.Equals, but we trigger for *any*
// overlapping namespace rather than requiring the namespace sets to match exactly.
bool isXamlDirective = false;
foreach (string xmlns in directive.GetXamlNamespaces())
{
if (AllXamlNamespaces.Contains(xmlns))
{
if (restrictedType.TypeReference?.IsAssignableFrom(type) == true)
{
return true;
}
isXamlDirective = true;
break;
}
}
// We've detected this type isn't nor inherits from a restricted type, add it to the safe types set.
_safeTypesSet.Add(type);
if (!isXamlDirective)
{
return true;
}
// The following is an exhaustive list of all allowed XAML directives.
if (directive.Name == XamlLanguage.Items.Name ||
directive.Name == XamlLanguage.Key.Name ||
directive.Name == XamlLanguage.Name.Name)
{
return true;
}
// This is a XAML directive but isn't in the allow-list; forbid it.
return false;
}
/// <summary>
/// Iterates through the currently loaded assemblies and gets the Types for the assemblies we've marked as unloaded.
/// If our thread static assembly count is still the same we can skip this, we know no new assemblies have been loaded.
/// Determines whether an incoming type is present in the allow list.
/// </summary>
private static void EnsureLatestAssemblyLoadInformation()
private bool IsAllowedType(Type type)
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
if (assemblies.Length != _loadedAssembliesCount)
// If the global opt-out switch is enabled, or if this type has been explicitly
// allow-listed (or is null, meaning this is a proxy which will be checked elsewhere),
// then it can come through.
if (type is null || SafeTypesFromRegistry.Contains("*") || _safeTypesSet.Contains(type) || SafeTypesFromRegistry.Contains(type.FullName))
{
foreach (Assembly assembly in assemblies)
{
RegisterAssembly(assembly);
}
_loadedAssembliesCount = assemblies.Length;
return true;
}
}
// We also have an implicit allow list which consists of:
// - primitives (int, etc.); and
// - any DependencyObject-derived type which exists in the System.Windows.* namespace.
/// <summary>
/// Get the Types from a newly loaded assembly and assign them in the RestrictedType list.
/// </summary>
private static void RegisterAssembly(Assembly assembly)
{
if (assembly != null)
{
string fullName = assembly.FullName;
bool isValidNamespace = type.Namespace != null && type.Namespace.StartsWith("System.Windows.", StringComparison.Ordinal);
bool isValidSubClass = type.IsSubclassOf(DependencyObjectType);
bool isValidPrimitive = type.IsPrimitive;
List<RestrictedType> types = null;
if (_unloadedTypes.TryGetValue(fullName, out types))
{
if (types != null)
{
foreach (RestrictedType restrictedType in types)
{
Type typeInfo = assembly.GetType(restrictedType.TypeName, false);
restrictedType.TypeReference = typeInfo;
}
}
_unloadedTypes.TryRemove(fullName, out types);
}
if (isValidPrimitive || (isValidNamespace && isValidSubClass))
{
// Add it to the explicit allow list to make future lookups on this instance faster.
_safeTypesSet.Add(type);
return true;
}
// Otherwise, it didn't exist on any of our allow lists.
return false;
}
/// <summary>
/// Known dangerous types exploitable through XAML load.
/// </summary>
static List<RestrictedType> _restrictedTypes = new List<RestrictedType>() {
new RestrictedType("System.Windows.Data.ObjectDataProvider",""),
new RestrictedType("System.Windows.ResourceDictionary",""),
new RestrictedType("System.Configuration.Install.AssemblyInstaller","System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"),
new RestrictedType("System.Activities.Presentation.WorkflowDesigner","System.Activities.Presentation, Version = 4.0.0.0, Culture = neutral, PublicKeyToken = 31bf3856ad364e35"),
new RestrictedType("System.Windows.Forms.BindingSource","System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
};
/// <summary>
/// Dictionary to keep track of known types that have not yet been loaded, the key is the assembly name.
/// Once an assembly is loaded we take the known types in that assembly, set the Type property in the RestrictedType entry, then remove the assembly entry.
/// </summary>
static ConcurrentDictionary<string, List<RestrictedType>> _unloadedTypes = null;
/// <summary>
/// Per instance set of found restricted types, this is initialized to the known types that have been loaded,
/// if a type is found that is not already in the set and is assignable to a restricted type it is added.
/// Per instance set of allow-listed types, may grow at runtime to encompass implicit allow list.
/// </summary>
HashSet<Type> _safeTypesSet = new HashSet<Type>();
/// <summary>
/// Keeps track of the assembly count, if the assembly count is the same we avoid having to go through the loaded assemblies.
/// Once we get a Type in IsRestrictedType we are guaranteed to have already loaded it's assembly and base type assemblies,any other
/// assembly loads happening in other threads during our processing of IsRestrictedType do not affect our ability to check the Type properly.
/// </summary>
[ThreadStatic] private static int _loadedAssembliesCount;
/// <summary>
/// Helper class to store type names.
/// </summary>
private class RestrictedType
{
public RestrictedType(string typeName, string assemblyName)
{
TypeName = typeName;
AssemblyName = assemblyName;
}
public string TypeName { get; set; }
public string AssemblyName { get; set; }
public Type TypeReference { get; set; }
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册