mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Fix 4 issues for the WDAC logging feature (#20913)
This commit is contained in:
@@ -3986,44 +3986,46 @@ namespace System.Management.Automation
|
||||
// - It's in FullLanguage but not because it's part of a parameter binding that is transitioning from ConstrainedLanguage to FullLanguage
|
||||
// When this is invoked from a parameter binding in transition from ConstrainedLanguage environment to FullLanguage command, we disallow
|
||||
// the property conversion because it's dangerous.
|
||||
if (ecFromTLS == null || (ecFromTLS.LanguageMode == PSLanguageMode.FullLanguage && !ecFromTLS.LanguageModeTransitionInParameterBinding))
|
||||
bool canProceedWithConversion = ecFromTLS == null || (ecFromTLS.LanguageMode == PSLanguageMode.FullLanguage && !ecFromTLS.LanguageModeTransitionInParameterBinding);
|
||||
if (!canProceedWithConversion)
|
||||
{
|
||||
result = _constructor();
|
||||
var psobject = valueToConvert as PSObject;
|
||||
if (psobject != null)
|
||||
if (SystemPolicy.GetSystemLockdownPolicy() != SystemEnforcementMode.Audit)
|
||||
{
|
||||
// Use PSObject properties to perform conversion.
|
||||
SetObjectProperties(result, psobject, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, formatProvider, recursion, ignoreUnknownMembers);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use provided property dictionary to perform conversion.
|
||||
// The method invocation is disabled for "Hashtable to Object conversion" (Win8:649519), but we need to keep it enabled for New-Object for compatibility to PSv2
|
||||
IDictionary properties = valueToConvert as IDictionary;
|
||||
SetObjectProperties(result, properties, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, enableMethodCall: false);
|
||||
throw InterpreterError.NewInterpreterException(
|
||||
valueToConvert,
|
||||
typeof(RuntimeException),
|
||||
errorPosition: null,
|
||||
"HashtableToObjectConversionNotSupportedInDataSection",
|
||||
ParserStrings.HashtableToObjectConversionNotSupportedInDataSection,
|
||||
resultType.ToString());
|
||||
}
|
||||
|
||||
typeConversion.WriteLine("Constructor result: \"{0}\".", result);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Audit)
|
||||
{
|
||||
SystemPolicy.LogWDACAuditMessage(
|
||||
// When in audit mode, we report but don't enforce, so we will proceed with the conversion.
|
||||
SystemPolicy.LogWDACAuditMessage(
|
||||
context: ecFromTLS,
|
||||
title: ExtendedTypeSystem.WDACHashTypeLogTitle,
|
||||
message: StringUtil.Format(ExtendedTypeSystem.WDACHashTypeLogMessage, resultType.FullName),
|
||||
fqid: "LanguageHashtableConversionNotAllowed",
|
||||
dropIntoDebugger: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
RuntimeException rte = InterpreterError.NewInterpreterException(valueToConvert, typeof(RuntimeException), null,
|
||||
"HashtableToObjectConversionNotSupportedInDataSection", ParserStrings.HashtableToObjectConversionNotSupportedInDataSection, resultType.ToString());
|
||||
throw rte;
|
||||
}
|
||||
}
|
||||
|
||||
result = _constructor();
|
||||
var psobject = valueToConvert as PSObject;
|
||||
if (psobject != null)
|
||||
{
|
||||
// Use PSObject properties to perform conversion.
|
||||
SetObjectProperties(result, psobject, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, formatProvider, recursion, ignoreUnknownMembers);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use provided property dictionary to perform conversion.
|
||||
// The method invocation is disabled for "Hashtable to Object conversion" (Win8:649519), but we need to keep it enabled for New-Object for compatibility to PSv2
|
||||
IDictionary properties = valueToConvert as IDictionary;
|
||||
SetObjectProperties(result, properties, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, enableMethodCall: false);
|
||||
}
|
||||
|
||||
typeConversion.WriteLine("Constructor result: \"{0}\".", result);
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (TargetInvocationException ex)
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Management.Automation.Internal;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using System.Management.Automation.Runspaces.Internal;
|
||||
using System.Management.Automation.Security;
|
||||
|
||||
using Dbg = System.Management.Automation.Diagnostics;
|
||||
|
||||
@@ -94,7 +95,22 @@ namespace System.Management.Automation.Remoting
|
||||
// to be parsed and evaluated on the remote session (not in the current local session).
|
||||
RemoteRunspace remoteRunspace = _runspaceRef.Value as RemoteRunspace;
|
||||
bool isConfiguredLoopback = remoteRunspace != null && remoteRunspace.IsConfiguredLoopBack;
|
||||
bool isTrustedInput = !isConfiguredLoopback && (localRunspace.ExecutionContext.LanguageMode == PSLanguageMode.FullLanguage);
|
||||
|
||||
bool inFullLanguage = context.LanguageMode == PSLanguageMode.FullLanguage;
|
||||
if (context.LanguageMode == PSLanguageMode.ConstrainedLanguage
|
||||
&& SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Audit)
|
||||
{
|
||||
// In audit mode, report but don't enforce.
|
||||
inFullLanguage = true;
|
||||
SystemPolicy.LogWDACAuditMessage(
|
||||
context: context,
|
||||
title: RemotingErrorIdStrings.WDACGetPowerShellLogTitle,
|
||||
message: RemotingErrorIdStrings.WDACGetPowerShellLogMessage,
|
||||
fqid: "GetPowerShellMayFail",
|
||||
dropIntoDebugger: true);
|
||||
}
|
||||
|
||||
bool isTrustedInput = !isConfiguredLoopback && inFullLanguage;
|
||||
|
||||
// Create PowerShell from ScriptBlock.
|
||||
ScriptBlock scriptBlock = ScriptBlock.Create(context, line);
|
||||
@@ -350,7 +366,7 @@ namespace System.Management.Automation.Remoting
|
||||
/// <param name="eventArgs"></param>
|
||||
private void HandleHostCall(object sender, RemoteDataEventArgs<RemoteHostCall> eventArgs)
|
||||
{
|
||||
System.Management.Automation.Runspaces.Internal.ClientRemotePowerShell.ExitHandler(sender, eventArgs);
|
||||
ClientRemotePowerShell.ExitHandler(sender, eventArgs);
|
||||
}
|
||||
|
||||
#region Robust Connection Support
|
||||
|
||||
@@ -2278,7 +2278,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
// Semantic checks on the using statement have already validated that there are no arbitrary expressions,
|
||||
// so we'll allow these expressions in everything but NoLanguage mode.
|
||||
|
||||
bool allowUsingExpressions = (Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage);
|
||||
bool allowUsingExpressions = Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage;
|
||||
object[] usingValuesInArray = null;
|
||||
IDictionary usingValuesInDict = null;
|
||||
|
||||
@@ -2428,7 +2428,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
// GetExpressionValue ensures that it only does variable access when supplied a VariableExpressionAst.
|
||||
// So, this is still safe to use in ConstrainedLanguage and will not result in arbitrary code
|
||||
// execution.
|
||||
bool allowVariableAccess = (Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage);
|
||||
bool allowVariableAccess = Context.SessionState.LanguageMode != PSLanguageMode.NoLanguage;
|
||||
|
||||
foreach (var varAst in paramUsingVars)
|
||||
{
|
||||
|
||||
@@ -5524,7 +5524,7 @@ namespace System.Management.Automation.Language
|
||||
return target.ThrowRuntimeError(args, moreTests, errorID, resourceString);
|
||||
}
|
||||
|
||||
string targetName = (targetValue as Type)?.FullName;
|
||||
string targetName = (targetValue as Type)?.FullName ?? targetValue?.GetType().FullName;
|
||||
SystemPolicy.LogWDACAuditMessage(
|
||||
context: context,
|
||||
title: ParameterBinderStrings.WDACBinderInvocationLogTitle,
|
||||
|
||||
@@ -714,6 +714,18 @@ namespace System.Management.Automation
|
||||
// of invoking it. So the trustworthiness is defined by the trustworthiness of the
|
||||
// script block's language mode.
|
||||
bool isTrusted = scriptBlock.LanguageMode == PSLanguageMode.FullLanguage;
|
||||
if (scriptBlock.LanguageMode == PSLanguageMode.ConstrainedLanguage
|
||||
&& SystemPolicy.GetSystemLockdownPolicy() == SystemEnforcementMode.Audit)
|
||||
{
|
||||
// In audit mode, report but don't enforce.
|
||||
isTrusted = true;
|
||||
SystemPolicy.LogWDACAuditMessage(
|
||||
context: context,
|
||||
title: ParserStrings.WDACGetSteppablePipelineLogTitle,
|
||||
message: ParserStrings.WDACGetSteppablePipelineLogMessage,
|
||||
fqid: "GetSteppablePipelineMayFail",
|
||||
dropIntoDebugger: true);
|
||||
}
|
||||
|
||||
foreach (var commandAst in pipelineAst.PipelineElements.Cast<CommandAst>())
|
||||
{
|
||||
@@ -729,7 +741,7 @@ namespace System.Management.Automation
|
||||
|
||||
var exprAst = (ExpressionAst)commandElement;
|
||||
var argument = Compiler.GetExpressionValue(exprAst, isTrusted, context);
|
||||
var splatting = (exprAst is VariableExpressionAst && ((VariableExpressionAst)exprAst).Splatted);
|
||||
var splatting = exprAst is VariableExpressionAst && ((VariableExpressionAst)exprAst).Splatted;
|
||||
commandParameters.Add(CommandParameterInternal.CreateArgument(argument, exprAst, splatting));
|
||||
}
|
||||
|
||||
@@ -797,8 +809,8 @@ namespace System.Management.Automation
|
||||
}
|
||||
|
||||
object argumentValue = Compiler.GetExpressionValue(argumentAst, isTrusted, context);
|
||||
bool spaceAfterParameter = (errorPos.EndLineNumber != argumentAst.Extent.StartLineNumber ||
|
||||
errorPos.EndColumnNumber != argumentAst.Extent.StartColumnNumber);
|
||||
bool spaceAfterParameter = errorPos.EndLineNumber != argumentAst.Extent.StartLineNumber ||
|
||||
errorPos.EndColumnNumber != argumentAst.Extent.StartColumnNumber;
|
||||
return CommandParameterInternal.CreateParameterWithArgument(commandParameterAst, commandParameterAst.ParameterName,
|
||||
errorPos.Text, argumentAst, argumentValue,
|
||||
spaceAfterParameter);
|
||||
|
||||
@@ -1361,4 +1361,10 @@ ModuleVersion : Version of module to import. If used, ModuleName must represent
|
||||
<data name="WDACParserForEachOperatorLogMessage" xml:space="preserve">
|
||||
<value>The ForEach keyword will fail '{0}' iteration item method invocation when run in Constrained Language mode.</value>
|
||||
</data>
|
||||
<data name="WDACGetSteppablePipelineLogTitle" xml:space="preserve">
|
||||
<value>Expression Evaluation May Fail</value>
|
||||
</data>
|
||||
<data name="WDACGetSteppablePipelineLogMessage" xml:space="preserve">
|
||||
<value>Creating a steppable pipeline from a script block may require evaluating some expressions within the script block. The expression evaluation will silently fail and return 'null' in Constrained Language mode, unless the expression represents a constant value.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
@@ -1714,4 +1714,10 @@ SSH client process terminated before connection could be established.</value>
|
||||
<data name="DISCUnknownConfigName" xml:space="preserve">
|
||||
<value>The session configuration file contains an unknown configuration option: {0}.</value>
|
||||
</data>
|
||||
<data name="WDACGetPowerShellLogTitle" xml:space="preserve">
|
||||
<value>Expression Evaluation May Fail</value>
|
||||
</data>
|
||||
<data name="WDACGetPowerShellLogMessage" xml:space="preserve">
|
||||
<value>Creating a PowerShell object from a script block may require evaluating some expressions within the script block. The expression evaluation will silently fail and return 'null' in Constrained Language mode, unless the expression represents a constant value.</value>
|
||||
</data>
|
||||
</root>
|
||||
|
||||
Reference in New Issue
Block a user