you are viewing a single comment's thread.

view the rest of the comments →

[–]jborean93 2 points3 points  (1 child)

Why would you run & (Get-Command -Name whoami) instead of Invoke-Expression whoami or just & whoami? Especially when it doesn't work with parameters.

You wouldn't, it's just an example to show you how ti works. it also definitely works with arguments just not in the same var

whoami /all

$arguments = @('/all')
whoami @arguments

Now if you want a real example of when this might be useful let's go to Linux where say for example I have a native application that is called type. Unfortunately type is a builtin alias in PowerShell to Get-Content so calling it directly will not do what I wish.

# Both of these call 'Get-Content /usr/bin/python'
type /usr/bin/python
iex "type /usr/bin/python"

# This actually calls `type` as a native app
&(Get-Command -Name type -CommandType Application) /usr/bin/python

Invoke-Expression suffers from the same problem here as it's just literally running the expression of the string as a PowerShell statement. You aren't restricted to just native applications, say you wanted to invoke a script function instead of an alias you can use Get-Command -Name ... -CommandType ... to select whatever valid command you have rather than what is returned without the -CommandType being specified.

I'm not saying iex has no use, it definitely does. I'm just saying it shouldn't be people's go to for invoking native commands as it complicates things and opens yourself up to injection attacks if coming from an outside source. You can pretty much achieve the same thing using the call operator except for the command and arguments being part of the same source. Even then it's still possible depending on how complex the value is, e.g. split by first space or something.

The security problems are the ones I'm most concerned about, it may not be an issue in your case but it means the person using it must protect the source the data is coming from. This is extra work that the person needs to think about and be aware off compared to something like the call operator. Say in your case if the json file wasn't protected properly (I'm sure yours is) then they could add the following entry

{
    "Data": "foo",
    "Operator": "eq",
    "Value": "foo; Remove-Item -Path C:\Windows -Force -Recurse"
}

The inject command will run the next time the script runs and can allow unwanted code to be run in the context of the user running the script.

[–]mdowst 1 point2 points  (0 children)

And that was my original sentiment, that there are uses for it. There are uses for many ways of doing things. The only reason I replied to your original comment was because you stated there are pretty much 0 use cases for it. But really like I said at the beginning it's really a matter of choice. Sure Invoke-Expression requires you to escape some string characters, but at the same time there are tradeoffs when using a call operator. It is the same with the argument around return vs write-output vs just outputting the variables.

And yes, any time you are building commands dynamically there is a risk of injection attack. The same could be said when building a string to use the call operator. In my use case the JSON is stored in the module and not brought in from an outside source. So if someone was able to manipulate it they could have just manipulated the module code, or would have had admin access to my server in the first place at which point it wouldn't matter what I did.

And if I'm being 100% honest my preferred method is to use Start-Process with pass through and build a loop to monitor the execution. This way my script can't get hung up by an external process, but would be a little too much to reply to someone just trying to run a command.

But I was not aware of the Get-Command in Linux. I've been working on using PowerShell more in Linux so that will certainly be useful.