mirror of
https://github.com/aphrody-labs/PowerShell.git
synced 2026-10-17 12:45:47 +00:00
Strip authorization header on redirects with web cmdlets (#3885)
Invoke-WebRequest and Invoke-RestMethod cmdlets will now strip authorization header on redirect unless the new parameter `-PreserveAuthorizationOnRedirect` is specified. The FullCLR implementation uses WebRequest to perform the request which silently strips the Authorization header when a redirect occurs. The CoreCLR implementation uses HttpClient to perform the request which does not strip the authorization header. The change explicitly handles the initial redirect, removes the authorization header and submits the request to location in the response. Fixes #2227
This commit is contained in:
1 parent
26a44abcec
commit
039ed6764d
3 files changed
+372
-22
No files matched your search
@@ -143,6 +143,70 @@ function GetTestData
|
||||
return $body
|
||||
}
|
||||
|
||||
function ExecuteRedirectRequest
|
||||
{
|
||||
param (
|
||||
[Parameter(Mandatory)]
|
||||
[string]
|
||||
$uri,
|
||||
|
||||
[ValidateSet('Invoke-WebRequest', 'Invoke-RestMethod')]
|
||||
[string] $Cmdlet = 'Invoke-WebRequest',
|
||||
|
||||
[ValidateSet('POST', 'GET')]
|
||||
[string] $Method = 'GET',
|
||||
|
||||
[switch] $PreserveAuthorizationOnRedirect
|
||||
)
|
||||
$result = [PSObject]@{Output = $null; Error = $null; Content = $null}
|
||||
|
||||
try
|
||||
{
|
||||
$headers = @{"Authorization" = "test"}
|
||||
if ($Cmdlet -eq 'Invoke-WebRequest')
|
||||
{
|
||||
$result.Output = Invoke-WebRequest -Uri $uri -TimeoutSec 5 -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method
|
||||
$result.Content = $result.Output.Content | ConvertFrom-Json
|
||||
}
|
||||
else
|
||||
{
|
||||
$result.Output = Invoke-RestMethod -Uri $uri -TimeoutSec 5 -Headers $headers -PreserveAuthorizationOnRedirect:$PreserveAuthorizationOnRedirect.IsPresent -Method $Method
|
||||
# NOTE: $result.Output should already be a PSObject (Invoke-RestMethod converts the returned json automatically)
|
||||
# so simply reference $result.Output
|
||||
$result.Content = $result.Output
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
$result.Error = $_
|
||||
}
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
<#
|
||||
Defines the list of redirect codes to test as well as the
|
||||
expected Method when the redirection is handled.
|
||||
See https://msdn.microsoft.com/en-us/library/windows/apps/system.net.httpstatuscode(v=vs.105).aspx
|
||||
for additonal details.
|
||||
#>
|
||||
$redirectTests = @(
|
||||
@{redirectType = 'MultipleChoices'; redirectedMethod='POST'}
|
||||
@{redirectType = 'Ambiguous'; redirectedMethod='POST'} # Synonym for MultipleChoices
|
||||
|
||||
@{redirectType = 'Moved'; redirectedMethod='GET'}
|
||||
@{redirectType = 'MovedPermanently'; redirectedMethod='GET'} # Synonym for Moved
|
||||
|
||||
@{redirectType = 'Found'; redirectedMethod='GET'}
|
||||
@{redirectType = 'Redirect'; redirectedMethod='GET'} # Synonym for Found
|
||||
|
||||
@{redirectType = 'redirectMethod'; redirectedMethod='GET'}
|
||||
@{redirectType = 'SeeOther'; redirectedMethod='GET'} # Synonym for RedirectMethod
|
||||
|
||||
@{redirectType = 'TemporaryRedirect'; redirectedMethod='GET'}
|
||||
@{redirectType = 'RedirectKeepVerb'; redirectedMethod='GET'} # Synonym for TemporaryRedirect
|
||||
)
|
||||
|
||||
Describe "Invoke-WebRequest tests" -Tags "Feature" {
|
||||
|
||||
BeforeAll {
|
||||
@@ -223,7 +287,7 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {
|
||||
$jsonContent.headers.Host | Should Match "httpbin.org"
|
||||
$jsonContent.headers.'User-Agent' | Should Match "WindowsPowerShell"
|
||||
}
|
||||
|
||||
|
||||
It "Validate Invoke-WebRequest error for -MaximumRedirection" {
|
||||
|
||||
$command = "Invoke-WebRequest -Uri 'http://httpbin.org/redirect/3' -MaximumRedirection 2 -TimeoutSec 5"
|
||||
@@ -231,7 +295,7 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {
|
||||
$result = ExecuteWebCommand -command $command
|
||||
$result.Error.FullyQualifiedErrorId | Should Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
|
||||
}
|
||||
|
||||
|
||||
It "Invoke-WebRequest supports request that returns page containing UTF-8 data." {
|
||||
|
||||
$command = "Invoke-WebRequest -Uri http://httpbin.org/encoding/utf8 -TimeoutSec 5"
|
||||
@@ -545,6 +609,59 @@ Describe "Invoke-WebRequest tests" -Tags "Feature" {
|
||||
$result.Output.RelationLink["last"] | Should BeExactly "http://localhost:8080/PowerShell?test=linkheader&maxlinks=3&linknumber=3"
|
||||
}
|
||||
|
||||
#region Redirect tests
|
||||
|
||||
It "Validates Invoke-WebRequest with -PreserveAuthorizationOnRedirect preserves the authorization header on redirect" -TestCases $redirectTests {
|
||||
param($redirectType, $redirectedMethod)
|
||||
|
||||
$response = ExecuteRedirectRequest -Uri "http://localhost:8080/PowerShell?test=redirect&type=$redirectType" -PreserveAuthorizationOnRedirect
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
# ensure Authorization header has been preserved.
|
||||
$response.Content.Headers -contains "Authorization" | Should Be $true
|
||||
}
|
||||
|
||||
|
||||
It "Validates Invoke-WebRequest preserves the authorization header on multiple redirects." -TestCases $redirectTests {
|
||||
param($redirectType)
|
||||
|
||||
$response = ExecuteRedirectRequest -Uri "http://localhost:8080/PowerShell?test=redirect&type=$redirectType&multiredirect=true" -PreserveAuthorizationOnRedirect
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
# ensure Authorization header was stripped
|
||||
$response.Content.Headers -contains "Authorization" | Should Be $true
|
||||
}
|
||||
|
||||
It "Validates Invoke-WebRequest strips the authorization header on various redirects" -TestCases $redirectTests {
|
||||
param($redirectType)
|
||||
|
||||
$response = ExecuteRedirectRequest -Uri "http://localhost:8080/PowerShell?test=redirect&type=$redirectType"
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
# ensure user-agent is present (i.e., no false positives )
|
||||
$response.Content.Headers -contains "User-Agent" | Should Be $true
|
||||
# ensure Authorization header has been removed.
|
||||
$response.Content.Headers -contains "Authorization" | Should Be $false
|
||||
}
|
||||
|
||||
# NOTE: Only testing redirection of POST -> GET for unique underlying values of HttpStatusCode.
|
||||
# Some names overlap in underlying value.
|
||||
It "Validates Invoke-WebRequest strips the authorization header redirects and switches from POST to GET when it handles the redirect" -TestCases $redirectTests {
|
||||
param($redirectType, $redirectedMethod)
|
||||
|
||||
$response = ExecuteRedirectRequest -Uri "http://localhost:8080/PowerShell?test=redirect&type=$redirectType" -Method 'POST'
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
# ensure user-agent is present (i.e., no false positives )
|
||||
$response.Content.Headers -contains "User-Agent" | Should Be $true
|
||||
# ensure Authorization header has been removed.
|
||||
$response.Content.Headers -contains "Authorization" | Should Be $false
|
||||
# ensure POST was changed to GET for selected redirections and remains as POST for others.
|
||||
$response.Content.HttpMethod | Should Be $redirectedMethod
|
||||
}
|
||||
|
||||
#endregion Redirect tests
|
||||
|
||||
BeforeEach {
|
||||
if ($env:http_proxy) {
|
||||
$savedHttpProxy = $env:http_proxy
|
||||
@@ -955,6 +1072,58 @@ Describe "Invoke-RestMethod tests" -Tags "Feature" {
|
||||
$result.Output.output | Should BeExactly 1
|
||||
}
|
||||
|
||||
#region Redirect tests
|
||||
|
||||
It "Validates Invoke-RestMethod with -PreserveAuthorizationOnRedirect preserves the authorization header on redirect" -TestCases $redirectTests {
|
||||
param($redirectType, $redirectedMethod)
|
||||
|
||||
$response = ExecuteRedirectRequest -Cmdlet 'Invoke-RestMethod' -Uri "http://localhost:8081/PowerShell?test=redirect&type=$redirectType" -PreserveAuthorizationOnRedirect
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
# ensure Authorization header has been preserved.
|
||||
$response.Content.Headers -contains "Authorization" | Should Be $true
|
||||
}
|
||||
|
||||
It "Validates Invoke-RestMethod preserves the authorization header on multiple redirects." -TestCases $redirectTests {
|
||||
param($redirectType)
|
||||
|
||||
$response = ExecuteRedirectRequest -Cmdlet 'Invoke-RestMethod' -Uri "http://localhost:8081/PowerShell?test=redirect&type=$redirectType&multiredirect=true" -PreserveAuthorizationOnRedirect
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
# ensure Authorization header was stripped
|
||||
$response.Content.Headers -contains "Authorization" | Should Be $true
|
||||
}
|
||||
|
||||
It "Validates Invoke-RestMethod strips the authorization header on various redirects" -TestCases $redirectTests {
|
||||
param($redirectType)
|
||||
|
||||
$response = ExecuteRedirectRequest -Cmdlet 'Invoke-RestMethod' -Uri "http://localhost:8081/PowerShell?test=redirect&type=$redirectType"
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
# ensure user-agent is present (i.e., no false positives )
|
||||
$response.Output.Headers -contains "User-Agent" | Should Be $true
|
||||
# ensure Authorization header has been removed.
|
||||
$response.Content.Headers -contains "Authorization" | Should Be $false
|
||||
}
|
||||
|
||||
# NOTE: Only testing redirection of POST -> GET for unique underlying values of HttpStatusCode.
|
||||
# Some names overlap in underlying value.
|
||||
It "Validates Invoke-RestMethod strips the authorization header redirects and switches from POST to GET when it handles the redirect" -TestCases $redirectTests {
|
||||
param($redirectType, $redirectedMethod)
|
||||
|
||||
$response = ExecuteRedirectRequest -Cmdlet 'Invoke-RestMethod' -Uri "http://localhost:8081/PowerShell?test=redirect&type=$redirectType" -Method 'POST'
|
||||
|
||||
$response.Error | Should BeNullOrEmpty
|
||||
# ensure user-agent is present (i.e., no false positives )
|
||||
$response.Content.Headers -contains "User-Agent" | Should Be $true
|
||||
# ensure Authorization header has been removed.
|
||||
$response.Content.Headers -contains "Authorization" | Should Be $false
|
||||
# ensure POST was changed to GET for selected redirections and remains as POST for others.
|
||||
$response.Content.HttpMethod | Should Be $redirectedMethod
|
||||
}
|
||||
|
||||
#endregion Redirect tests
|
||||
|
||||
BeforeEach {
|
||||
if ($env:http_proxy) {
|
||||
$savedHttpProxy = $env:http_proxy
|
||||
|
||||
Reference in new issue
Block a user