1) Domain controller client dns entry best practices
2) Tracing and monitoring ldap, kerberos and ntlm traffic on a domain controller
3) SChannel error codes
4) Deleting smartcard certificates
Thursday, April 14, 2016
Tuesday, April 12, 2016
Active Directory ACL's explained
In a previous post on decoding AD ACL's, I provided some code which took BSonPosh's get-adacl output and decoded the SID's and GUID's to help provide more readable output. The example of this is below, however you may find some of the other fields to be a bit confusing. So I created a few different types of test permissions on an OU to show how they are reflected in the Powershell output of these two commands.
Permission set in GUI: "Apply to: All Descendant objects, create/delete Conference Site objects"
ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType : Descendents
ObjectType : msExchConferenceContainer
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Allow
IdentityReference : TEST.LOCAL\Nathan
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : InheritOnly
Permission set in GUI: "Apply to: This object and all descendant objects, create/delete Contact objects"
ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType : All
ObjectType : contact
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Allow
IdentityReference : TEST.LOCAL\Nathan
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : None
Permission set in GUI: "Apply to: This object only, create/delete Computer Objects"
ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType : None
ObjectType : computer
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Allow
IdentityReference : TEST.LOCAL\Nathan
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
Permission set in GUI: "Apply to: Descendent Computer objects, Modify Owner"
ActiveDirectoryRights : WriteOwner
InheritanceType : Descendents
ObjectType : 00000000-0000-0000-0000-000000000000
InheritedObjectType : computer
ObjectFlags : InheritedObjectAceTypePresent
AccessControlType : Allow
IdentityReference : BHI-MASTER\adminlinlnat
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : InheritOnly
InheritedObjectType: Notice this will be all zero's when the permission is for creating a child object in a container. When it is permissions being set on a specific type of child objects, then it will be set that that object type, and the ObjectType value will be all zero's. When setting a permission on a specific property of a specific type of child object, you will get both fields filled in with the ObjectType being the specified property, and InheritedObjectType being the AD object's type.
PropagationFlags: InheritOnly exists when applying to something other than the current OU. (https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.propagationflags(v=vs.110).aspx)
InheritenceFlags: ContainerInherit when applying to anything below the current level, ObjectInherit when applying to child objects (https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.inheritanceflags(v=vs.110).aspx)
InheritanceType: All (everything from this level down), Descendents (children and descendants, not the current object), None (current level only) (https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectorysecurityinheritance(v=vs.110).aspx)
Permission set in GUI: "Apply to: All Descendant objects, create/delete Conference Site objects"
ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType : Descendents
ObjectType : msExchConferenceContainer
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Allow
IdentityReference : TEST.LOCAL\Nathan
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : InheritOnly
Permission set in GUI: "Apply to: This object and all descendant objects, create/delete Contact objects"
ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType : All
ObjectType : contact
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Allow
IdentityReference : TEST.LOCAL\Nathan
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : None
Permission set in GUI: "Apply to: This object only, create/delete Computer Objects"
ActiveDirectoryRights : CreateChild, DeleteChild
InheritanceType : None
ObjectType : computer
InheritedObjectType : 00000000-0000-0000-0000-000000000000
ObjectFlags : ObjectAceTypePresent
AccessControlType : Allow
IdentityReference : TEST.LOCAL\Nathan
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
Permission set in GUI: "Apply to: Descendent Computer objects, Modify Owner"
ActiveDirectoryRights : WriteOwner
InheritanceType : Descendents
ObjectType : 00000000-0000-0000-0000-000000000000
InheritedObjectType : computer
ObjectFlags : InheritedObjectAceTypePresent
AccessControlType : Allow
IdentityReference : BHI-MASTER\adminlinlnat
IsInherited : False
InheritanceFlags : ContainerInherit
PropagationFlags : InheritOnly
InheritedObjectType: Notice this will be all zero's when the permission is for creating a child object in a container. When it is permissions being set on a specific type of child objects, then it will be set that that object type, and the ObjectType value will be all zero's. When setting a permission on a specific property of a specific type of child object, you will get both fields filled in with the ObjectType being the specified property, and InheritedObjectType being the AD object's type.
PropagationFlags: InheritOnly exists when applying to something other than the current OU. (https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.propagationflags(v=vs.110).aspx)
InheritenceFlags: ContainerInherit when applying to anything below the current level, ObjectInherit when applying to child objects (https://msdn.microsoft.com/en-us/library/system.security.accesscontrol.inheritanceflags(v=vs.110).aspx)
InheritanceType: All (everything from this level down), Descendents (children and descendants, not the current object), None (current level only) (https://msdn.microsoft.com/en-us/library/system.directoryservices.activedirectorysecurityinheritance(v=vs.110).aspx)
Wednesday, February 24, 2016
Some useful links for group policy client side debugging
Group policy debugging:
How to enable it: http://blogs.technet.com/b/mempson/archive/2010/01/10/userenvlog-for-windows-vista-2008-win7.aspx
Enabling it for older OS's: http://social.technet.microsoft.com/wiki/contents/articles/4506.group-policy-debug-log-settings.aspx
How to understand the log files: http://blogs.msdn.com/b/richpec/archive/2009/07/20/userenv-debugging-line-by-line.aspx
Repairing local security policy: https://support.microsoft.com/en-us/kb/278316
How to enable it: http://blogs.technet.com/b/mempson/archive/2010/01/10/userenvlog-for-windows-vista-2008-win7.aspx
Enabling it for older OS's: http://social.technet.microsoft.com/wiki/contents/articles/4506.group-policy-debug-log-settings.aspx
How to understand the log files: http://blogs.msdn.com/b/richpec/archive/2009/07/20/userenv-debugging-line-by-line.aspx
Repairing local security policy: https://support.microsoft.com/en-us/kb/278316
Tuesday, December 22, 2015
Wednesday, December 16, 2015
Tis the season for vacation clearing (and password expiration)
As we approach the end of the year, along with its holidays, its common for many employees to take leave for long periods of time. So as a gift to helpdesks everywhere, often they would request to know who will have their password expire during the peak holiday times (to prepare for the support calls). To build a list like this is quite easy with powershell. This assumes you don't have fine grain password policies. In this example, we look at expiring passwords between Dec 21 and Jan 4 given the working days and anticipated return dates around the Christmas and New Years holidays:
import-module activedirectory
#grab the domain wide password policy and extract a # of days integer
$passwordage = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge |select -exp days
#define your start and end filter dates and subtract the max Password age value.
#We need to calculate using passwordlastset timestamps
$startdate = ([datetime]"12-21-2015").adddays(-$passwordage)
$enddate = ([datetime]"1-4-2016").adddays(-$passwordage)
#Filter as much as possible on the LDAP side with the date ranges.
#The Select statement includes a calculated
#expression to convert the passwordlastset value to an actual expiration date.
#Convert to CSV and output to file.
#Zip it and mail it out.
get-aduser -filter {(enabled -eq $true) -and (passwordlastset -ge $startdate) -and (passwordlastset -le $enddate)} -Properties passwordlastset, mail | select samaccountname, name, mail, @{name="ExpirationDate"; exp={$_.passwordlastset.adddays($passwordage)}} | convertto-csv -notypeinfo | out-file .\expiringholidays.csv
import-module activedirectory
#grab the domain wide password policy and extract a # of days integer
$passwordage = (Get-ADDefaultDomainPasswordPolicy).MaxPasswordAge |select -exp days
#define your start and end filter dates and subtract the max Password age value.
#We need to calculate using passwordlastset timestamps
$startdate = ([datetime]"12-21-2015").adddays(-$passwordage)
$enddate = ([datetime]"1-4-2016").adddays(-$passwordage)
#Filter as much as possible on the LDAP side with the date ranges.
#The Select statement includes a calculated
#expression to convert the passwordlastset value to an actual expiration date.
#Convert to CSV and output to file.
#Zip it and mail it out.
get-aduser -filter {(enabled -eq $true) -and (passwordlastset -ge $startdate) -and (passwordlastset -le $enddate)} -Properties passwordlastset, mail | select samaccountname, name, mail, @{name="ExpirationDate"; exp={$_.passwordlastset.adddays($passwordage)}} | convertto-csv -notypeinfo | out-file .\expiringholidays.csv
Tuesday, December 15, 2015
Checking Mcafee DAT version information remotely with powershell
This script can be used to remotely check a Mcafee client's datversion number and the date of the DAT file's release. It uses basic remote registry reading techniques, so remote registry access (usually administrator on the remote machine) will be required for it to work. You can use this script as a template for other registry reading operations that you may need. It is a basic script that only accepts single computer input. You can change parameters and turn this into a function to handle pipeline or array input.
Update July 2018. Added a secondary registry key in due to some differences I'm seeing in my environment lately. With different product versions and EPO use, this location may move around a bit. If you find this code doesn't work for you, check the current dat version in the taskbar icon, then search the registry for the dat version number. This should get you to the location that your product is storing this information in.
Update July 2018. Added a secondary registry key in due to some differences I'm seeing in my environment lately. With different product versions and EPO use, this location may move around a bit. If you find this code doesn't work for you, check the current dat version in the taskbar icon, then search the registry for the dat version number. This should get you to the location that your product is storing this information in.
param ( [parameter(mandatory=$true)][string]$computername ) function ping-host([string]$computername) { #This function will perform a simple, small size single packet ping of a machine and return true/false for the result if ([string]::IsNullOrEmpty($computername) ) {return $false} #ping first for reachability check $po = New-Object net.NetworkInformation.PingOptions $po.set_ttl(64) $po.set_dontfragment($true) [Byte[]] $pingbytes = (65,72,79,89) $ping = new-object Net.NetworkInformation.Ping $savedEA = $Erroractionpreference $ErrorActionPreference = "silentlycontinue" $pingres = $ping.send($computername, 1000, $pingbytes, $po) if (-not $?) {return $false} $ErrorActionPreference = $savedEA if ($pingres.status -eq "Success") { return $true } else {return $false} } if ((ping-host $computername) -eq $false) { New-Object PSobject -Property @{ Computername = $computername DATVersion = "System Not Online" Datdate = $null } } else { try { #Set up the key that needs to be accessed and what registry tree it is under $key = "Software\McAfee\AVEngine" $type = [Microsoft.Win32.RegistryHive]::LocalMachine #open up the registry on the remote machine and read out the TOE related registry values $regkey = [Microsoft.win32.registrykey]::OpenRemoteBaseKey($type,$computername) $regkey = $regkey.opensubkey($key) $status = $regkey.getvalue("AVDatVersion") $datdate = $regkey.getvalue("AVDatDate") } catch { try { $key = "Software\Wow6432Node\McAfee\AVEngine" $type = [Microsoft.Win32.RegistryHive]::LocalMachine #open up the registry on the remote machine and read out the TOE related registry values $regkey = [Microsoft.win32.registrykey]::OpenRemoteBaseKey($type,$computername) $regkey = $regkey.opensubkey($key) $status = $regkey.getvalue("AVDatVersion") $datdate = $regkey.getvalue("AVDatDate") } catch { #try newer registry location try { $key = "Software\Wow5432Node\Network Associates\ePolicy Orchestrator\Application Plugins\VIRUSCAN880" $regkey = [Microsoft.win32.registrykey]::OpenRemoteBaseKey($type,$computername) $regkey = $regkey.opensubkey($key) $status = $regkey.getvalue("DATVersion") $datdate = $regkey.getvalue("DatDate") } catch { $status = "Cannot read regkey" } } } New-Object PSobject -Property @{ Computername = $computername DATVersion = $status DatDate = $datdate } |select Computername,DatVersion,DatDate }
Thursday, December 3, 2015
Powershell Switch for a numeric range
There are several ways of handling a range of values in a Switch statement in powershell. In this example, I will show a simple conversion of a numeric month value to a quarter [string].
First example:
The range operator returns an array of the numbers in that specified range, so we use -contains to test our value. If we left out -contains, all switch values would match as no comparison is being made, yet the range is being evaluated as true.
Second example:
The key to this example is the Break statement. Without this, everything would match as the switch operator continues to evaluate for all possible matches (not just the first one). Break will cause it to stop evaluating.
Third example:
The more "wordy" example with multiple conditions and the -And. This may be more readable, however the first example does a pretty good job with this. The functionality is far more obvious than example #2. In any case, using conditions to check a range of values will save time and code. Alternatively (though not very elegant or practical), you can use a regex switch for this:
First example:
switch($month){ {1..3 -contains $_}{"Q1"} {4..6 -contains $_}{"Q2"} {7..9 -contains $_}{"Q3"} {10..12 -contains $_}{"Q4"} }
The range operator returns an array of the numbers in that specified range, so we use -contains to test our value. If we left out -contains, all switch values would match as no comparison is being made, yet the range is being evaluated as true.
Second example:
switch($month) { {$_ -le 3} {"Q1";break;} {$_ -le 6} {"Q2";break;} {$_ -le 9} {"Q3";break;} {$_ -le 12} {"Q4"; break;} }
The key to this example is the Break statement. Without this, everything would match as the switch operator continues to evaluate for all possible matches (not just the first one). Break will cause it to stop evaluating.
Third example:
switch($month) { {$_ -ge 1 -and $_ -le 3} {"Q1"} {$_ -ge 4 -and $_ -le 6} {"Q2"} {$_ -ge 7 -and $_ -le 9} {"Q3"} {$_ -ge 10 -and $_ -le 12} {"Q4"} }
The more "wordy" example with multiple conditions and the -And. This may be more readable, however the first example does a pretty good job with this. The functionality is far more obvious than example #2. In any case, using conditions to check a range of values will save time and code. Alternatively (though not very elegant or practical), you can use a regex switch for this:
switch -regex ([string]$month) { "^[1-3]$" {"Q1"} "^[4-6]$" {"Q2"} "^[7-9]$" {"Q3"} "^1[0-2]$" {"Q4"} }
Subscribe to:
Posts (Atom)