Merged PR 6561: Add security mitigations for 6.1.3 release

This commit is contained in:
Paul Higinbotham
2019-02-12 20:36:33 +00:00
committed by Travis Plunk
parent f40eb9878f
commit 61ed206e1e
10 changed files with 430 additions and 4 deletions
@@ -1401,6 +1401,80 @@ try
$module.ExportedCommands.Values[0].Name | Should -BeExactly 'PublicFn'
}
}
Describe "New-Module should not create module from trusted scriptblock when running in ConstrainedLanguage context" -Tags 'Feature','RequireAdminOnWindows' {
BeforeAll {
$script = @'
function ScriptFn { Write-Output $ExecutionContext.SessionState.LanguageMode }
'@
$scriptFileNameT = "NewModuleTrustedScriptBlock_System32"
$scriptFilePathT = Join-Path $TestDrive ($scriptFileNameT + ".ps1")
$script | Out-File -FilePath $scriptFilePathT
$scriptFileNameU = "NewModuleUntrustedScriptBlock"
$scriptFilePathU = Join-Path $TestDrive ($scriptFileNameU + ".ps1")
$script | Out-File -FilePath $scriptFilePathU
}
It "New-Module throws error when creating module with trusted scriptblock in ConstrainedLanguage" {
$expectedError = $null
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
# Get scriptblock from trusted script file
$sb = (Get-Command $scriptFilePathT).ScriptBlock
# Create new module from trusted scriptblock while in ConstrainedLanguage
try
{
New-Module -Name TrustedScriptFoo -ScriptBlock $sb
throw "No Exception!"
}
catch
{
$expectedError = $_
}
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError.FullyQualifiedErrorId | Should -BeExactly "Modules_CannotCreateModuleWithFullLanguageScriptBlock,Microsoft.PowerShell.Commands.NewModuleCommand"
}
It "New-Module succeeds in creating module with untrusted scriptblock in ConstrainedLanguage" {
$result = $null
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
# Get scriptblock from untrusted script file
$sb = (Get-Command $scriptFilePathU).ScriptBlock
# Create and import module from scriptblock
$m = New-Module -Name UntrustedScriptFoo -ScriptBlock $sb
Import-Module -ModuleInfo $m -Force
$result = ScriptFn
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$result | Should -BeExactly "ConstrainedLanguage"
}
}
}
finally
{
@@ -988,6 +988,292 @@ try
}
}
Describe "Dot sourced script block functions from trusted script files should not run FullLanguage in ConstrainedLanguage context" -Tags 'Feature','RequireAdminOnWindows' {
BeforeAll {
$scriptFileName = "TrustedScriptBlockTest_System32"
$scriptFilePath = Join-Path $TestDrive ($scriptFileName + ".ps1")
@'
function TrustedFn {
Write-Output $ExecutionContext.SessionState.LanguageMode
}
'@ | Out-File -FilePath $scriptFilePath
$scriptModuleName = "UntrustedModuleScriptBlockTest"
$scriptModulePath = Join-Path $TestDrive ($scriptModuleName + ".psm1")
@'
function RunScriptBlock {{
$sb = (Get-Command -Name {0}).ScriptBlock
# ScriptBlock trusted function, TrustedFn, is dot sourced into current scope
1 | ForEach-Object $sb
TrustedFn
}}
'@ -f $scriptFilePath | Out-File -FilePath $scriptModulePath
}
It "Verifies a scriptblock from a trusted script file does not run as trusted" {
$result = $null
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
# Import untrusted module
Import-Module -Name $scriptModulePath -Force
# Run module function that dot sources TrustedFn and runs it in module scope
$result = RunScriptBlock
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
# Ensure scriptblock TrustedFn function ran as untrusted
$result | Should -BeExactly "ConstrainedLanguage"
}
}
Describe "Dot sourcing trusted script in ConstrainedLanguage context is allowed when importing modules" -Tags 'Feature','RequireAdminOnWindows' {
BeforeAll {
$importModuleName = "ToImportTrustedModuleTest_System32"
$importModulePath = Join-Path $TestDrive ($importModuleName + ".psm1")
$modScript = @'
function ImportModuleFn { "ImportModuleFn: $($ExecutionContext.SessionState.LanguageMode)" }
Export-ModuleMember -Function "ImportModuleFn"
'@ | Out-File -FilePath $importModulePath
$scriptModuleName = "ImportTrustedModuleTest_System32"
$scriptModulePath = Join-Path $TestDrive ($scriptModuleName + ".psm1")
@'
Import-Module -Name {0} -Force
function ModuleFn {{ "ModuleFn: $($ExecutionContext.SessionState.LanguageMode)" }}
Export-ModuleMember -Function "ModuleFn","ImportModuleFn"
'@ -f $importModulePath | Out-File -FilePath $scriptModulePath
}
It "Verifies that trusted module functions run in FullLanguage" {
$result1 = $null
$result2 = $null
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
Import-Module -Name $scriptModulePath -Force
$result1 = ModuleFn
$result2 = ImportModuleFn
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$result1 | Should -BeExactly "ModuleFn: FullLanguage"
$result2 | Should -BeExactly "ImportModuleFn: FullLanguage"
}
}
Describe "PowerShell classes are not allowed in constrained language mode" -Tags 'Feature','RequireAdminOnWindows' {
BeforeAll {
$randomClassName = "class_$(Get-Random -Max 9999)"
$script = @'
class {0} {{ static Hello([string] $msg) {{ [System.Console]::WriteLine("Hello from: $msg") }} }}
'@ -f $randomClassName
$modulePathName = "modulePath_$(Get-Random -Max 9999)"
$modulePath = Join-Path $testdrive $modulePathName
New-Item -Path $modulePath -ItemType Directory -Force
$untrustedScriptFile = Join-Path $modulePath "T1ScriptClass.ps1"
$script | Out-File -FilePath $untrustedScriptFile
$untrustedScriptModule = Join-Path $modulePath "T1ScriptClass.psm1"
$script | Out-File -FilePath $untrustedScriptModule
$trustedScriptFile = Join-Path $modulePath "T1ScriptClass_System32.ps1"
$script | Out-File -FilePath $trustedScriptFile
$trustedScriptModule = Join-Path $modulePath "T1ScriptClass_System32.psm1"
$script | Out-File -FilePath $trustedScriptModule
}
AfterAll {
Remove-Module -Name T1ScriptClass_System32 -Force -ErrorAction Ignore
}
It "Verifies that classes cannot be created in script running under constrained language" {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
Invoke-Expression -Command $script 2>$null -ErrorAction Stop
throw "No Error!"
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$expectedError.FullyQualifiedErrorId | Should -BeExactly "ClassesNotAllowedInConstrainedLanguage,Microsoft.PowerShell.Commands.InvokeExpressionCommand"
}
It "Verifies that classes cannot be created in script files running under constrained language" {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
& ($untrustedScriptFile)
throw "No Error!"
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -EnableFullLanguageMode -RevertLockdownMode
}
$expectedError.FullyQualifiedErrorId | Should -BeExactly "ClassesNotAllowedInConstrainedLanguage"
}
It "Verifies that classes cannot be created in untrusted script modules running under constrained language" {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
Import-Module -Name $untrustedScriptModule -ErrorAction Stop
throw "No Error!"
}
catch
{
$expectedError = $_
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -EnableFullLanguageMode -RevertLockdownMode
}
$expectedError.FullyQualifiedErrorId | Should -BeExactly "ClassesNotAllowedInConstrainedLanguage"
}
It "Verifies that classes can be created in trusted script files running under constrained language" {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
{ & ($trustedScriptFile) } | Should -Not -Throw
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -EnableFullLanguageMode -RevertLockdownMode
}
}
It "Verifies that classes can be created in trusted script modules running under constrained language" {
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
{ Import-Module -Name $trustedScriptModule -ErrorAction Stop } | Should -Not -Throw
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -EnableFullLanguageMode -RevertLockdownMode
}
}
}
Describe "Invoke-History should not run command lines in FullLanguage mode when system is locked down" -Tags 'Feature','RequireAdminOnWindows' {
BeforeAll {
$LanguageModeHistoryFilePath = Join-Path $TestDrive "LanguageModeHistory.XML"
# $ExecutionContext.SessionState.LanguageMode command line history item clixml
@'
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>Microsoft.PowerShell.Commands.HistoryInfo</T>
<T>System.Object</T>
</TN>
<ToString>$ExecutionContext.SessionState.LanguageMode</ToString>
<Props>
<I64 N="Id">123</I64>
<S N="CommandLine">$ExecutionContext.SessionState.LanguageMode</S>
<Obj N="ExecutionStatus" RefId="1">
<TN RefId="1">
<T>System.Management.Automation.Runspaces.PipelineState</T>
<T>System.Enum</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>Completed</ToString>
<I32>4</I32>
</Obj>
<DT N="StartExecutionTime">2018-07-26T14:36:33.923608-07:00</DT>
<DT N="EndExecutionTime">2018-07-26T14:36:33.9266018-07:00</DT>
</Props>
</Obj>
</Objs>
'@ | Out-File -FilePath $LanguageModeHistoryFilePath
$historyItem = Import-Clixml -Path $LanguageModeHistoryFilePath
}
It "Verifies that Invoke-History runs command lines in ConstrainedLanguage" {
$result = $null
try
{
Invoke-LanguageModeTestingSupportCmdlet -SetLockdownMode
$ExecutionContext.SessionState.LanguageMode = "ConstrainedLanguage"
# Add "$ExecutionContext.SessionState.LanguageMode" command line to history
$historyItem | Add-History
# Retrieve history item command and invoke
$retrievedItem = Get-History -Count 1
$result = $retrievedItem | Invoke-History
}
finally
{
Invoke-LanguageModeTestingSupportCmdlet -RevertLockdownMode -EnableFullLanguageMode
}
$result | Should -BeExactly "ConstrainedLanguage"
}
}
# End Describe blocks
}
finally