Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
56 changes: 29 additions & 27 deletions src/System.Management.Automation/engine/LanguagePrimitives.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3986,44 +3986,46 @@ internal object Convert(object valueToConvert,
// - 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)
{
// Use PSObject properties to perform conversion.
SetObjectProperties(result, psobject, resultType, CreateMemberNotFoundError, CreateMemberSetValueError, formatProvider, recursion, ignoreUnknownMembers);
}
else
if (SystemPolicy.GetSystemLockdownPolicy() != SystemEnforcementMode.Audit)
{
// 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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
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;

Expand Down Expand Up @@ -94,7 +95,22 @@ private PSCommand ParsePsCommandUsingScriptBlock(string line, bool? useLocalScop
// 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);
Expand Down Expand Up @@ -350,7 +366,7 @@ internal void Override(RemoteRunspace remoteRunspace, object syncObject, out boo
/// <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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2278,7 +2278,7 @@ private System.Management.Automation.PowerShell GetPowerShellForPSv3OrLater(stri
// 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;

Expand Down Expand Up @@ -2428,7 +2428,7 @@ private List<object> GetUsingVariableValues(List<VariableExpressionAst> paramUsi
// 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)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5524,7 +5524,7 @@ internal static DynamicMetaObject EnsureAllowedInLanguageMode(DynamicMetaObject
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,18 @@ internal static SteppablePipeline GetSteppablePipeline(PipelineAst pipelineAst,
// 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>())
{
Expand All @@ -729,7 +741,7 @@ internal static SteppablePipeline GetSteppablePipeline(PipelineAst pipelineAst,

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));
}

Expand Down Expand Up @@ -797,8 +809,8 @@ private static CommandParameterInternal GetCommandParameter(CommandParameterAst
}

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);
Expand Down
6 changes: 6 additions & 0 deletions src/System.Management.Automation/resources/ParserStrings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Original file line number Diff line number Diff line change
Expand Up @@ -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>