Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invoke-Restmethod broken by tab character after the header parameter variable #15943

Closed
5 tasks done
JamesLear92 opened this issue Aug 17, 2021 · 21 comments
Closed
5 tasks done
Labels
Resolution-No Activity Issue has had no activity for 6 months or more WG-Engine core PowerShell engine, interpreter, and runtime

Comments

@JamesLear92
Copy link

JamesLear92 commented Aug 17, 2021

Prerequisites

Steps to reproduce

The Invoke-Restmethod command fails to cast the header parameter to System.Collections.IDictionary if the following scenarios are true:
You are storing your header as a hashtable variable
You have a tab character between the variable name of the hashtable, and the next parameter

With a space character between "-Headers $Headers" and "-ContentType 'application/json'" it works fine, but with a tab character, somewhere in Powershell it's removing the tab and messing up the cast.

Take the following code and run it. It should return fine. However, if you then copy this into VsCode, and remove the space after '-Headers $Headers' and instead put a tab in, then copy it into a powershell window and it will fail.

$Headers = @{
    "method"           = "POST"
    "sec-ch-ua"        = '"Chromium";v="92", " Not A;Brand";v="99", "Microsoft Edge";v="92"'
    "accept"           = "*/*"
}
Invoke-RestMethod -Uri 'http://dummy.restapiexample.com/api/v1/create' -Method 'POST' -Headers $Headers -ContentType 'application/json' -Body '{"name":"test","salary":"123","age":"23"}' 

When copied into a new powershell window, it appears that the character between $headers and -ContentType is [char]9 which is the ascii code for a tab character.

The error message:

Cannot bind parameter 'Headers'. Cannot convert the "System.Collections.Hashtable-ContentType"

Shows to me, that the character is being removed, and somehow the next parameter is treated as if it's part of the type name of the header object type.
If you rearrange the parameters so that body is the parameter in front of $header with a tab between, then you get the error message:

Cannot bind parameter 'Headers'. Cannot convert the "System.Collections.Hashtable-Body"

Issue occurs in both PowerShell 5.1, and PowerShell 7.14. Issue does not occur when debugging in VSCode, likely because tabs are converted to spaces?

Expected behavior

$Headers = @{
	"method"           = "POST"
	"sec-ch-ua"        = '"Chromium";v="92", " Not A;Brand";v="99", "Microsoft Edge";v="92"'
	"accept"           = "*/*"
}
Invoke-RestMethod -Uri 'http://dummy.restapiexample.com/api/v1/create' -Method 'POST' -Headers $Headers	-ContentType 'application/json' -Body '{"name":"test","salary":"123","age":"23"}'


status  data                                     message
------  ----                                     -------
success @{name=test; salary=123; age=23; id=978} Successfully! Record has been added.

Actual behavior

$Headers = @{
	"method"           = "POST"
	"sec-ch-ua"        = '"Chromium";v="92", " Not A;Brand";v="99", "Microsoft Edge";v="92"'
	"accept"           = "*/*"
}
Invoke-RestMethod -Uri 'http://dummy.restapiexample.com/api/v1/create' -Method 'POST' -Headers $Headers	-ContentType 'application/json' -Body '{"name":"test","salary":"123","age":"23"}'

Invoke-RestMethod : Cannot bind parameter 'Headers'. Cannot convert the "System.Collections.Hashtable-ContentType"
value of type "System.String" to type "System.Collections.IDictionary".
At line:1 char:107
+ ... m/api/v1/create' -Method 'POST' -Headers $Headers-ContentType 'applic ...
+                                              ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Invoke-RestMethod], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Error details

Invoke-RestMethod : Cannot bind parameter 'Headers'. Cannot convert the "System.Collections.Hashtable-ContentType"
value of type "System.String" to type "System.Collections.IDictionary".
At line:1 char:107
+ ... m/api/v1/create' -Method 'POST' -Headers $Headers-ContentType 'applic ...
+                                              ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Invoke-RestMethod], ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Environment data

Name                           Value
----                           -----
PSVersion                      5.1.22000.65
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.22000.65
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Name                           Value
----                           -----
PSVersion                      7.1.4
PSEdition                      Core
GitCommitId                    7.1.4
OS                             Microsoft Windows 10.0.22000
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

@JamesLear92 JamesLear92 added the Needs-Triage The issue is new and needs to be triaged by a work group. label Aug 17, 2021
@iSazonov iSazonov added the WG-Engine core PowerShell engine, interpreter, and runtime label Aug 17, 2021
@rjmholt
Copy link
Collaborator

rjmholt commented Aug 17, 2021

I just tried to reproduce this, but haven't been able to so far:

image

image

Can you provide a hex dump or file attachment that reproduces the error? I'm wondering if rather than a tab, it's registering as something more exotic in unicode...

For the record, the tokenizer reads whitespace here:

if (c.IsWhitespace())
{
SkipWhiteSpace();
goto again;
}

That method is implemented here.

@vexx32
Copy link
Collaborator

vexx32 commented Aug 17, 2021

I recall there was also an issue with some versions of PSReadLine eating certain unicode characters under some circumstances. @JamesLear92 what version of the PSReadLine module are you currently using?

@rjmholt
Copy link
Collaborator

rjmholt commented Aug 18, 2021

Yeah, I also wonder if this could be a console/PSReadLine thing rather than a direct PowerShell issue

@iSazonov
Copy link
Collaborator

iSazonov commented Aug 18, 2021

The Tab is removed without PSRL too on Windows.

@JamesLear92
Copy link
Author

@rjmholt I made sure to test what character is present when raising the issue as I also thought it might be an exotic character. But it's definitely [char]9. The issue doesn't occur when running the script, only when pasting it into PowerShell. But I've confirmed that the character is [char]9 when pasting it into PowerShell

@JamesLear92
Copy link
Author

@vexx32
I can confirm it's also occurring when the PsReadLine module is removed, but the versions I am running are:
2.0.0 in Ps 5.1
2.1.0 in Ps 7.14

@JamesLear92
Copy link
Author

Issue is also present when using Windows Terminal 1.9.1942.0

@iSazonov
Copy link
Collaborator

/cc @DHowett

@rjmholt
Copy link
Collaborator

rjmholt commented Aug 18, 2021

I'm able to reproduce, but only with right-click paste, not Ctrl+V paste:

image

This suggests to me that the issue is external to PowerShell

@ghost ghost removed the Needs-Triage The issue is new and needs to be triaged by a work group. label Aug 18, 2021
@JamesLear92 JamesLear92 reopened this Aug 18, 2021
@vexx32
Copy link
Collaborator

vexx32 commented Aug 18, 2021

Yeah, it works fine when loading a file with the tab character... must be something with the console host, or something along those lines?

@iSazonov
Copy link
Collaborator

This suggests to me that the issue is external to PowerShell

But I don't see the issue in cmd.exe (neither standalone or Windows Terminal).

@rkeithhill
Copy link
Collaborator

Hmm, I do see the issue when right-click pasting into CMD in Windows Terminal:

image

Ditto for right-click pasting into bash in WSL/Ubuntu in Windows Terminal:

image

@JamesLear92
Copy link
Author

JamesLear92 commented Sep 1, 2021

Ok, issue is certainly the interaction between the terminal and powershell.
When using Ctrl+V, powershell itself has an event handler, and it pastes. But when using right click paste, the terminal has to type the characters to powershell.

Because tab is used for completing in PowerShell/Cmd, the tab is consumed as an autocomplete request rather than a character.
You can see this by running the following and right click pasting:

'Get-Proc' + [char]9 + 'Test' | scb

You will almost certainly get the text "Get-ProcessTest"

The issue exists also in Windows Terminal, except Ctrl+V is handled by the Terminal rather than Powershell, so the problem also occurs there.

Glad we know what the problem is. Who fixes it?

@JamesLear92
Copy link
Author

Thinking about this, this could be a huge security problem. It allows for strings to escape and execute. You can test and manufacture this exploit with the following:

'Start-Pr' + [char]9 + ' PowerShell' + [char]13 + 'Exit' + [char]13 | scb

It will generate a string in your clipboard which will start a new powershell process and close your current window (without you ever pressing enter).

@vexx32
Copy link
Collaborator

vexx32 commented Sep 1, 2021

The user still has to manually paste that string, but yes arguably it's a bit odd that those characters are not interpreted as literal characters when pasting.

@JamesLear92
Copy link
Author

@vexx32 Yeah it doesn't seem too bad, but you could have any number of tabs, tabbing to a completely different code. Going from a script you're happy to paste as plane text, to a malicious self executing string which doesn't even wait for you to see what's pasted and press enter.

You're right though that it does need to be right clicked into a powershell window.

@rjmholt
Copy link
Collaborator

rjmholt commented Sep 1, 2021

@daxian-dbw would have the most context here to offer suggestions.

However, I suspect this might be by design due to the architecture of right click to paste (and is why PSRL encourages Ctrl+V usage); I don't think there's a way for PSRL to distinguish a user-provided interactive Tab from one delivered by a right click, so they must both do the same thing.

Thinking about this, this could be a huge security problem

Once you have access to the clipboard and the ability to paste something to an arbitrary window, you're already well beyond standard security boundaries. Windows Terminal does have a defense in depth feature to try to help here:

image

But ultimately this is the clipboard version of the email attachment problem and there's only so much that can be done to prevent users from pulling the trigger on themselves. Anyway, further security discussion is best had through our security process.

As I say, I think this is an issue of right-click-to-paste being indistinguishable from direct user input, so Tab is doing exactly what it's configured to in PSRL here.

Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

2 similar comments
Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

Copy link
Contributor

This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.

@microsoft-github-policy-service microsoft-github-policy-service bot added Resolution-No Activity Issue has had no activity for 6 months or more labels Nov 16, 2023
Copy link
Contributor

This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution-No Activity Issue has had no activity for 6 months or more WG-Engine core PowerShell engine, interpreter, and runtime
Projects
None yet
Development

No branches or pull requests

6 participants
@rkeithhill @rjmholt @JamesLear92 @iSazonov @vexx32 and others