Powershell: Unable to use the -Recursive switch for AD group membership - powershell

I have (what I think is) an odd problem.
I have two domain admin accounts and one domain controller (for the purpose of this question). Here is the scenario:
Admin1 RDPs to dc01 and runs the Powershell command (see command below), and it succeeds
Admin2 RDPs to dc01 and runs the Powershell command (see command below), and it fails (see error below).
In both cases, we are entering the credentials of admin1 when prompted by Get-Credential
Command:
Get-ADGroupMember administrators -Credential (Get-Credential) -Server dc01 -Recursive
Error:
Get-ADGroupMember : There is no such object on the server
If I remove the -Recursive parameter, then the command works for both admins (again, using the credentials of admin1). If I open ADUC as admin1, then look at the members of Administrators, I can see all members, opening sub-groups without issue.
What in the world is going on? Thanks.

Well, looks like it was a permissions issue. I added the service account to Enterprise Admins and the failure stopped. I have no idea which object is causing the failure.

Related

Why Search-ADAccount is giving different results when Run as Administrator

I am connected as Domain Admin to my DC. When I run the following command in a PowerShell windows, it finds 2 users
Search-ADAccount -UsersOnly -AccountInactive -TimeSpan 90.00:00:00 -SearchBase "OU=myOu,DC=myDomain,DC=local"
| Where {$_.enabled} | Sort-Object -Property LastLogonDate
When I run the same command in a PowerShell Run as Administrator, it finds 28 users
it looks like if the PowerShell console is started as Administrator, it can affect the cmdlet's ability to read certain Object and I do not understand why.
Has someone has seen such behavior and can explain why please?
You can temporarily disable User Account Control (UAC) and then run your PowerShell command which should return the expected results even if you don't invoke Run as Administrator. That's your quick answer.
The reason is because UAC is not giving you the admin token which you think you already have (but don't) when you run PowerShell as a non-administrator (even though you are logged into the DC as a domain administrator). When UAC is bypassed, such as (1) when it's disabled, (2) has its security level lowered enough, or (3) you invoke Run as Administrator, you have all the rights to read all the properties in AD and all the expected data returns. But in this case PowerShell will not show values for properties when there is no admin token attached because UAC is enabled on the DC. It will simply show no values/data (as opposed to throwing an error). There's a Reddit thread on this here.

Double-Hop Errors when running Skype for Business Cmdlets

I am attempting to automate the Skype for Business Server installation process in Powershell, I have a script that remotes into specified machines and begins preparing them as Front-End servers. The problem lies when certain SfB cmdlets (SfB commands are all of the form "verb-Cs...", ex. Get-CsUser or Get-CsPool) are run in remote sessions, they throw the double-hop error:
Exception: Active Directory error "-2147016672" occurred while searching for domain controllers in domain...
This is after running Enable-CsComputer, which enables the computer's role-based off its definition in the topology (topology was published successfully). The user object is in all required groups (RTCUniversalServerAdmins, Schema Admins, CsAdministrators & Local Admin rights on all SfB Servers). Oddly enough, the command 'Import-CsConfiguration -localstore" does not throw errors, and it's in the same remote session. There may be other local or domain groups that I need to be in, but I cannot pinpoint exactly which and have not seen them documented in the Skype build guides. Skype commands that have parameters to specify targets or just pull data, such as Get-CsPool or Get-CsAdForest, do not have errors because they are run in the local scope. The Enable-CsComputer has no parameter for the computer name, it has to be executed from that machine itself.
Enabling CredSSP delegation on each server is not an option, and I'm not understanding why there is a "second hop" in this command! If the second hop was a resource on a file server or database, that would make sense, and be easy to solve, but in this case, I can't track it. Can anyone tell me what I may be missing?
Here's a code sample to try and illustrate. From the jumbox I get the pool data to create an array, and a session is opened to each machine:
$ServerArray =get-cspool -identity $poolName
$i=0
$SessionArray = #{}
foreach($server in $ServerArray.Computers){$SessionArray[$i] = new-PsSession -ComputerName $server}
foreach($session in $SessionArray.values){
invoke-Command -session $session -scriptBlock {
#remote commands:
import-csConfiguration -<config file path> -localstore; #no errors
enable-CsReplica; #no errors
enable-cscomputer; #double hop error here
}}
If I log into that machine and run the same command, it executes fine but the intention of the project is to automate it on an arbitrary number of machines.
It looks like it's just trying to authenticate to a domain controller, which is reasonable. You'll have to approach this like any other double-hop issue.
Microsoft has an article dedicated to the double hop issue, and has a few solutions other than CredSSP that you can look at: Making the second hop in PowerShell Remoting

SID for Administrators group doesn't show in a member account

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.

Get-WinEvent via Powershell remoting

I have a non-admin access to a server. I'm allowed to connect via RDP, and to use PowerShell remoting. When I invoke the following PowerShell command from an RDP session:
Get-WinEvent -MaxEvents 100 -Provider Microsoft-Windows-TaskScheduler
I get 100 records, as expected.
When I do the same via PowerShell remoting, by invoking the following from my local machine:
invoke-command -ComputerName myserver {Get-WinEvent -MaxEvents 100 -Provider Microsoft-Windows-TaskScheduler }
I get an error:
No events were found that match the specified selection criteria.
CategoryInfo : ObjectNotFound: (:) [Get-WinEvent], Exception
FullyQualifiedErrorId : NoMatchingEventsFound,Microsoft.PowerShell.Commands.GetWinEventCommand
Any idea why? The remote PowerShell session should be running under identical credentials, right?
EDIT: whoami does show a difference in the security context between RDP logon and PowerShell remoting - the group set is different. In the RDP logon session, there are the following groups in the token:
BUILTIN\Remote Desktop Users
NT AUTHORITY\REMOTE INTERACTIVE LOGON
while in the remoted one, there's
CONSOLE LOGON
That could account for the discrepancy in rights...
EDIT: from the registry, it looks like the task scheduler log somehow is a part of the System log. According to MS KB article Q323076, the security descriptor for the System log can be found under HKLM\SYSTEM\CurrentControlSet\Services\EventLog\System, value CustomSD. I can't check the server in question, but on another server where I'm an admin, there's no CustomSD under that key. Under HKLM\SYSTEM\CurrentControlSet\Services\EventLog\System\Microsoft-Windows-TaskScheduler, neither. Only the Security log gets a CustomSD. The next question is, where's the default SD?
Permissions on the actual log file at C:\Windows\System32\winevt\LogsMicrosoft-Windows-TaskScheduler%4Operational.evtx are irrelevant, the access is being mediated by the EventLog service anyway.
If you are not an administrator on the remote computer, and invoke-command -ComputerName myserver {whoami /all} tells you are who you expected to be.
You will need to be part of Event Log Reader group on the remote computer.
As well as Remote Management Users group, which I believe you already are.
If you need to read security logs, you will also need Manage auditing and security log under Local Security Policy -> Security Settings -> Local Policies -> User Rights Assignment
According to Default ACLs on Windows Event Logs # MSDN blog, in Windows Server 2003+, the default ACL for the System log goes:
O:BAG:SYD:
*(D;;0xf0007;;;AN) // (Deny) Anonymous:All Access
*(D;;0xf0007;;;BG) // (Deny) Guests:All Access
(A;;0xf0007;;;SY) // LocalSystem:Full
(A;;0x7;;;BA) // Administrators:Read,Write,Clear
(A;;0x5;;;SO) // Server Operators:Read,Clear
(A;;0x1;;;IU) // INTERACTIVE LOGON:Read <===================
(A;;0x1;;;SU) // SERVICES LOGON:Read
(A;;0x1;;;S-1-5-3) // BATCH LOGON:Read
(A;;0x2;;;LS) // LocalService:Write
(A;;0x2;;;NS) // NetworkService:Write
Does NT AUTHORITY\INTERACTIVE LOGON include RDP logon? I've found a forum message that says so, but I'd better find a doc to that effect...
The article claims this ACE comes "straight from the source code". So it's hard-coded in the service, with a chance to change via the registry.
You need local admin rights to open a powershell session.
But there is a workaround/alterative here:
https://4sysops.com/archives/powershell-remoting-without-administrator-rights/
I had the weirdest variation of this problem, was driving me nuts !
Remoting from a server W2008r2 (logged on as domain admin, inside interactive powershell session) to workstation Win7 to get logon/logoff events :
invoke-command -computername $pc {Get-WinEvent -FilterHashtable #{logname='
Security';Id=#(4624,4634)}}
-> No events were found that match the specified selection criteria.
But it does work when outputting an empty string in the scriptblock before the Get-Winevent :
invoke-command -computername $pc {"";Get-WinEvent -FilterHashtable #{lognam
e='Security';Id=#(4624,4634)}}
TimeCreated ProviderName Id Message PSComputerName
----------- ------------ -- ------- --------------
19/03/2018 11:51:41 Microsoft-Windows-Se... 4624 An account was succe... b25_x64
19/03/2018 11:51:41 Microsoft-Windows-Se... 4624 An account was succe... b25_x64
Stumbled upon this fix after trying everything: Enter-Pssession, New-Pssession, using -credential parameter to pass a predefined credential to invoke-command, to get-winevent, to both. Nothing worked, gave "No events..." in every combination.
Then I inserted a $cred inside the scriptblock to show the passed on credential for debugging, and suddenly I got the events I was looking for...

Insufficient access rights to perform the operation -- Powershell

I am writing a simple script to copy AD group membership from one user to the other. I am doing it using the ActiveDirectory module only.
The script looks like it would work and does work up until I try to ad the groups to the user.
Code:
import-module ActiveDirectory
$templateUser = get-ADUser user1
$targetUser = getADUser user2
$groups =get-adprincipalgroupmembership $templateUser
$groups2 = get-ADPrincipalGroupMembership $targetUser
foreach($group in $groups) {
add-adGroupMember $group $targetUser
}
Error:
Add-ADGroupMember : insufficient access rights to performt the operation
At line:9 char:18
+ FullyQualifiedErrorID : Insufficient access rights to perform the operation,Microsoft.ActiveDirectory.Management.Commands.AddADGroupMember
Notes/Thoughts:
I am logged in as a normal user, but I ran the powershell as a different user (my admin account). I am not a local admin, but I am an admin on the domain. I am able to add the user to groups if I launch the AD Tools and do it manually (I have permissions to add to those groups).
Edit:
Run the powershell as admin.
Run powershell as administrator.
I hit this today in Server 2012. I was running the powershell as Administrator, I was a domain admin, I was a local admin, I was every kind of admin I could find.
I "fixed" it by using the Active Directory Users and Computers tool, adding myself as the Manager of the AD groups I was trying to add users to, and ticked the box to allow the manager to change membership. I could then run AD-AddGroupMember happily.
I ran into this problem as well using Powershell remoting to connect to a domain controller.
In my case it turned out Include inheritable permissions from this object's parent was turned off for the specific object I couldn't change.
I ran into this issue today where an automated system was using powershell scripts for various things.... It turned out to be executionpolicy.
We were running our script with the ExecutionPolicy Bypass flag, and even running the command directly in powershell outside of a script wouldn't work, but once we set executionpolicy to unrestricted, everything magically worked.
For us we were able to create security groups even, but not add users to groups via powershell, even though we could make the same changes in ADUC.