Skip to content
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
bcaaa2a
UseDefaultDllImportSearchPathsAttribute
LingxiaChen Jul 8, 2019
e09d6ca
Update rule title.
LingxiaChen Jul 9, 2019
20ec3e0
Merge branch 'master' into UseDefaultDllImportSearchPathsAttribute
LLLXXXCCC Jul 12, 2019
2a7eecc
Update rule message.
LingxiaChen Jul 12, 2019
3207b5f
Update.
LingxiaChen Jul 12, 2019
3543d04
Merge branch 'UseDefaultDllImportSearchPathsAttribute' of https://git…
LingxiaChen Jul 12, 2019
c9e6108
Add comment to test cases.
LingxiaChen Jul 15, 2019
314ec65
Add comment about the Known Dlls.
LingxiaChen Jul 15, 2019
dd1ff21
Remove the dll extension limitaion.
LingxiaChen Jul 18, 2019
03a4151
Add a test case using nonexistent absolute path.
LingxiaChen Jul 18, 2019
4eb57f0
Mark cases using absolute path to import dll as NoDiagnostic.
LingxiaChen Jul 22, 2019
67a066e
Add a test case.
LingxiaChen Jul 22, 2019
98f8ffc
Merge branch 'master' into UseDefaultDllImportSearchPathsAttribute
LLLXXXCCC Jul 23, 2019
b66bb54
Do not use AssemblyDirectory, LegacyBehavior, UseDllDirectoryForDepen…
LingxiaChen Jul 24, 2019
80412bb
Merge branch 'UseDefaultDllImportSearchPathsAttribute' of https://git…
LingxiaChen Jul 24, 2019
39324b8
Merge branch 'master' into UseDefaultDllImportSearchPathsAttribute
LingxiaChen Jul 25, 2019
b143627
Merge branch 'UseDefaultDllImportSearchPathsAttribute' of https://git…
LingxiaChen Jul 25, 2019
c43e691
Merge branch 'LLLXXXCCC-UseDefaultDllImportSearchPathsAttribute' into…
LingxiaChen Jul 25, 2019
a873385
Sync.
LingxiaChen Jul 25, 2019
f620275
Change title using sentence casing.
LingxiaChen Jul 25, 2019
6ca96e7
Merge pull request #19 from dotnet/master
LLLXXXCCC Jul 30, 2019
d43709f
Address review feedback.
LingxiaChen Jul 30, 2019
3704fb1
Add test cases for EditorConfigOption.
LingxiaChen Aug 1, 2019
d71044c
Mark DllImportSearchPath.ApplicationDirectory as a bad use.
LingxiaChen Aug 1, 2019
b61330e
Add another rule for using unsafe DllImportSearchPath value.
LingxiaChen Aug 2, 2019
6d53be4
Address review feedback.
LingxiaChen Aug 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion docs/Analyzer Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -288,4 +288,13 @@ Option Values: integral values

Default Value: Specific to each configurable rule ('100000' by default for most rules)

Example: `dotnet_net_core.CA5387.sufficient_IterationCount_for_weak_KDF_algorithm = 100000`
Example: `dotnet_code_quality.CA5387.sufficient_IterationCount_for_weak_KDF_algorithm = 100000`

#### Configure unsafe DllImportSearchPath bits when using DefaultDllImportSearchPaths attribute
Option Name: `unsafe_DllImportSearchPath_bits`

Option Values: Integer values of System.Runtime.InteropServices.DllImportSearchPath

Default Value: Specific to each configurable rule ('258', which is AssemblyDirectory | UseDllDirectoryForDependencies, by default for most rules)

Example: `dotnet_code_quality.CA5392.unsafe_DllImportSearchPath_bits = 258`
Original file line number Diff line number Diff line change
Expand Up @@ -1074,4 +1074,22 @@
<data name="JsonNetMaybeInsecureSerializerTitle" xml:space="preserve">
<value>Ensure that JsonSerializer has a secure configuration when deserializing</value>
</data>
<data name="UseDefaultDllImportSearchPathsAttribute" xml:space="preserve">
<value>Use DefaultDllImportSearchPaths attribute for P/Invokes</value>
Copy link

@dotpaul dotpaul Jul 30, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use DefaultDllImportSearchPaths attribute for P/Invokes [](start = 11, length = 55)

Trying to think of a title/message/description kinda makes me think we should have a separate rule for checking the value. What do you think?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you thumbs up the comment, does that mean you're going to add another rule? 🙂

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NP.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that a "yes let's have a separate diagnostic if the value has unsafe bits", or a "no let's use the same diagnostic"? 🙂

</data>
<data name="UseDefaultDllImportSearchPathsAttributeDescription" xml:space="preserve">
<value>By default, P/Invokes using DllImportAttribute probe a number of directories, including the current working directory for the library to load. This can be a security issue for certain applications, leading to DLL hijacking.</value>
</data>
<data name="UseDefaultDllImportSearchPathsAttributeMessage" xml:space="preserve">
<value>The method {0} didn't use DefaultDllImportSearchPaths attribute for P/Invokes.</value>
</data>
<data name="DoNotUseUnsafeDllImportSearchPath" xml:space="preserve">
<value>Do not use unsafe DllImportSearchPath value</value>
</data>
<data name="DoNotUseUnsafeDllImportSearchPathDescription" xml:space="preserve">
<value>There could be malicious DLL under the application directory or the default DLL search directories. Use an DllImportSearchPath value that sepecifies explicit search path instead</value>
</data>
<data name="DoNotUseUnsafeDllImportSearchPathMessage" xml:space="preserve">
<value>Use unsafe DllImportSearchPath value {0}</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using Analyzer.Utilities;
using Analyzer.Utilities.Extensions;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.FlowAnalysis.DataFlow;
using Microsoft.NetCore.Analyzers.Security.Helpers;

namespace Microsoft.NetCore.Analyzers.Security
{
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class UseDefaultDllImportSearchPathsAttribute : DiagnosticAnalyzer
{
internal static DiagnosticDescriptor UseDefaultDllImportSearchPathsAttributeRule = SecurityHelpers.CreateDiagnosticDescriptor(
"CA5392",
typeof(MicrosoftNetCoreAnalyzersResources),
nameof(MicrosoftNetCoreAnalyzersResources.UseDefaultDllImportSearchPathsAttribute),
nameof(MicrosoftNetCoreAnalyzersResources.UseDefaultDllImportSearchPathsAttributeMessage),
DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX,
helpLinkUri: null,
descriptionResourceStringName: nameof(MicrosoftNetCoreAnalyzersResources.UseDefaultDllImportSearchPathsAttributeDescription),
customTags: WellKnownDiagnosticTags.Telemetry);
internal static DiagnosticDescriptor DoNotUseUnsafeDllImportSearchPathRule = SecurityHelpers.CreateDiagnosticDescriptor(
"CA5393",
nameof(MicrosoftNetCoreAnalyzersResources.DoNotUseUnsafeDllImportSearchPath),
nameof(MicrosoftNetCoreAnalyzersResources.DoNotUseUnsafeDllImportSearchPathMessage),
DiagnosticHelpers.EnabledByDefaultIfNotBuildingVSIX,
helpLinkUri: null,
descriptionResourceStringName: nameof(MicrosoftNetCoreAnalyzersResources.DoNotUseUnsafeDllImportSearchPathDescription),
customTags: WellKnownDiagnosticTagsExtensions.DataflowAndTelemetry);

// DllImportSearchPath.AssemblyDirectory = 2.
// DllImportSearchPath.UseDllDirectoryForDependencies = 256.
// DllImportSearchPath.ApplicationDirectory = 512.
private const int UnsafeBits = 2 | 256 | 512;
private const int LegacyBehavior = 0;

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(
UseDefaultDllImportSearchPathsAttributeRule,
DoNotUseUnsafeDllImportSearchPathRule);

public override void Initialize(AnalysisContext context)
{
context.EnableConcurrentExecution();

// Security analyzer - analyze and report diagnostics on generated code.
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);

context.RegisterCompilationStartAction(compilationStartAnalysisContext =>
{
var compilation = compilationStartAnalysisContext.Compilation;
var wellKnownTypeProvider = WellKnownTypeProvider.GetOrCreate(compilation);

if (!wellKnownTypeProvider.TryGetTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDllImportAttribute, out INamedTypeSymbol dllImportAttributeTypeSymbol) ||
!wellKnownTypeProvider.TryGetTypeByMetadataName(WellKnownTypeNames.SystemRuntimeInteropServicesDefaultDllImportSearchPathsAttribute, out INamedTypeSymbol defaultDllImportSearchPathsAttributeTypeSymbol))
{
return;
}

var cancellationToken = compilationStartAnalysisContext.CancellationToken;
var unsafeDllImportSearchPathBits = compilationStartAnalysisContext.Options.GetUnsignedIntegralOptionValue(
optionName: EditorConfigOptionNames.UnsafeDllImportSearchPathBits,
rule: DoNotUseUnsafeDllImportSearchPathRule,
defaultValue: UnsafeBits,
cancellationToken: cancellationToken);
var defaultDllImportSearchPathsAttributeOnAssembly = compilation.Assembly.GetAttributes().FirstOrDefault(o => o.AttributeClass.Equals(defaultDllImportSearchPathsAttributeTypeSymbol));

compilationStartAnalysisContext.RegisterSymbolAction(symbolAnalysisContext =>
{
var symbol = symbolAnalysisContext.Symbol;

if (!symbol.IsExtern || !symbol.IsStatic)
{
return;
}

var dllImportAttribute = symbol.GetAttributes().FirstOrDefault(s => s.AttributeClass.Equals(dllImportAttributeTypeSymbol));
var defaultDllImportSearchPathsAttribute = symbol.GetAttributes().FirstOrDefault(s => s.AttributeClass.Equals(defaultDllImportSearchPathsAttributeTypeSymbol));

if (dllImportAttribute != null)
{
var constructorArguments = dllImportAttribute.ConstructorArguments;

if (constructorArguments.Length == 0)
{
return;
}

if (Path.IsPathRooted(constructorArguments[0].Value.ToString()))
{
return;
}

var rule = UseDefaultDllImportSearchPathsAttributeRule;
var ruleArgument = symbol.Name;

if (defaultDllImportSearchPathsAttribute == null)
{
if (defaultDllImportSearchPathsAttributeOnAssembly != null)
{
var dllImportSearchPathOnAssembly = (int)defaultDllImportSearchPathsAttributeOnAssembly.ConstructorArguments.FirstOrDefault().Value;
var validBits = dllImportSearchPathOnAssembly & unsafeDllImportSearchPathBits;

if (dllImportSearchPathOnAssembly != LegacyBehavior &&
validBits == 0)
{
return;
}

rule = DoNotUseUnsafeDllImportSearchPathRule;
ruleArgument = ((DllImportSearchPath)validBits).ToString();
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a huge deal, but may want to consider refactoring so you don't have to repeat this code and the code below.

}
else
{
var dllImportSearchPath = (int)defaultDllImportSearchPathsAttribute.ConstructorArguments.FirstOrDefault().Value;
var validBits = dllImportSearchPath & unsafeDllImportSearchPathBits;

if (dllImportSearchPath != LegacyBehavior &&
validBits == 0)
{
return;
}

rule = DoNotUseUnsafeDllImportSearchPathRule;
ruleArgument = ((DllImportSearchPath)validBits).ToString();
}

symbolAnalysisContext.ReportDiagnostic(
symbol.CreateDiagnostic(
rule,
ruleArgument));
}
}, SymbolKind.Method);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="cs" original="../MicrosoftNetCoreAnalyzersResources.resx">
<body>
<trans-unit id="DoNotUseUnsafeDllImportSearchPath">
<source>Do not use unsafe DllImportSearchPath value</source>
<target state="new">Do not use unsafe DllImportSearchPath value</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseUnsafeDllImportSearchPathDescription">
<source>There could be malicious DLL under the application directory or the default DLL search directories. Use an DllImportSearchPath value that sepecifies explicit search path instead</source>
<target state="new">There could be malicious DLL under the application directory or the default DLL search directories. Use an DllImportSearchPath value that sepecifies explicit search path instead</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseUnsafeDllImportSearchPathMessage">
<source>Use unsafe DllImportSearchPath value {0}</source>
<target state="new">Use unsafe DllImportSearchPath value {0}</target>
<note />
</trans-unit>
<trans-unit id="JsonNetInsecureSerializerMessage">
<source>When deserializing untrusted input, allowing arbitrary types to be deserialized is insecure. When using deserializing JsonSerializer, use TypeNameHandling.None, or for values other than None, restrict deserialized types with a SerializationBinder.</source>
<target state="new">When deserializing untrusted input, allowing arbitrary types to be deserialized is insecure. When using deserializing JsonSerializer, use TypeNameHandling.None, or for values other than None, restrict deserialized types with a SerializationBinder.</target>
Expand Down Expand Up @@ -122,6 +137,21 @@
<target state="translated">Pokud chcete zmenšit bezpečnostní riziko, zařaďte pole {0} jako Unicode tak, že StructLayout.CharSet na {1} nastavíte na CharSet.Unicode nebo explicitně zařadíte pole jako UnmanagedType.LPWStr. Pokud potřebujete tento řetězec zařadit jako ANSI nebo jako systémově závislý, zadejte explicitně MarshalAs a pomocí atributu BestFitMapping vypněte přizpůsobené mapování. Zabezpečení můžete ještě zvýšit tak, že zapnete ThrowOnUnmappableChar.</target>
<note />
</trans-unit>
<trans-unit id="UseDefaultDllImportSearchPathsAttribute">
<source>Use DefaultDllImportSearchPaths attribute for P/Invokes</source>
<target state="new">Use DefaultDllImportSearchPaths attribute for P/Invokes</target>
<note />
</trans-unit>
<trans-unit id="UseDefaultDllImportSearchPathsAttributeDescription">
<source>By default, P/Invokes using DllImportAttribute probe a number of directories, including the current working directory for the library to load. This can be a security issue for certain applications, leading to DLL hijacking.</source>
<target state="new">By default, P/Invokes using DllImportAttribute probe a number of directories, including the current working directory for the library to load. This can be a security issue for certain applications, leading to DLL hijacking.</target>
<note />
</trans-unit>
<trans-unit id="UseDefaultDllImportSearchPathsAttributeMessage">
<source>The method {0} didn't use DefaultDllImportSearchPaths attribute for P/Invokes.</source>
<target state="new">The method {0} didn't use DefaultDllImportSearchPaths attribute for P/Invokes.</target>
<note />
</trans-unit>
<trans-unit id="UseManagedEquivalentsOfWin32ApiTitle">
<source>Use managed equivalents of win32 api</source>
<target state="translated">Použití spravovaných ekvivalentů rozhraní Win32 API</target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,21 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="de" original="../MicrosoftNetCoreAnalyzersResources.resx">
<body>
<trans-unit id="DoNotUseUnsafeDllImportSearchPath">
<source>Do not use unsafe DllImportSearchPath value</source>
<target state="new">Do not use unsafe DllImportSearchPath value</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseUnsafeDllImportSearchPathDescription">
<source>There could be malicious DLL under the application directory or the default DLL search directories. Use an DllImportSearchPath value that sepecifies explicit search path instead</source>
<target state="new">There could be malicious DLL under the application directory or the default DLL search directories. Use an DllImportSearchPath value that sepecifies explicit search path instead</target>
<note />
</trans-unit>
<trans-unit id="DoNotUseUnsafeDllImportSearchPathMessage">
<source>Use unsafe DllImportSearchPath value {0}</source>
<target state="new">Use unsafe DllImportSearchPath value {0}</target>
<note />
</trans-unit>
<trans-unit id="JsonNetInsecureSerializerMessage">
<source>When deserializing untrusted input, allowing arbitrary types to be deserialized is insecure. When using deserializing JsonSerializer, use TypeNameHandling.None, or for values other than None, restrict deserialized types with a SerializationBinder.</source>
<target state="new">When deserializing untrusted input, allowing arbitrary types to be deserialized is insecure. When using deserializing JsonSerializer, use TypeNameHandling.None, or for values other than None, restrict deserialized types with a SerializationBinder.</target>
Expand Down Expand Up @@ -122,6 +137,21 @@
<target state="translated">Um das Sicherheitsrisiko zu verringern, marshallen Sie das Feld "{0}" als Unicode, indem Sie "StructLayout.CharSet" für "{1}" auf "CharSet.Unicode" festlegen oder das Feld explizit als "UnmanagedType.LPWStr" marshallen. Wenn Sie diese Zeichenfolge als ANSI oder systemunabhängig marshallen müssen, geben Sie MarshalAs explizit an, deaktivieren Sie die optimierte Zuordnung mithilfe des BestFitMapping-Attributs, und stellen Sie zur Erhöhung der Sicherheit sicher, dass ThrowOnUnmappableChar aktiviert ist.</target>
<note />
</trans-unit>
<trans-unit id="UseDefaultDllImportSearchPathsAttribute">
<source>Use DefaultDllImportSearchPaths attribute for P/Invokes</source>
<target state="new">Use DefaultDllImportSearchPaths attribute for P/Invokes</target>
<note />
</trans-unit>
<trans-unit id="UseDefaultDllImportSearchPathsAttributeDescription">
<source>By default, P/Invokes using DllImportAttribute probe a number of directories, including the current working directory for the library to load. This can be a security issue for certain applications, leading to DLL hijacking.</source>
<target state="new">By default, P/Invokes using DllImportAttribute probe a number of directories, including the current working directory for the library to load. This can be a security issue for certain applications, leading to DLL hijacking.</target>
<note />
</trans-unit>
<trans-unit id="UseDefaultDllImportSearchPathsAttributeMessage">
<source>The method {0} didn't use DefaultDllImportSearchPaths attribute for P/Invokes.</source>
<target state="new">The method {0} didn't use DefaultDllImportSearchPaths attribute for P/Invokes.</target>
<note />
</trans-unit>
<trans-unit id="UseManagedEquivalentsOfWin32ApiTitle">
<source>Use managed equivalents of win32 api</source>
<target state="translated">Verwaltete Entsprechungen der Win32-API verwenden</target>
Expand Down
Loading