Why is NoProfile pwsh parameter considered safer? - powershell

I read that when using a Powershell script in a scheduled task, external command or shortcuts, to always use the -NoProfile parameter. This is because otherwise Powershell will load some other profile which will be dangerous since you wouldn't know the content and can produce unexpected behaviours.
What I don't understand is, to my knowledge, by default, Powershell will run the "Current User, Current Host" profile (if I don't state -NoProfile). Since it is one of the basic profile files, why would it, or any of the other files be considered dangerous? Is it not trusted?
Links I referred to:
Link 1
Link 2

Related

Is there any way to have powershell automatically run a command anytime a command is run

I'm wanting to be able to have PowerShell automatically run a specified command anytime anything is run in PowerShell(hitting enter, any command at all). I've searched all over google with no luck finding anything except the way to have a command run on startup of powershell
If you need it a bit hidden you could do it with a ScheduledTask and Auditing Events.
Enable Auditing to get all changes logged as events
https://learn.microsoft.com/en-us/powershell/scripting/windows-powershell/wmf/whats-new/script-logging?view=powershell-7.2&viewFallbackFrom=powershell-6
Create a Scheduled Task that starts with a trigger from Events by ID. Take the IDs from the Microsoft article above. Add the command you would like to run as action. This means command is "PowerShell" and parameters are like -NonInteractive -Windowstyle minimized -c "command was executed | out-file c:\temp\activity.log"
Set it to be run as the user "system" if you want it at full permission without user interaction.
Don't forget this task to be allowed to run multiple times if you want it to.
Be aware that this might generate a lot of log entries and a lot of powershell processes depending on how log your task will run.
But in most cases the solution mentioned by Mathias R. Jessen above might be the easiest one, but is also easy to be changed by any user for the session even if you changed prompt in the settings mentioned here: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles?view=powershell-7.2

How to Automate scripts with options in Powershell?

I'm not a native English speaker as such pardon some discrepancy in my question. I'm looking at a way to Automate option selection in Programs/Scripts running via PowerShell.
For example:
Start-Process -FilePath "velociraptor.exe" -ArgumentList "config generate -i"
In the above snipper PowerShell will run Velociraptor and initiate the configuration wizard from a Ps1 file. The Wizard has few options. After running it will generate some Yaml files.
As such what would be the way to have PowerShell Script automate the option selection process? I know what the option should be. I looked around but I don't know proper terms to find what I need. Nor am I sure this can be done with PowerShell.
The end goal is to have the Ps1 download Exe, run the config command and continue with choosing the selection based on predefined choices. So far I gotten download and lunching of the velociraptor.exe working. But not sure how to skip the window in screenshot and have PowerShell script do it instead.
I couldn't find a CLI reference for velociraptor at https://www.velocidex.com/, but, generally speaking, your best bet is to find a non-interactive way to provide the information of interest, via dedicated _parameters_ (possibly pointing to an input file).
Absent that, you can use the following technique to provide successive responses to an external program's interactive prompts, assuming that the program reads the responses from stdin (the standard input stream):
$responses = 'windows', 'foo', 'bar' # List all responses here
$responses | velociraptor.exe config generate -i

Powershell command to run for everyone

I am running into a problem with a PowerShell script. I want to add a Microsoft store app with a PowerShell command:
Add-Appxpackage -path C:\Temp\whiteboard.appx
The command is working fine, but only for 1 user not for everyone. It must be installed for everyone. How can that be done?
As #WafflesAndCustard already mentioned, the issue for executing the script is the ExecutionPolicy.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7
The PowerShell-Script Execution takes another road as you probably might think of ... PS-User-Policy takes precedence over PS-Computer-Policy, but Local- (gpedit) and Domain-Policies (gpmc) overrides anything and takes the final precedence (Domain policies have highest priority)
By default -> no PowerShell Script execution is allowed.
When you want to use your script for all users, without predefining the PS-executionpolicy, you should use the native command like
powershell.exe -ExecutionPolicy ByPass -Script ....
BUT, and that's really IMPORTANT when it comes to security:
Please don't use the temp folder as this is usual something everybody can write to!
E.g. a user/program can place a malicious executable file into that folder with same name and your task (or whatever) will execute it with high privileges.

PowerShell: Start-Process Firefox, how do he know the path?

When I call the following code:
Start-Process Firefox
Then the PowerShell opens the browser. I can do that with several other programs and it works. My question is: How does the PowerShell know which program to open if I type Firefox? I mean, Im not using a concrete Path or something ...
I though it has something to do with the environment variables ... But I cannot find any variable there which is called Firefox ... How can he know?
I traced two halves of it, but I can't make them meet in the middle.
Process Monitor shows it checks the PATHs, and eventually checks HKLM\Software\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe so that's my answer to how it finds the install location, and then runs it.
That registry key is for Application Registration which says:
When the ShellExecuteEx function is called with the name of an executable file in its lpFile parameter, there are several places where the function looks for the file. We recommend registering your application in the App Paths registry subkey.
The file is sought in the following locations:
The current working directory.
The Windows directory only (no subdirectories are searched).
The Windows\System32 directory.
Directories listed in the PATH environment variable.
Recommended: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths
That implies PowerShell calls the Windows ShellExecuteEx function, which finds FireFox as a registered application, or it tries the same kind of searching itself internally.
Going the other way to try and confirm that, the Start-Process cmdlet has a parameter set called UseShellExecute. The 'Notes' of that help says:
This cmdlet is implemented by using the Start method of the System.Diagnostics.Process class. For more information about this method, see Process.Start Method
Trying to trace through the source code on GitHub:
Here is the PowerShell source code for Start-Process.
Here, at this line it tries to look up the $FilePath parameter with CommandDiscovery.LookupCommandInfo.
Here it checks else if (ParameterSetName.Equals("UseShellExecute"))
Then Here is the .Start() function which either starts it with ShellExecute or Process.Start()
OK, not sure if ShellExecute and ShellExecuteEx behave the same, but it could be PS calling Windows, which is doing the search for "FireFox".
That CommandSearcher.LookupCommandInfo comes in here and follows to TryNormalSearch() which is implemented here and immediately starts a CommandSearcher which has a state machine for the things it will search
SearchState.SearchingAliases
Functions
CmdLets
SearchingBuiltinScripts
StartSearchingForExternalCommands
PowerShellPathResolution
QualifiedFileSystemPath
and there I get lost. I can't follow it any further right now.
Either it shortcuts straight to Windows doing the lookup
Or the PowerShell CommandSearcher does the same search somehow
Or the PowerShell CommandSearcher in some way runs out of searching, and the whole thing falls back to asking Windows search.
The fact that Process Monitor only logs one query in each PATH folder for "firefox.*" and then goes to the registry key suggests it's not doing this one, or I'd expect many more lookups.
The fact that it logs one query for "get-firefox.*" in each PATH folder suggests it is PowerShell's command searcher doing the lookup and not Windows.
Hmm.
Using Process Monitor I was able to trace the PowerShell.
It first searches the $env:path variable, then the $profile variable.
In my case firefox wasn't found and then it searches through a whole lot in the Registry and somehow finds it.
It might have something to do with how firefox is installed on the system.

Run Executable File Without UAC Popup as Administrator

I am running a large study where we have staff in various countries collecting information on tablet computers running Windows 10 Enterprise. Each staff member is assigned to a tablet and they log into the tablet with their standard username and password. These users do not have local admin rights on the machines, but all tablets have a single Administrator Username and Password which I know and these are uniform across the tablets.
Each night, users invoke a program on their tablets that uploads data to our servers and then we pass information back to the tablet during this synchronization process. Otherwise, they are disconnected from the internet. At the end of the synchronization process a program is executed that allows me to run any script I like, but the script executes under the standard user account (i.e. without elevated privileges).
I need to update all the tablets with a bug fix for software that they use on the tablets and I'd like to do this during the synchronization process. The bug fix is contained in a simple executable file that can be easily pushed to the staff memebers' tablets along with any code I like during the sync. If users were running the synchronization program as administrators, this wouldn't a problem as I could simply run the executable via a script at the end of the synchronization. But they aren't, so I'm trying to find a way that I could run a script (I don't really care what it is. It could be a windows batch file, a vbs script, VB.NET, powershell, etc.) and have that script execute with administrative privileges and run the installation without the UAC prompt interfering.
I don't even mind supplying the admin password in plaintext to be honest, since these users are all our employees and they can't really do anything really concerning to us with it (and I could always deploy a subsequent file through the synchronization process to delete the program that has the password in it). I realize this sounds somewhat complicated, but in a nutshell, I'd like to carry out these steps:
Send the bug update executable to the tablet computer (I can do this now)
Develop custom code, that will pass admin credentials to the tablet and install the executable in 1 without having the UAC appear (I can send the script to the tablet during sync but do not know how to execute it as the Admin without getting the UAC prompt).
Any ideas how I can do this? I've explored this all day with minimal success using PowerShell scripts like the ones described here and here. This was the closest I got after storing the credentials in $cred, but it continued to give me the UAC prompt:
Start-Process PowerShell.exe -Cred $cred -ArgumentList '-command &{Start-Process -FilePath C:\MySyncPath\BugFix32.exe -Verb runas}]
UPDATE
After some additional work, I think I'd be able to get this to run if I could somehow disable to UAC control with a script that can run under the regular user's account and pass the admin credentials to it. Any idea how I might be able to accomplish this? If I could get this to work, even with a reboot, I'd be able to accomplish what I need.
The actual issue you're having is that you want to update your application, but the application is in the Program Files folder (or some other location that standard users are not allowed to modify).
In order to allow any user the ability to update your program, you must grant all users Full Control to your folder. Ideally your application's installer would have done this adjustment to the DACL during installation (when the installer was running as an administrator).
For now you will have to settle for a final one-time requirement that the users elevate to administrator. Then you can disable all security on your application - allowing any user (malicious or not) to modify your application at will.
GrantEveryoneFullControlToFileOrFolder("C:\Program Files\Contoso");
with a pseudocode implementation of:
void GrantAllUsersFullControlToFileOrFolder(String path)
{
PACL oldDACL;
PACL newDACL;
PSECURITY_DESCRIPTOR sd;
//Get the current DALC (Discretionary Access Control List) and Security Descriptor
GetNamedSecurityInfo(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
nil, nil, ref oldDACL, nil, ref sd);
//Create an SID for the "Users" group
PSID usersSid = StringToSid("S-1-5-32-545");
// Initialize an EXPLICIT_ACCESS structure for the new Access Control Entry (ACE)
EXPLICIT_ACCESS ea;
ZeroMemory(#ea, SizeOf(EXPLICIT_ACCESS));
ea.grfAccessPermissions = GENERIC_ALL;
ea.grfAccessMode = GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE;
ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP;
ea.Trustee.ptstrName = PChar(usersSID);
// Create a new ACL that merges the new ACE into the existing ACL.
// SetEntriesInAcl takes care of adding the ACE in the correct order in the list
SetEntriesInAcl(1, #ea, oldDACL, ref newDACL); //use LocalFree to free returned newDACL
//Attach the new ACL as the object's new DACL
SetNamedSecurityInfo(path, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION,
nil, nil, newDACL, nil);
LocalFree(HLOCAL(sd));
LocalFree(HLOCAL(newDACL));
FreeSid(usersSID);
}
It's not completely unheard of for applications to be modifiable by any user: Most MMOs install updates while you play. MMOs usually have a shim applied by Microsoft that gives all users control of the application folder.
run the script as a domain admin account... and set execution policy before the script is run, then run as administrator... some applications are picky about UAC still, but Set-ExecutionPolicy [bypass/remotesigned] will ensure that you're not prompted. however, sharing and permissions may still be an issue if the domain admin account doesn't have access to the share. psexec does this, but it's literally a matter of doing what i just mentioned and the psexec file essentially writes out the permissions by the end of the script. the intent was to make sure that passwords weren't written in clear text, it hashes the password value. either way, if you want this done securely, using a GPO and making sure your file permissions/share is at the highest level might iterate out the prompt. that's why you'll see some batch files use %1 %2 %3 %4 %5 %6 %7 %8 %9 .... that's because it's automatically requesting elevation and will loop in an iterative cycle until the UAC prompt isn't necessary.
i know i'm bumping an old thread, but this is what i've found, trying to mix and match legacy cmd batches with powershell ... lots to consider about the execution policy leading into the call vs during the call...
This question is in the category of "when people ask for security holes as features".
You cannot bypass (or, if you prefer this phrasing, "programmatically accept") the UAC prompt and automatically elevate without interactive confirmation. UAC is designed specifically to prevent this. (If this were possible, all malware would do it.)
This isn't a PowerShell thing but a general windows 10 thing. You'd need to disable UAC for this. No experience with it on Windows 10 yet though.
You can try setting the EnableLUA registry key to 0. The key can be found in:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
This will probably need a reboot to be active though.