My company needs to activate MFA tomorrow and we need to know how to clear out all of the stored credentials in the Windows Credential Manager. The problem credential that I can't remove via Powershell is one called "SSO_POP_Device" under "Other Items".
I have a command that will remove all credentials EXCEPT the SSO_POP_Device. The code is below. I've stopped and started the CM service, which just restores what it remembered from before (still need to clear the credentials so they don't get used after MFA is active). I am aware that it can be manually removed in CM, but remember, I need a Powershell script or CMD line method of removing this for multiple users across the company. I discovered through research that this is likely tied to our Microsoft Accounts and specifically, to Office / Outlook 365.
This is the command that removes all credentials except SSO_POP_Device currently. It's pretty short.
cmdkey /list | ForEach-Object{if($_ -like "*Target:*"){cmdkey /delete:($_ -replace " ","" -replace "Target:","")}}
I would expect to be able run some Powershell or CMD line to scrub anything whatsoever from Credential Manager, regardless of where it is stored or what it's related to. Whenever I run cmdkey /list with just SSO_POP_Device remaining on the list, it returns nothing. There are no error messages except when I'm firing off random delete commands into the aether.
Related
New to powershell but bear with me. I am trying to automate an install of Prosystem Fx Engagement, but need to install a SQL instance. I have already done this part, but I will also need to automate the changing of a services account within services.msc. It will need to be changed from "This account" to "Log in as Local System Account"
https://imgur.com/en9COWl
The name of the service is MSSQL$PROFXENGAGEMENT, and the display name of the service is SQL Server (PROFXENGAGEMENT).
I don't really want to use the method below because the password is visible on the .ps file. I tried looking around but was not able to find anything. Is this even possible?
$LocalSrv = Get-WmiObject Win32_service -filter "name='MSSQL$PROFXENGAGEMENT'"
$LocalSrv.Change($null,$null,$null,$null,$null,$false,"DOMAIN\administrator","PASSWORD")
As for the method you are saying you don't want to use for the account change activity. You don't have to and should not put plain text password in scripts.
You can prompt for the password, store that in a variable and use it. Yet, that means a human has to be there to address that, so, not very automated.
So, this means you need to set the credentials in a file or other store and call that from your script.
Meaning like what is described below. This of course has to be done in advance of any other use case that will need it.
using secure password with multiple users without prompt
#saving credentials
Get-Credential | Export-CliXml -Path c:\credential.xml
#importing credentials to a variable
$Credential = Import-CliXml -Path c:\credential.xml
A YouTube Video on the topic:
Learn to securely use Passwords with PowerShell
You could also use the Windows Credential Store, and call it from there. Also shown in the above video.
Using Windows Credential Manager
https://gallery.technet.microsoft.com/scriptcenter/PowerShell-Credentials-d44c3cde
https://www.powershellgallery.com/packages/CredentialManager/1.0
https://www.experts-exchange.com/questions/29061982/Powershell-Using-credentials-stored-in-Credential-Manager.html
Background
Working in a small O365 environment that recently upgraded from E3 to E5.
Issue
The audit log shows that a user enabled DeliverToMailboxAndForward on their mailbox with the Set-Mailbox operation.
Questions
Is PowerShell the only way to issue Set-Mailbox or can it be done
through the GUI somehow?
Is there a way to disable/prevent users from settings this (i.e. do the end users have too many permissions)?
When I query Get-Mailbox user | fl name,forwardingSMTPAddress,delivertomailboxandforward the ForwardingSmtpAddress is empty and DeliverToMailboxAndForward is False. Is this the only way to ensure the action is disabled? Does the disable action appear in any event/audit log?
Is PowerShell the only way to issue Set-Mailbox or can it be done through the GUI somehow?
As an Exchange admin, you can use the Exchange Admin Center (EAC) to go to the Mailbox properties -> Mailbox Features -> Under Mail Flow, select View details -> Check the Enable forwarding, and Browse to the recipient.
Configure email forwarding for a mailbox
Is there a way to disable/prevent users from settings this (i.e. do
the end users have too many permissions)?
From a user perspective they can forward using the Outlook GUI:
Forward email from Office 365 to another email account
When I query Get-Mailbox user | fl name,forwardingSMTPAddress,delivertomailboxandforward the
ForwardingSmtpAddress is empty and DeliverToMailboxAndForward is
False. Is this the only way to ensure the action is disabled? Does the
disable action appear in any event/audit log?
You can use either the PowerShell script to query, or navigate through ECA console to verify. The disable action should appear in the audit if it is set up.
On to the issue,
The audit log shows that a user enabled DeliverToMailboxAndForward on
their mailbox with the Set-Mailbox operation.
Typically most users don't have access to the Exchange Management Console, and the ability to run PowerShell operations. That makes this audit entry "seem" odd. But then digging through the docs I come up to this entry:
Cmdlets that are run directly in the Exchange Management Shell are
audited. In addition, operations performed using the Exchange admin
center (EAC) are also logged because those operations run cmdlets in
the background.
Administrator audit logging in Exchange Server
So what you are likely seeing is an entry that is a GUI running a cmdlet in the background, without the user actually having direct Exchange Management Shell access. As for permissions, I'm not sure about explicit permissions to deny this specific action without denying a lot of other stuff (i.e. it's like denying permissions to forward messages) unless you have a business need to do this.
This question may get a better response in an Office 365 forum, but I'll try to answer your questions:
The GUI/Web UI is executing PowerShell commands on the back end when users change their configuration. In order to be allowed to change a setting in the GUI, the same permission needs to exist for the PowerShell cmdlets.
This permissions is a default included in the MyBaseOptions management role for Office 365 mailbox users. This role includes many other permissions which users require to manage their own mailbox, such as permissions to create inbox rules or update their picture. You can see all the actions included in this role with this command:
Get-ManagementRole -Identity mybaseoptions |Select -Expand roleEntries
The easiest way to audit current mailbox settings is likely running the command as you have done. A more efficient way to query all your mailboxes for just those with specific settings is to use the -Filter parameter on the Get-Mailbox command like this:
Get-Mailbox -Filter {DeliverToMailboxAndForward -eq $true -and ForwardingSMTPAddress -ne $null}
I hope that helps answer your questions!
As the title implies, I'm trying to automate the login process to AzureRMAccount in Powershell.
I've scoured every forum on every website I can find trying every different combination of solutions (well, except for the solution that works).
Every time I try to automate the login process of my Azure account, I get an error :
Unknown User Type
Yes, I have full access to this account, and Yes it does work fine if I omit all of the parameters and allow for the interactive username/password dialog.
I have even tried to simply call the Get-Credentials and push those into a variable and then call Login-AzureRMAccount using those creds....no luck.
Add-AzureRMAccount fails too.
Any help would be appreciated.
I did find one solution, although it's not the most secure solution as it generates a disk file putting your information at risk if someone were to gain access to the machine on which the Powershell code is executing.
You can login interactively and immediately export the context to a json file, Then at a later time, import that json file as the current context to bypass login
PS C:\> Save-AzureRmContext -Profile (Add-AzureRmAccount) -Path C:\test.json
then in a later session, Import the context
PS C:\> Import-AzureRmContext -Path C:\test.json
Again, this is not the most secure option but it did achieve the results. I would love to have a more secure option.
Now, before I start, I will let you in on a secret: this is on a Domain Controller.*
*The above statement is stricken due to irrelevance as the only significant change that occurs to the Local Administrator account and the Local Administrator Group (within the context and scope of this question) is minimal and doesn't alter the outcome enough to require differentiation.
I didn't have this kind of trouble on any of the other servers and I am willing to bet that the reason behind it is because it is on a DC.*
*Same reason as stated above. The accepted answer explains the inconsistency and was an oversight on my part, not the architecture (read features) of Windows Security or Domain Controllers.
I have been playing around with a few ideas on how to check if a script has been called from an account that is either the local Administrator or, at the very least, called by an account that is part of the Local Administrators group.
I have renamed the local Admin account, however, I know that I can see if the script has been called by local Admin account by typing:
(New-Object System.Security.Principal.NTAccount('reserved')).Translate([System.Security.Principal.SecurityIdentifier]).Value
and I can see if the SID ends in -500.
The problem occurs when I run a condition to see if the calling account is part of the Administrators group (which is a larger scope) by typing:
PS> [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match "S-1-5-32-544")
PS> False
A quick check to see what account it was using:
PS> $env:username
PS> reserved
or the needlessly complicated way (though I prefer it sometimes):
PS> Write-Host ((Get-WmiObject Win32_Account | ?{$_.SID.Substring($_.SID.Length-4,4) -eq '-500'}).Caption).Split("\",2)[1] -fore GREEN
PS> reserved
and I even type:
PS> net user reserved
where it tells me Local Group Memberships *Administrators.
I pull up ADUC (dsa.msc) and I look in the Builtin container and double-click on the Administrators group. I select the Members tag and lo, and behold, reserved is actually a member!
So, a recap:
By typing net user reserved, I was able to verify it was part of the Local Administrators group
I looked in ADUC and verified reserved was a member of the builtin Administrators group
I ensured reserved was indeed the Local Administrator account by verifying the SID started with S-1-5... and ended with ...-500
To take it a step further, I made sure the SID matched the Active Directory Group named "Administrators" by typing Get-ADGroup -Identity "Administrators". I then typed Get-ADGroupMember -Identity "Administrators" and made sure reserved was listed (it was AND the SID matched!).
When I check to see if the well-known Administrators Group SID is found in the Groups of that account (by getting the current Windows Identity), it says that it isn't.
What gives?
Why do I get every indication that it actually is a member of the Local Administrators group but that SID isn't found in the account's groups?
When a computer is promoted to a domain controller, there are no more local users or groups on the machine. Member computers have local users and groups, and can also use domain users and groups for authentication, but on a DC, there are only domain objects.
See also: https://serverfault.com/a/264327/236470
I happened to stumble across something and I realized the answer to this question. For the sake of those that come here looking for assistance, here is the answer to my question:
Very simply--in regards to Powershell--if the Administrator Group SID (S-1-5-32-544) does not show up in the Groups of the user, that is a first-line indication that the script is not running with Administrative credentials.
For example, when I type out:
([Security.Principal.WindowsIdentity]::GetCurrent()).Groups
and I do not see the Administrator Group SID listed even though I know for a fact that the account I am signed into is a member of the Administrator Group, it means the current Powershell process does not have Administrative credentials.
If you click Run As Administrator and type the same as above, you will see that it lists the Administrator Group SID in Groups.
The reason why I was experiencing the inconsistency is simply because I was not running the Powershell process as an Administrator.
So, in short, there are a few ways you can check to verify if your current Powershell session has Administrator credentials. The first one is found in countless websites around the internet and is very common (I did not write this one):
$myWindowsID = [Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal = New-Object Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole = [Security.Principal.WindowsBuiltInRole]::Administrator
if($myWindowsPrincipal.IsInRole($adminRole)) {
\\ TODO: Process is running as Administrator
Clear-Host
} else {
$newProcess = New-Object System.Diagnostics.ProcessStartInfo "Powershell"
$newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"
$newProcess.Verb = "runas"
[System.Diagnostics.Process]::Start($newProcess)
exit
}
Here is another way (I did write this one):
[Security.Principal.WindowsIdentity]::GetCurrent() | %{
if($_.Groups -contains "S-1-5-32-544") {
\\ TODO: Process is running as Administrator
Clear-Host
} else {
Start Powershell -ArgumentList "& '$MyInvocation.MyCommand.Path'" -Verb runas
exit
}
}
# The Foreach-Object (%) could be replaced with another pipeline filter
I see a lot of people asking this question and because of Powershell appealing to many Systems Administrator (especially ones without a background in programming), I really think this will come in handy for others down the line.
I am looking for a way to capture the network credentials of the current session into a variable that I can pass later...
The point is to execute commands on a foreign domain that I have account access/privileges to, but there is not a trust between the source and target domains.
First, we run inside a powershell that was spawned using the runas command (runas /netonly /user:domian\account powershell
From here I can do pretty much everything I want to except create an event in the task scheduler without hardcoding the username/password into the command line
invoke-command -computer $destination -scriptblock {schtasks -ru domain\account -rp password}
What I am looking to do is something like
$username = Get Current Session Network Username ($(whoami) brings up the actual local longon account,not the runas account that spawned the powershell window)
$password = Get the Password that was entered when the RunAs command was executed
Once a security token has been created from credentials entered and validated against active directory, the password is no longer kept around. It is not available for retrieval and reuse elsewhere. Only the token remains. This is by design.
UPDATE:
I dug a little further to bolster my case, and it's not quite as above but the end result is the same. The password used with runas.exe does not appear to be available. The network credentials are not validated against AD, which makes sense in retrospect since you often use /netonly for working with a remote, untrusted domain: By definition, you cannot validate the remote credentials from the local system. From MSDN:
Here's information for the flag LOGON_NETCREDENTIALS_ONLY, used with CreateProcessWithLogonW.
Log on, but use the specified credentials on the network only. The new
process uses the same token as the caller, but the system creates a
new logon session within LSA, and the process uses the specified
credentials as the default credentials.
This value can be used to create a process that uses a different set
of credentials locally than it does remotely. This is useful in
inter-domain scenarios where there is no trust relationship.
The system does not validate the specified credentials. Therefore, the
process can start, but it may not have access to network resources.
Ok, so since it can't validate the credentials and get a token, then it must store the password somewhere in memory since it must pass them over the wire later for SSPI etc. So, can we get at them from the process launched from runas.exe ? Let's see:
PS> runas /netonly /user:foo\bar powershell.exe
Enter the password for foo\bar: ******
I literally used foo\bar for domain and user above. It is not validated, as mentioned already. I entered 12345 for a password. The above line will launch a new instance of powershell. So, from that new instance, let's look at the default network credentials:
PS> [System.Net.CredentialCache]::DefaultNetworkCredentials
UserName Domain
-------- ------
Oh well, out of luck: Nothing there. My guess is the credentials are guarded in some encrypted part of memory in the kernel, probably the LSA (local security authority) out of reach from prying processes.