Labels

Showing posts with label Security. Show all posts
Showing posts with label Security. Show all posts

Saturday, July 25, 2020

PCNS and Kerberos S4U2Self updating lastLogonTimestamp

While trying to decommission a legacy user domain that was a target for MIM password synchronisation, I noticed that lastLogonTimestamp was being updated whenever a password was changing in another connected forest. It turns out this was because we still had PCNS on Domain Controllers in the legacy forest (for bi-directional password sync), and a ‘feature’ of PCNS is to update lastLogonTimestamp due to a Kerberos S4U2Self network logon. Note that this is still governed by the ‘ms-DS-Logon-Time-Sync-Interval’ attribute (default 14 days) providing a window so that LLT isn’t updated *every* time you log on, only as soon as you fall out of the time sync window.

I poked around a little and I believe this occurs because the pcnssvc.exe calls the AuthzInitializeContextFromSid() function, which appears to perform a network logon of the target user to grab information from the token. This uses the Kerberos 2003 extensions for S4U (service for user). This made it invalid to use lastLogonTimestamp as a mechanism to determine whether accounts are still being logged in to, as PCNS was making it seem like they were!

I also think that anything that uses the S4U extensions will exhibit the same behaviour. For example, to do an equivalent in PowerShell, you can create a new windows identity object with only the UPN, which also results in a network logon of the target account:


  new-object system.security.principal.windowsidentity("user@domain.com")

This results in event 4624 network logon on the local machine - which consequently will fail if the target user doesn’t have SeNetworkLogonRight – ‘Access this computer from the network’ right:

  Logon Information:
 Logon Type:  3
 Restricted Admin Mode: -
 Virtual Account:  No
 Elevated Token:  Yes

  Impersonation Level:  Identification

And looking at the Kerberos conversation, after getting a TGT, it ends doing a AP-REQ using the ‘PA-FOR-USER’ S4U2Self structure:










And once the ticket has been acquired, if you use ‘klist tickets’, you’ll see the krbtgt and the S4U ticket (only showing your user, it won’t display the:













References:

AuthzInitializeContextFromSid function
http://msdn.microsoft.com/en-us/library/windows/desktop/aa376309(v=vs.85).aspx AuthzInitializeContextFromSid attempts to retrieve the user's token group information by performing an S4U logon. AuthzInitializeContextFromSid attempts to retrieve the information available in a logon token had the client actually logged on. An actual logon token provides more information, such as logon type and logon properties, and reflects the behavior of the authentication package used for the logon.

WindowsIdentity Constructor (String)
http://msdn.microsoft.com/en-us/library/td3046fc.aspx
This constructor is intended for use on computers joined only to Windows Server 2003 domains. An exception is thrown for other domain types. This restriction is because the constructor uses the KERB_S4U_LOGON structure.

Kerberos S4U2self
https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/02636893-7a1f-4357-af9a-b672e3e3de13
The S4U2self extension allows a service to obtain a service ticket to itself on behalf of a user. The user is identified to the KDC using the user's name and realm. Alternatively, the user might be identified based on the user's certificate. The Kerberos ticket-granting service (TGS) exchange request and response messages, KRB_TGS_REQ and KRB_TGS_REP, are used along with one of two new data structures. The new PA-FOR-USER data structure is used when the user is identified to the KDC by the user name and realm name.

Wayne's World of IT (WWoIT). 


Read more!

Saturday, September 13, 2008

Simple string encryption with PowerShell

While looking for a method to obfuscate passwords in script files, I started with securestring input combined with the convertfrom-securestring and convertto-securestring functions. Unfortunately (or fortunately from a security perspective) the securestring seems relevant only for per session/user/process/computer (or a combination thereof).

From documentation these functions use Rijndael symmetric encryption, so I modified another example for a very simple, key-less passphrase-less encryption/decryption of a string. This isn’t even very good obfuscation, let alone encryption, but if you encrypted a password and then reproduce the last 10 lines to decrypt the encrypted string, it’s slightly better than storing passwords in very visible paintext (sort of). I guess this could be obfuscated further by reading the encrypted string from a secured file or registry key.

This could be made as complex as you like with keys and initialisation vectors, but unless you make people enter the key (and then why not just make them enter the password?), there would still be something in plaintext, so I didn’t think there was much point.

I'm still undecided on whether there is any benefit with such simple obfuscation, but I thought I'd post the script nonetheless.



$string = "LongStringToEncryptAsATest"
$string

$r = new-Object System.Security.Cryptography.RijndaelManaged  # use Rijndael symmetric key encryption
$c = $r.CreateEncryptor((1..16), (1..16))    # Set the key and initialisation vector to 128-bytes each of (1..16)
$ms = new-Object IO.MemoryStream
$cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write" # Target data stream, transformation, and mode
$sw = new-Object IO.StreamWriter $cs
$sw.Write($String)       # Write the string through the crypto stream into the memory stream
$sw.Close()
$cs.Close()
$ms.Close()
$r.Clear()
[byte[]]$result = $ms.ToArray()      # Byte array from the encrypted memory stream
$encstring = [Convert]::ToBase64String($result)    # Convert to base64 for transport

$encstring         # The encrypted base64 string representation


$Encrypted = [Convert]::FromBase64String($encstring)   # Convert the encrypted string to a byte array
$r = new-Object System.Security.Cryptography.RijndaelManaged  # use Rijndael symmetric key encryption
$d = $r.CreateDecryptor((1..16), (1..16))    # Set the key and initialisation vector to 128-bytes each of (1..16)

$ms = new-Object IO.MemoryStream @(,$Encrypted)    # Create a memorystream from a single-element name/value pair hash table of the byte array
$cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read" # Target data stream, transformation, and mode
$sr = new-Object IO.StreamReader $cs     # Read the string through the crypto stream from the encrypted memory stream
write-output $sr.ReadToEnd()      # Write the unencrypted string
$sr.Close()
$cs.Close()
$ms.Close()
$r.Clear()


Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Sunday, September 7, 2008

Creating secedit templates with PowerShell

This post provides a powershell script to create a secedit security template based on an existing NTFS filesystem permissions structure. This script uses the PowerShell get-childitem cmdlet combined with the get-acl cmdlet to provide the SDDL string, which is then processed to print out only explicit ACLs, after stripping out inherited ACE's in a very cheap and nasty regular expression matching way.

Using this script provides a basic DACL per-directory secedit template type view of a filesystem, excellent to move away from directly applying ACLs to the filesystem or just to provide point-in-time views of your NTFS security.

How good is powershell?


# -- CreateSecurityTemplate.ps1 -- #
#
# 06/09/2008, Wayne Martin, Initial version
#
#
# Description:
#   Given a starting directory, recursively list explicit ACLs in SDDL format for reproduction in a secedit security template
#
# Assumptions, this script works on the assumption that:
#   Only discretionary access control entries are used
#
# Limitations:
#   260 max_path length limitation is in place with get-childitem
#
# Arguments:
#  -p : Path     - The root folder to begin the search
#
# Example:
#   . .\CreateSecurityTemplate.ps1 -p c:\windows\temp

param ($path = "")

if ($path -eq "") {
    write-output "Please specify a root directory to begin the search, eg . .\CreateSecurityTemplate.ps1 -p c:\windows\temp"
    exit 2
} else {
    write-output "Processing $path"
}

$ErrorActionPreference = "SilentlyContinue"

$EXPLICIT_ACL_OVERWRITE = 2
$EXPLICIT_ACL_MERGE = 2

$PATTERN_SPLIT_ACL = "^\(|\)\(|\)$"
$PATTERN_NOT_INHERITED_ACE = ".;.*ID.*;"
$PATTERN_EMPTY_LINE = "^$"

$DALC_AUTOINHERIT_REQ = "D:AR"
$path

$objects = $null
$objects = get-childitem $path -Recurse | where{$_.PSIsContainer}    # Find directories

foreach ($object in $objects)          # For each directory
{
    if ($object -is [System.IO.DirectoryInfo])
    {
        $FullName = $object.FullName
        $acl = get-acl -path $FullName        # Get the ACL for this directory

        $sddl = $acl.sddl         # Get the ACL in SDDL string format
        $sddl = $sddl.remove(0, $sddl.indexof("("))
 
 # Split to each ACE, return only those that are not inherited and not an empty line
        $aces = [regex]::split($sddl,$PATTERN_SPLIT_ACL) | where{ $_ -notmatch $PATTERN_NOT_INHERITED_ACE } | where{ $_ -notmatch $PATTERN_EMPTY_LINE} 

        if ($aces.length -gt 1) {        # Are there any explicit aces on this directory?
            $newSDDL = "(" + [string]::join(")(", $aces) + ")"     # Yes, construct the new SDDL string
            write-output ("""" + $FullName + """,$EXPLICIT_ACL_OVERWRITE,""$DALC_AUTOINHERIT_REQ" + $newsddl + """")
        }
    }
}

exit 0

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Sunday, August 31, 2008

Fixing Permissions with NTFS intra-volume moves

This post discusses methods to automatically correct permission problems associated with moving data within a single NTFS volume in NTFS5.x - Windows 2000 and 2003 (and XP). Data secured with different ACLs on a single volume that is moved will normally result in incorrect permissions, as the data is re-linked in the MFT without taking into account permission inheritance.

This problem will occur if:

  1. The user context that initiated the move - either locally or through a share - has the delete permission to the root directory object being moved and the right to create in the new location
  2. The target location does not already contain a folder with the same name (if the folder does exist a copy/delete is performed rather than a move).
For example:
 

\\Server\Share\Folder1   - localA:C
\\Server\Share\Folder1\A - localA:C inherited from the root
\\Server\Share\Folder2   - localB:C
\\Server\Share\Folder2\B - localB:C inherited from the root


UserAB who has access to both Folder1 and Folder2, performs a drag and drop operation in explorer, with the source of Folder2\B and a drop-target of Folder1.

After the move, the permissions on \\Server\Share\Folder1\B are still inherited with access to localB, and no access to localA.

How to fix the problem

This can be fixed by using setacl or icacls to reset permission inheritance, or by using security templates to control permissions to the filesystem.

setacl

Reset permission inheritance:
setacl -on %Directory%\*.* -ot file -actn rstchldrn -rst DACL

setacl.exe is a very powerful permissions utility for reporting and modifying ACLs.

In the example above, to reset permissions inheritance for each folder:
for /d %i in (\\server\share\*) do echo setacl -on %i\*.* -ot file -actn rstchldrn -rst DACL

icacls

Reset permission inheritance:
icacls %Directory% /reset /T /C

In the example above, to reset permissions inheritance for each folder:
for /d %i in (\\server\share\*) do echo icacls %i /reset /T /C

icacls is a 2003 SP2 utility, but also runs on XP.

Security Templates

I find that security templates are an excellent method of managing permissions, as they provide:

  • A repeatable method of applying permissions, great for fixing mistakes, DR, restore
  • Accountability and change control - it's easy to see who made changes to a security template, and with templates rollback and change control is much easier
  • Auditing - It's very simple to provide the results of the template to auditors showing your security structure

To reapply the security template, you could run (prefix with psexec to run remotely):
secedit /configure /db c:\windows\temp\%random%.sdb /cfg c:\windows\security\templates\ExampleTemplate.inf /log c:\windows\temp\example.log

Note that for this to reset inheritance, each security template entry must use 2 in the second field, which directs secedit to overwrite existing explicit ACEs, a by-product of which is that inherited ACLs are reset on child objects. If you use a second column of 0 - to merge the results, the incorrectly set inherited ACL is not reset on the child objects.

If you had a security template managing permissions to the example above, it would look something like:

 

[Unicode]
Unicode=yes
[Version]
signature="$CHICAGO$"
Revision=1

[Profile Description]
Description=Example Template

[File Security]
;Set security for Folder1
"D:\Share\Folder1",2,"D:AR(A;OICI;FA;;;BA)(A;OICI;0x1301bf;;;S-1-5-21-129063155-272689390-804422213-3709)(A;OICI;FA;;;SY)"
"D:\Share\Folder2",2,"D:AR(A;OICI;FA;;;BA)(A;OICI;0x1301bf;;;S-1-5-21-129063155-272689390-804422213-3710)(A;OICI;FA;;;SY)"



How to identify the problem

Below is a rather inefficient and simple PowerShell script that will report directories that have inherited ACLs that don't match the parent directory. I'm sure there are better ways to do this, but secedit /analyze doesn't do it and while I started off parsing cacls /S and setacl output with a VBScript, I think the PowerShell script is at least better than that. It works only for simple permission structures, ie you’ve set permissions at the root of somewhere and expecting them to inherit all the way to the end.

I say the script is quite inefficient in that even though I'm filtering the output of get-childitem in the resulting array to return only directories, I believe it still processes all files and directories. And then for each directory I'm finding the parent and checking the ACLs - where it would be more efficient to find the parent and then process all directories directly under the parent before recursing.

Anyway, once you've found the directories, you can often use 'dir /q' to report the new owner, which in testing I've done is set at the person doing the move on the new root folder object.

Note that these permissions problems can occur with files, but the script below only checks directories (because it seemed overkill to check each file when there could be millions, plus it's quite plausible that directory ACLs don't match file ACLs).

Output based on the example above:
PS C:> . .\CheckInheritedSecurity.ps1 -p D:\Share
The ACE for 'TEST\wm' on 'D:\Share\Folder1\B' is marked as inherited but doesn't appear to have been inherited directly from the parent directory

 

$root = ""

if ($args.count -eq 2) {
  for ($i = 0; $i -le $args.count-1; $i+=2) {
    if ($args[$i].ToLower().Contains("-p")) {
      $root = $args[$i+1]
    }
  }
}

if ($root -eq "") {
  write-output "Please specify a root directory to begin the search"
  exit 2
}

$rootSubDirs = get-childitem $root  where{$_.PSIsContainer}

foreach ($tld in $rootSubDirs)
{
  $objects = $null
  $objects = get-childitem $tld.FullName -Recurse  where{$_.PSIsContainer}

  foreach ($object in $objects)
  {
    if ($object -is [System.IO.DirectoryInfo])
    {
      $FullName = $object.FullName
      $acl = get-acl -path $FullName
      $accessRules = $acl.GetAccessRules($false, $true, [System.Security.Principal.NTAccount])      # Report only inherited, as NTAccount (not SIDs)

      $parent = $object.Parent
      $parentFullName = $parent.FullName
      $parentacl = get-acl -path $parent.FullName

      $ParentAccessRules = $parentacl.GetAccessRules($true, $true, [System.Security.Principal.NTAccount])      # Report explicit and inherited, as NTAccount (not SIDs)

      #write-output ($object.fullname + ", child of " + $parent.FullName)

      foreach ($accessRule in $accessRules)
      {
        $InheritedFromParent = $false

        foreach ($parentAccessRule in $ParentAccessRules)
        {
          if ($accessRule.IdentityReference -eq $parentAccessRule.IdentityReference) { $InheritedFromParent = $true }
        }

        if (!$InheritedFromParent)
        {
          $identity = $AccessRule.IdentityReference.ToString()
          write-output ("The ACE for '$identity' on '$FullName' is marked as inherited but doesn't appear to have been inherited directly from the parent directory")
        }
   
      }
    }
  }
}

exit 0


References:

SetACL
http://setacl.sourceforge.net/

SDDL syntax in secedit security templates
http://waynes-world-it.blogspot.com/2008/03/sddl-syntax-in-secedit-security.html

Create or modify a security template for NTFS permissions
http://waynes-world-it.blogspot.com/2008/03/create-or-modify-security-template-for.html

Useful NTFS and security command-line operations
http://waynes-world-it.blogspot.com/2008/06/useful-ntfs-and-security-command-line.html

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Saturday, August 23, 2008

Replica Domain for Authentication

This post describes a solution I implemented to create a relatively secure risk-free external trust between a 2003 and legacy NT4.0 domain to access IIS-based web applications. Normally this scenario has many drawbacks across two 'secure' networks and I ended up provisioning a replica of our corporate 2003 forest trusted by the NT 4.0 domain, and used an identity management solution to synchronise accounts/passwords.

Serveral hundred people happily use pass-through authentication to access web applications, and for authentication we only had to poke a hole in the network for one port in one direction (the replica domain is being hosted on the resource network). There would have to be more ports open for the actual application between workstation and resource server, eg HTTP or MSQL-1433.

The solution is described below and an example of how this sleight of hand works from an NTLM authentication perspective to provide pass-through authentication originating from one domain but authenticating with another.

Supposing you have a corporate domain name PROD (prod.com) and a foreign resource domain named NT4. Users from PROD need to access SQL and IIS web-based applications in the NT4 resource domain, and pass-through authentication is a requirement.

If you are fortunate enough to have an identity management solution in place, then what you could do is:

  1. Create a new forest not on your production network, called prod.local with a NetBIOS domain name of PROD. The NetBIOS domain name must be the same, but the FQDN can be different.
  2. Place the new forest in a DMZ with the required access to the foreign network (being the trusted domain has this domain initiating the outbound TCP/UDP connections). If the trusting company is amenable, you could also host this replica domain on their network, making network security VERY simple.
  3. Create the trust, following http://support.microsoft.com/kb/325874. Note that there are NetBIOS name resolution requirements, using either lmhosts or WINS.
  4. Using your identity management solution, synchronise accounts and passwords from prod.com to prod.local
  5. Enable netlogon debugging on prod.local (nltest /dbflag:0x2080FFFF) so that you can see authentication attempts
  6. Using a workstation that is a member of the prod.com domain, try and authenticate to the resource server in the NT4 domain.
  7. All going well you should see authentication attempts from the NT4 DC to your replica prod.local DC, even though the attempt originated from a domain member of prod.com

Notes:

  1. If this was trusted by an NT 4.0 domain luckily pretty much everything will be wrapped in NetBIOS rather than direct SMB or RPC. it’s still an ephemeral source port though for the TCP 138 endpoint.
  2. Note that even though one side of the trust is an NT 4.0 domain, as long as this is an external NTLM trust (as opposed to a 2003 forest trust), then this should still work (depending on SID filtering). Being NT 4.0 in this case made it even more unworkable to trust the 2003 domain, as it would require access to the 2003 PDC emulator – not something you typically want to host in your DMZ.
  3. Having a second replica DC is always a good idea for redundancy.
  4. If anything to do with SIDs was involved this would NOT work, it’s only because the NTLM authentication model doesn’t use the SID in the challenge-response that this pass-through authentication works.

Example – simple web access

Assuming there’s a 2003 member server running IIS using windows authentication in the NT 4.0 resource domain, and XP clients from the corporate forest are accessing the application directly:

  1. Internet Explorer from the workstation initiates a HTTP session with the web server
  2. HTTP 401 is returned by the web server, indicating that authentication is required, with the WWW-Authenticate response headers indicating Negotiate and NTLM are the available schemes.
  3. NTLM Negotiate (0x00000001) is then sent from the client to the server indicating supported NTLM options
  4. The web server responds with a challenge message (0x00000002) for the client to prove their identity
  5. The workstation responds with an authenticate message (0x00000003) – an encrypted challenge response based on the logged on users’ password hash
  6. A Netlogon RPC call is initiated from the web server to the NT 4.0 DC the server has its secure channel with to initiate the samlogon request, providing the username, domain name, challenge, and challenge-response.
  7. The NT 4.0 DC checks the information and determines that it has a trust with the named domain.
  8. The NT 4.0 DC establishes a secure channel with the trusted replica domain (or uses the existing channel)
  9. A second Netlogon RPC call is then passed through to the replica 2003 domain using the same information as the first call (wrapped in NetBIOS in this case)
  10. The replica DC retrieves the hash of the specified user’s password, the original challenge is then encrypted using this hash and compared to the challenge-response provided with the request.
  11. Assuming passwords are synchronised, the hashes match and the trusted netlogon call is successful
  12. The Netlogon call from the web server is also returned as successful
  13. The web page is served to the XP workstation

References:

Trust between a Windows NT domain and an Active Directory domain cannot be established or it does not work as expected
http://support.microsoft.com/kb/889030

How to establish trusts with a Windows NT-based domain in Windows Server 2003
http://support.microsoft.com/kb/325874

LMHOSTS File Information and Predefined Keywords
http://support.microsoft.com/kb/102725/

How to establish trusts with a Windows NT-based domain in Windows 2000
http://support.microsoft.com/kb/308195

Network access validation algorithms and examples for Windows Server 2003, Windows XP, and Windows 2000
http://support.microsoft.com/kb/103390

NTLM user authentication in Windows
http://support.microsoft.com/kb/102716

NTLM specification
http://download.microsoft.com/download/a/e/6/ae6e4142-aa58-45c6-8dcf-a657e5900cd3/%5BMS-NLMP%5D.pdf



Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Friday, June 27, 2008

Preventing accidental NTFS data moves

This post tries to deal with the eternal problem of users accidentally moving data around on an NTFS volume just because they can, describing my understanding of the problem and the lack of a solution with NTFS permissions only, and a method I've used to work around this problem.

This problem is most apparent with a single share containing top-level directories with different security. When a user has change control to more than one directory, it then becomes possible to drag and drop whole top-level folders into other folders.

When this occurs on the same NTFS volume, it seems the file MoveFileEx function is smart enough to re-link the object to a new parent in the MFT FRS entry for the directory, rather than a recursive copy/delete operation. This is very efficient if it's what you're expecting, but the less than intuitive impacts of this include:

  1. Permissions on child objects - subfolders or files - are ignored in the re-link move, including lack of permissions and specific access denied ACLs
  2. The ACL on the source directory is not reset when it gets to the target, including inheritance from the new parent, and inheritance that was valid in the old parent

For example:
Share\A - Ausers:C
Share\B - Busers:C
Share\B\File.txt - Busers:R
Share\B\Data - Busers:C (inherited from the parent B)

  1. A user that's in AUsers and BUsers accidentally drags the B directory into A. If the destination A\B directory doesn't exist and the user has the delete right to B, the file will be re-linked in NTFS, totally ignoring the fact that the user only has read-only access to B\file.txt.
  2. Instead of dragging the whole top-level directory, the user drags B\Data into A. Again, if A\Data doesn't exist and the user has Delete to Data, the directory is re-linked in NTFS. Looking at the permissions of the new A\Data, it still lists an ACE of BUsers:C, inherited from the 'parent object' that is obviously no longer the parent.

There are many ways of dealing with this problem, for example, you could:

  • Remove change control and use Write. This would be very simple security to manage, but this would prevent users from deleting/renaming files and subdirectories. If creator owner:C were added, this would allow users to delete/rename their own data, but not move/delete/rename data that already exists. This is probably a better solution and would prevent accidental moves/deletes of any kind by normal users, but requires a lot more effort to manage.
  • A small group of custodians could be responsible for managing the creation and deletion of directories, reducing the risk by removing the right to delete from most users.
  • Prevent drag-and-drop through explorer on workstations.
  • Develop a filesystem mini-filter that sits at an altitude to interpret file system operations that are the result of a drag and drop request, and deny requests that involve too much change (or the top 3 levels of each top-level directory for example)
  • Develop a WH_GETMESSAGE hook to intercept explorer drag-and-drop messages and cancel them before the request gets to the server
  • Develop a DropHandler for Directory/Folder objects to filter requests.

However, these solutions generally require too much effort, so I've come up with the following relatively simple workaround:

Prevent a move operation completed as a copy/delete on top-level folders by:

  • Creating a placeholder file within each top-level directory, with users having read-only access to the file. This file will be processed first due to the name beginning with a space (0x20 – processed first in tests), and explorer will immediately return an access denied message. The file should have the hidden attribute set, eg ‘ placeholder.txt’

Prevent users from performing NTFS re-link moves within a volume on top-level directories by:

  • Removing Delete from the top-level directory - part of Change, which general practice is to give users - typically this folder, subfolders and files. As part of a move (drag/drop, cut/paste), if users have the Delete right to the source directory object and a same-named target folder doesn't already exist, NTFS will re-link the directory to the new parent regardless of permissions on the source subfolders and files. This could be achieved by using C: OICIIO (object-inherit, container-inherit, inherit-only), and RWX to the top-level directory, ensuring that a recursive copy/delete operation is performed, which does check access control, and re-inherit permissions in the target.

For example, a user has access to both A and B, with the placeholders secured for read-only:
Share - Users:R
Share\A - AUsers:C
Share\A\placeholder.txt - AUsers:R
Share\B - BUsers:C
Share\B\ placeholder.txt - BUsers:R


In the example above, these changes will prevent the user from:

  • Deleting an entire directory, either A or B, prevented by the placeholder file (deleting the contents) and the lack of Delete on the container.
  • An accidental drag-and-drop of B into A, made into a copy/delete operation by the lack of Delete on the container and prevented as a copy/delete by the placeholder file which is processed first. Note that A\B folder would still be created with inherited permissions of A, but no contents would be copied/deleted.
  • Renaming either A or B. Users only have read on the root, delete is required to rename.

Under normal circumstances with drag and drop in explorer from XP workstation to a 2003 file server, if the following is true then the move operation will re-link the top-level directory within NTFS by attaching it to a new parent, as opposed to a copy/delete operation:

  1. If the data is on the same volume, presented to the user through a share, with or without Access Based Enumeration
  2. If the user has the delete right to the directory object that is the source of the drag operation.
  3. If in the drop target, a folder does not already exist with the same name.

In this scenario, access control is not validated on child objects within the drag source and permissions are not reset in the new drop target (inherited or direct).

Notes:

  1. The user must have access to read the placeholder when using Access Based Enumeration, otherwise the file will simply be hidden and all other objects will be moved (as a copy/delete)
  2. Testing with a re-link move operation and a copy/delete move operation was completed, using diskedit.exe to find the File Record Segment number for the file from the NTFS MFT. When copy/delete was used, a new target directory was created with a new MFT entry, whereas when the object was re-linked, the FRS number remained the same, and the FILE_REFERENCE ParentDirectory entry in the $FILE_NAME attribute was updated to reflect the new parent.
  3. If an object in the drag source is locked by another user (eg command prompt chdir to a subfolder on the console of the server), and in the scenario where the folder would normally be moved at the top-level (instead of copy/delete), explorer on the workstation will automatically fall-back to the copy/delete method).
  4. The same occurs on the console of the file server managing the local volume, moving folders is changing the parent object at a MFT/FRS level, nothing to do with access control on the objects (assuming Delete on the source and create directory on the target)
  5. Using the MoveSecurityAttributes registry value (310316) on the server does ensure that permissions are not copied, which does inherit new permission in the target. However, this can also be confusing, as moving and then moving back would lose permissions.
  6. To determine processing order, several test directories and files were created, and testing shows that directories are processed last-first, ie ASCII character 126 (0x7e) ‘~’ is processed first for directory moves. However, files within a directory are ‘moved’ before directories, and files are processed first-last, and 32 (0x20) is the first common printable character.
  7. Preferably secedit security templates would be used to control the security on the filesystem, providing a repeatable method to apply security.

References:

Inherited permissions are not automatically updated when you move folders
http://support.microsoft.com/kb/320246

MoveFileEx Function
http://msdn.microsoft.com/en-us/library/aa365240(VS.85).aspx

How NTFS Works
http://technet2.microsoft.com/windowsserver/en/library/8cc5891d-bf8e-4164-862d-dac5418c59481033.mspx?mfr=true

How to configure file sharing in Windows XP
http://support.microsoft.com/kb/304040

How permissions are handled when you copy and move files and folders
http://support.microsoft.com/kb/310316

When you try to move files from one network drive to another network drive, the files keep permissions from the source folders on a client computer that is running Windows XP or Windows Server 2003
http://support.microsoft.com/kb/945272

Viewing NTFS information with nfi and diskedit
http://waynes-world-it.blogspot.com/2008/03/viewing-ntfs-information-with-nfi-and.html



Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Tuesday, June 17, 2008

IE Warnings when files are executed

In some scenarios, a prompt will occur when trying to download and run an executable either through Internet Explorer or VBScript from a FQDN UNC path. I've had this occur to me when a VBScript was trying to execute robocopy.exe from a remote share using a fully qualified domain name UNC path. The script was not running on the interactive desktop, and the prompt asking for permission to allow execution prevented the script from finishing.

Windows XPSP2 and Windows Server 2003 SP1 both have new functionality with downloaded files that may be executed and check the digital signature on the files. If the binary does not contain a digital signature, a 'Open File - Security Warning' popup indicating that the publisher could not be verified will be displayed, awaiting user interaction to allow or deny the execution request.

In the VBScript scenario, this was only happening because the execution was called from a Fully Qualified Domain Name, and despite being the local domain (in this case), it was still interpreted as a threat and a warning was presented.



-- Popup
Open File - Security Warning
The publisher could not be verified. Are you sure you want to run this software

Name: Robocopy.exe
Publisher: Unknown publisher
Type: Application
From: FQDN server
This file does not have a valid digital signature that verifies its publisher.
--


Workaround:

Add HKU\.Default\Software\Microsoft\Windows\CurrentVersion\Policies\Associations\LowRiskFileTypes and ensure a semi-colon separated list of extension types exist with those you want to allow. Eg '.exe;.cab'

Note that the path above is to the .default hive, used by the System account. Add to 'Default User\ntuser.dat' or HKCU to modify the default or change the current user respectively. Group policy could also be used to control this setting.

Duplicating the problem:

You can verify the problem before and after by pasting a FQDN UNC path to an IE window, eg
\\server.com.au\c$\windows\system32\robocopy.exe

Or by running the following VBScript:
 

Set objShell = CreateObject("WScript.Shell")
strCMD = "\\server.com.au\c$\windows\system32\robocopy.exe"
intReturnVal
= objShell.Run(strCMD, 0, TRUE)


Note that robocopy.exe version XP010 was used in these tests, running on an XP SP2 workstation to a 2003 server.

References

Internet_Explorer_XPSP2_Security_White_paper.doc
http://www.microsoft.com/downloads/details.aspx?FamilyId=E550F940-37A0-4541-B5E2-704AB386C3ED

Detailed Information on IE problems with XPSP2/2K3SP1:
http://www.jsware.net/jsware/iewacky.php3

Description of IE security zone registry entries:
http://support.microsoft.com/default.aspx?scid=kb;en-us;182569

Problems adding top-level domains to zones site list
http://support.microsoft.com/?kbid=259493

Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Monday, June 9, 2008

AD Security vs Distribution Groups

This post contains information on security groups versus distribution groups in a Windows Active Directory, how to make use of mail enabled security groups and how to convert groups between different scopes.

Groups of type distribution do not have a SID, and without a security identifier, they cannot be part of an Access Control Entry or a security token, even though the members of the distribution group may be accounts that do have SIDs.

Security groups can be mail-enabled, allowing the group to be used for both access control and mail distribution, and depending on your level of service autonomy and delegation of administration this may be suitable. If you nest security and/or distribution groups, there may also be some confusion if using mail enabled security groups.

Implementing Mail-enabled Security Groups

In a simple Exchange 2003 environment, you may be able to:

  1. Convert the groups of type distribution to security, with a scope of global. Universal could be used instead of global, but this depends on whether you have a requirement for cross-domain intra-forest GC access to group membership.
  2. Ensure the security groups are mail enabled
  3. Set the 'Managed By' information on the group to an individual or local group to manage the DL and update the membership list. This will set ACLs on the AD group object to allow members to be updated in the group.
  4. Add the global group to existing local groups used to manage permissions on file shares.
Notes:
  • One reason to use distribution groups rather than mail-enabled security groups is because of service and data autonomy - to separate Exchange DL admins from security group admins, using the method above would make this difficult.
  • You can use the 'dsmod group' command to change the scope and type of a 200x Active Directory group. See the examples below.

Converting an Active Directory security group from Global to Local or vice versa:

This process was tested on an XP workstation against a Windows 2000 Active Directory domain in native mode.

Identify the DN of the group by running
- dsquery group -name %GroupName%

Find the current group scope of the group just identified, by running
- dsget group %GroupDN% -scope -secgrp

Change the group scope to universal, a stepping stone required as groups can't be converted directly between global and local, by running:
- dsmod group %GroupDN% -scope u

Change the group scope to global or local (depending on the requirements), by running:
- dsmod group %GroupDN% -scope g
- dsmod group %GroupDN% -scope l

This modifies an existing group, without changing the SID, useful when the group is already used to apply permissions.

References

Group Objects
http://msdn2.microsoft.com/en-us/library/ms676913.aspx

Group scope
http://technet2.microsoft.com/windowsserver/en/library/79d93e46-ecab-4165-8001-7adc3c9f804e1033.mspx?mfr=true

Troubleshooting mail transport and distribution groups in Exchange 2000 Server and in Exchange Server 2003
http://support.microsoft.com/kb/839949

Group Types
http://technet2.microsoft.com/windowsserver/en/library/95107162-47eb-4891-832f-0c0b15b7c8581033.mspx?mfr=true

Global Catalog Server Requirement for User and Computer Logon
http://support.microsoft.com/kb/216970



Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Sunday, May 25, 2008

Automated Cluster File Security and Purging

If you have a cluster share that contains temporary data in separate top-level directories, this post may help you automate the security and purging of that shared data. This is useful for transient data such as drop directories for scanners and faxes, or scratch directories for general sharing.

To summarise, this will provide:

  1. A cluster-based scheduled task that runs each day, dependant on the network name and physical disk resource currently hosting the directory
  2. A batch file run by the scheduled task that secures each directory, and purges files older than 30 days, logging results to the physical node hosting the resource.

Creating the Scheduled Task

  1. Create the scheduled task cluster resource:
    cluster /cluster:%cluster% res "%resource_name%" /create /group:"%cluster_group%" /type:"Volume Shadow Copy Service Task"
    cluster /cluster:%cluster% res "%resource_name%" /priv ApplicationName="cmd.exe"
    cluster /cluster:%cluster% res "%resource_name%" /priv ApplicationParams="/c c:\admin\SecureAndPurge.bat"
    cluster /cluster:%cluster% res "%resource_name%" /priv CurrentDirectory=""
    cluster /cluster:%cluster% res "%resource_name%" /prop Description="%resource_name%"
    cluster /cluster:%cluster% res "%resource_name%" /AddDep:"%network_name_resource%"
    cluster /cluster:%cluster% res "%resource_name%" /AddDep:"%disk_resource%"
    cluster /cluster:%cluster% res "%resource_name%" /On
    cluster /cluster:%cluster% res "%resource_name%" /prop RestartAction=1
  2. Set the schedule for the cluster resource:
    • Use the cluster administrator GUI, this cannot currently be set with cluster.exe with the VSS scheduled task cluster resource
  3. Restart the resource to pickup the schedule change:
    cluster /cluster:%cluster% res "%resource_name%" /Off
    cluster /cluster:%cluster% res "%resource_name%" /On

Note that the cluster resource providing scheduled task capability is the ‘Volume Shadow Copy Service Task’ resource. This is a recommended solution from Microsoft for providing scheduled task capability on a cluster. See the ‘Cluster Resource’ document in the references below.

The LooksAlive and IsAlive functions for the VSSTask.dll simply check that the scheduled task is known to the local task scheduler. To further reduce the impact of resource failure, the resource should be marked as not affecting the cluster, preventing potential failover if this task were to fail more than three times (by default).

The scheduled task should run a simple batch file on the local disk of the cluster node. Keeping the batch file local further reduces the risk that problems with the batch file could cause the cluster group to fail. The theory is that if the batch file is on local disk, it can be modified/deleted before bringing the cluster resources online.

Creating the batch file

Create a batch file and set some environment variables for %directory%, %purgeDir%, %domain%, %logFile%, %AdminUtil%, %FileAge% to fit your environment, and then include at least the three commands below:

  • Set the security on each directory within the directory. Note that this assumes that for each directory, there is a matching same-named security group, prefixed with l (for local), eg lDirectory1.

    for /d %%i in (%Directory%\*) do cacls %%i /e /g %Domain%\l%%~ni:C >> %LogFile%
  • Move the files with robocopy that are older than %FileAge% days:

    %AdminUtil%\robocopy %Directory% "%PurgeDir%" *.* /minage:%FileAge% /v /fp /ts /mov /e /r:1 /w:1 /log+:%LogFile%
  • Delete the files that were moved:

    If Exist "%PurgeDir%" rd /s /q "%PurgeDir%"

Note that depending on the size of data, you might want to ensure that the purgedir is on the same volume as the source files, which won't use any disk space as the files are moved. If the purgedir was on a different drive you would temporarily need as much free space as the size of data being purged.

References:

Cluster resource
http://technet2.microsoft.com/windowsserver/en/library/f6b35982-b355-4b55-8d7f-33127ded5d371033.mspx?mfr=true

Volume Shadow Copy Service resource type
http://technet2.microsoft.com/windowsserver/en/library/bc7b7f3a-d477-42b8-8f2d-a99748e3db3b1033.mspx?mfr=true

Using Shadow Copies of Shared Folders in a server cluster
http://technet2.microsoft.com/windowsserver/en/library/66a9936d-2234-411f-87b4-9699d5401c8c1033.mspx?mfr=true

Scheduled task does not run after you push the task to another computer
http://support.microsoft.com/kb/317529

Scheduled Task for the Shadow Copies of Shared Folders Feature May Not Run on a Windows Server 2003 Cluster
http://support.microsoft.com/kb/828259

Behavior of the LooksAlive and IsAlive functions for the resources that are included in the Windows Server Clustering component of Windows Server 2003
http://support.microsoft.com/kb/914458

Generic Cluster-enabled Scheduled Tasks:
http://waynes-world-it.blogspot.com/2008/04/2003-cluster-enabled-scheduled-tasks.html



Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Monday, May 5, 2008

Impersonating a user without passwords

While playing with starting processes in the winlogon secure desktop and unlocking a machine without a password (remoteunlock.exe), I experimented with using ZwCreateToken through ztokenman.exe to start a process as a user without knowing their password.

Combined with psexec, this allows you to run something as a user that’s interactively logged on, while their workstation is locked and without knowing their password.

Start a process on the winlogon desktop, used when the machine is locked:

  • psexec /s \\%computer% cmd /c c:\windows\temp\psexec /accepteula /x /d /s cmd

From this command prompt, run ztokenman.exe and:

  1. In the Process drop-down, select a process owned by the user (eg explorer.exe)
  2. Click DumpProcessToken
  3. In the 'Create a Process With the Current Token' text-box, type cmd.exe
  4. Click 'CreateProcessAsUser with Current Token'


From the cmd.exe that opens, this should be under the context of the interactive user of the workstation. For example, if you run net use, you should see the connections the user has.

This uses an undocumented API - ZwCreateToken, after calling OpenProcessToken to duplicate a token from an existing process.

Is this actually useful for anything? Probably not, but it’s interesting nonetheless. Note that remoteunlock.exe will actually provide access to the desktop for the interactive winlogon session, even if the machine is locked.

References

RunAsEx and ztokenman:
http://www.codeguru.com/cpp/w-p/win32/cursors/article.php/c6745/

Unlocking XP/2003 without passwords
http://waynes-world-it.blogspot.com/2008/04/unlocking-xp2003-without-passwords.html

RemoteUnlock.exe
http://www.codeproject.com/KB/system/RemoteUnlock.aspx


Read more!

Running a process in the secure winlogon desktop

Have you ever wanted to run something in the secure desktop controlled by winlogon - the desktop you see when nobody is logged on?

I have, and recently realised that psexec supports this - with the '-x' command. For example, if you run the following command and then press ctrl+alt+del or logoff, you’ll still have a console with the ability to start other commands:

  • psexec /x /d /s cmd

This only works on the local machine, but of course psexec allows you to run things remotely! The following command therefore uses psexec to remotely run cmd to start psexec locally to run cmd in the local winlogon desktop of the remote computer:

  • psexec /s \\%computer% cmd /c psexec /accepteula /x /d /s cmd

This was done using psexec.exe v1.94 and the second command assumes that psexec.exe is available in the path on the remote computer.

References:

Unlocking XP/2003 without passwords
http://waynes-world-it.blogspot.com/2008/04/unlocking-xp2003-without-passwords.html


Read more!

Monday, April 21, 2008

Unlocking XP/2003 without passwords

The winlogon secure desktop is really just another desktop on winsta0, and I came across a utility - RemoteUnlock.exe - which injects itself as a thread in the console winlogon process of a remote machine and switches from the secure winlogon desktop to the logged on user’s winsta0\default desktop.

This allows you to skip the SAS process requiring the account password of the currently logged on user, and just shows the desktop, allowing full console interaction as the logged on user.

This doesn't really have very many practical uses, but the concept is great and I thought I would share the utility I came across plus some additional thoughts on the topic.

The utility and source code:
http://www.codeproject.com/KB/system/RemoteUnlock.aspx

I've previously toyed with creating a command shell on a remote winlogon desktop, which can be done with the following command:
- psexec /s \\%computer% cmd /c c:\windows\temp\psexec /accepteula /x /d /s cmd

After another discussion regarding secure passwords with PowerShell, I was curious just what might be possible from the Winlogon desktop.

One thing led to another, and after trying unsuccessfully using a PowerShell script run from a command shell on the Winlogon desktop (using psexec) calling GetProcessWindowStation/UnlockWindowStation (an undocumented API, presumably unlocking a window station) and OpenDesktop/SwitchDesktop , I came across a reference to UnlockWindowStation which mentioned that this would only work when running as part of winlogon.exe, explaining why the PowerShell script did nothing.

I then successfully tested remoteunlock.exe running from one XPSP2 workstation against another. RemoteUnlock uses switchdesktop which doesn’t actually unlock the desktop, I was going to recompile and try unlockwindowstation, but I don’t have Visual Studio. It would also be interesting to modify this to work with TS winlogon processes, rather than only the interactive console (I presume you could similarly ‘unlock’ an in-use TS session).

As an aside, below is the PowerShell script calling APIs through VB.Net embedded code, which doesn’t work in this case but it's still a valid example of how to call APIs from PowerShell (which I essentially just copied from http://monadblog.blogspot.com/2005_12_01_archive.html):



$provider = new-object Microsoft.VisualBasic.VBCodeProvider
$params = new-object System.CodeDom.Compiler.CompilerParameters
$params.GenerateInMemory = $True
$refs = "System.dll","Microsoft.VisualBasic.dll"
$params.ReferencedAssemblies.AddRange($refs)


# VB.NET EXAMPLE 
$txtCode = @'
Class FindProcessWinStation
    Declare Auto Function GetProcWinStation Lib “user32.dll” Alias "GetProcessWindowStation" () As Integer
    Declare Auto Function UnlockWinStation Lib “user32.dll” Alias "UnlockWindowStation" (ByVal WinSta As Integer) As Integer
    Declare Auto Function OpenWinStation Lib “user32.dll” Alias "OpenWindowStation" (ByVal lpszWinSta As String, ByVal fInherit as Boolean, ByVal ACCESS_MASK as Integer) As Integer
    Declare Auto Function OpenDesktop Lib “user32.dll” Alias "OpenDesktop" (ByVal lpszDesktop As String, ByVal dwFlags as Integer, ByVal fInherit as Boolean, ByVal ACCESS_MASK as Integer) As Integer
    Declare Auto Function SwitchDesktop Lib “user32.dll” Alias "SwitchDesktop" (ByVal hDesktop As Integer) As Integer
    Function Main()
        main = GetProcWinStation()
'        UnlockWinStation(main)
'        main = OpenWinStation("winsta0\\desktop", True, 895)
        main = OpenDesktop("Default", 0, True, 256)
        SwitchDesktop(main)

    End Function
end class
'@



$results = $provider.CompileAssemblyFromSource($params, $txtCode)
$mAssembly = $results.CompiledAssembly
$i = $mAssembly.CreateInstance("FindProcessWinStation")
$r = $i.main()

write-host $r



Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Sunday, April 6, 2008

Domain local security groups for cross-forest security

With multi-domain forests there is a chance of access control entries being ignored when querying a Global Catalog if domain local groups for a domain other than that of the current GC are used to secure directory objects. This can include both allowing and denying access, each of which carry risks. This is mitigated somewhat as this is limited to GC read-only operations on secured Active Directory objects, but still needs to be carefully assessed before using in multi-domain forests. There are no known issues with single-domain forests.

These issues arose in the scenario of a cross-forest administration domain, where there is little choice but to use domain local groups to secure directory objects in managed domains, thereby enabling access to be granted to global/universal groups across-forests.

This goes against general Microsoft recommendation, and some research has been completed to further understand the limitations.

Scenario:

  1. Connecting with a cross-forest account to administer a trusting domain.
  2. The cross-forest account is a member of a global or universal group in the trusted domain
  3. The cross-forest group is a member of a trusting domain local group
  4. ACLs are applied on directory objects to the domain local group.
  5. The trusting domain is one of several domains in a forest
  6. There is an external one-way NTLM trust, with each domain in the forest being accessed (but I don't believe a forest trust would change the result)
  7. ACLs are set on a local group in the trusting domain denying access to the read a security group object.
  8. The user is a member of this cross-forest domain global group that is a member of the domain local group to deny access

The cross-forest user tries to query the secured object:

  • dsquery * "CN=SecurityGroupName,CN=Users,%domainDN%" -attr * -gc

As access is denied on this object, Dsquery reports:

  • dsquery failed:The specified directory service attribute or value does not exist.

However, to bypass the security applied to the ACE, you could target the GC query at the other trustin domain in the forest:
  • dsquery * "CN=SecurityGroupName,CN=Users,%domainDN%" -attr * -gc -s DC.other.domain.in.trusting.forest

Object is successfully enumerated as the trusting domain local ACE is ignored.

The same occurs in the scenario of granting specific access to an object that would otherwise be denied or not implicity granted.

What this does not affect:

  1. Single-domain forests. The scope of domain local is not an issue as there is only one domain.
  2. LDAP 389 operations to a domain partition on a DC, rather than a read-only GC type query.
  3. Samr/netlogon operations to a Domain Controller in the trusting domain
    Replication issues. Originally it was thought that this could cause issues with replication consistency, this is not the case and only affects security on the GC.

What this could affect:

  1. Security on automated GC usage, such as Universal group enumeration (during logon or otherwise), forest-wide searches, Exchange address-book lookups and UPN logons
  2. Security on any manually initiated GC query (such as used in the testing).

Unknown:

  1. Application directory partitions with a forest-wide replication scope, such as forest dns zones. It seems the 'Security descriptor reference domain' of an application partition partially solves this issue, in addition to GC not containing replicas of any application partitions and an application directory partition can't contain security principals.

Notes:

  1. The user token contains universal, global and domain local groups for the user domain (cross-forest), not domain local groups in the DC domain. An impersonation token is created for the GC access, containing the forest-wide universal, domain global and domain local scope of the domain that the GC is in.
  2. The same can be seen through the GUI when connecting with ldp.exe to the a GC instance of one domain over 3268, and then browsing to the other domain tree
  3. Groups of scope domain local are partially replicated to the Global Catalog in the forest, so when viewing the security descriptor of an object that contains a domain local reference from another domain than the domain of the connected GC, the SID is easily resolved to a name. However, the token used to authenticate the GC query contains only the domain local groups in the GC's domain, not the intended trusting domain, causing the ACE to be ineffective.
  4. Exchange 2007 has some capability to automate the configuration of cross-forest Exchange administration. I assume it won't be too long before a Windows AD administration equivalent is available. There is reference to parallel groups and then using the ForeignForestFQDN Exchange setup option, I'm unsure of the outcome, but I assume it is universal->local->ACE (see Step 7 in 'How to Configure Cross-Forest Administration')
Excerpt from 'Global catalog replication' below:

A global catalog stores a replicated, read-only copy of all objects in the forest and a partial set of each object's attributes, including the security descriptor for each object. The security descriptor contains a discretionary access control list (DACL), which specifies permissions on the object. When a user connects to a global catalog and tries to access an object, an access check is performed based on the user's token and the object's DACL. Any permissions specified in the object's DACL for domain local groups that are not from the domain that the domain controller hosting the global catalog (to which the user has connected) belongs to, will be ineffective because only domain local groups from the global catalog's domain of which the user is a member are represented in the user's access token. As a result, a user may be denied access when access should have been granted, or allowed access when access should have been denied.

As a best practice, you should avoid using domain local groups when assigning permissions on Active Directory objects, or be aware of the implications if you do use them. To prevent unauthorized access to global catalog data, use global groups or universal groups instead. For information about global and universal groups, see Group scope.
References:

Global catalog replication
http://technet2.microsoft.com/windowsserver/en/library/8ac658b0-199c-47df-ac2b-ef9cb56fa7f01033.mspx?mfr=true

DNS zone replication in Active Directory
http://technet2.microsoft.com/windowsserver/en/library/6c0515cf-1719-4bf4-a3c0-7e3514cef6581033.mspx?mfr=true

Application directory partitions
http://technet2.microsoft.com/windowsserver/en/library/ed363e83-c043-4a50-9233-763e6f4af1f21033.mspx?mfr=true

What Is the Global Catalog?
http://technet2.microsoft.com/windowsserver/en/library/24311c41-d2a1-4e72-a54f-150483fa885a1033.mspx?mfr=true

What's New in Active Directory
http://www.microsoft.com/windowsserver2003/evaluation/overview/technologies/activedirectory.mspx

How to Configure Cross-Forest Administration (Exchange 2007)
http://technet.microsoft.com/en-us/library/bb232078.aspx

Exchange 2007 Permission Considerations
http://technet.microsoft.com/en-us/library/aa996881.aspx

Multiple Forest Considerations in Windows 2000 and Windows Server 2003
http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/directory/activedirectory/mtfstwp.mspx

Group Scope (2003):
http://technet2.microsoft.com/WindowsServer/en/library/79d93e46-ecab-4165-8001-7adc3c9f804e1033.mspx?mfr=true

Group Type and Scope Usage in Windows
http://support.microsoft.com/kb/231273

Accessing resources across-forests
http://technet2.microsoft.com/WindowsServer/en/library/517b4fa4-5266-419c-9791-6fb56fabb85e1033.mspx

Accessing resources across domains
http://technet2.microsoft.com/WindowsServer/en/library/e36ceae6-ff36-4a1b-9895-75f0eacfe94c1033.mspx


Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Account Management eventlog auditing

This post describes a method of account management event log auditing to extract relevant events from a domain for auditing and analysis. It's a simple batch file running on a server to export daily logs and collate them based on month.

Note that this is not a replacement for - or even an attempt at - a security event log management tool, it's really just a quick method of gathering events occurring in a Windows Active Directory domain.

Installation and use

  • Create ADExportEvents.bat using the batch commands below
  • Create AccountManagementEvents.txt as below or modify to suit your needs
  • Create directories to store the batch file, dumpel, daily and month logs. Get dumpel.exe from windows resource kit if you don't already have it
  • Test the batch file works from the command prompt.
  • Create a scheduled task on the DC you are running this on to run the batch file every day

This should allow:

  • Administrators to interrogate the logs, showing a holistic view of changes made throughout the domain without having to look at each DC
  • Easy tracking of one-off problems (eg. somebody accidentally deletes a user/group/group membership with or without realising)
Any number of events can be monitored, however the dumpel.exe utility used to extract the events has a limit of 10 IDs per extraction. Interesting events have been grouped in categories based on the object being targeted, which allows:
  • Inter-related events to show up in a single log file (eg. A user being created, their account being automatically locked, and then the password change to fix the problem)
  • Log files to be separated based on group, simplifying the process when looking for a particular event (eg, when a group was deleted)
To ensure this is a low-maintenance solution the task:
  • Dynamically queries the directory for a list of DCs to operate against
  • Works from a simple batch file that calls a Microsoft Resource Kit utility to export the events
  • Uses an input file describing the events to be collected in CSV format, enabling new events to be added to an existing group and new groups to be added simply by editing the control file.
Assumptions:
  • Account Management Auditing is turned on for the domain
  • Each DC has a large enough security log to store n hours of security events, where n is length between scheduled task runs
Permanent Logging

To provide logs collated by month, the following command is executed as part of the batch file. Adjust the %MonthlyLogDir% to whatever directory you choose.

For /f %%p in (%UniqueGroups%) do for /f "tokens=3,4 delims=/ " %%i in ('echo %date%') do if exist %LogDir%\AcctMgmt_%%p_%%j%%i??.txt copy %LogDir%\AcctMgmt_%%p_%%j%%i??.txt %MonthlyLogDir%\AcctMgmt_%%p_%%j%%i.txt /y 1>nul


Security

The batch file runs from one DC in the domain, querying all other DCs. This was completed by modifying the Domain Controllers Group Policy to allow the 'Domain Controllers' security group to have the 'Manage Auditing and Security Log' right, allowing any DC to look at the security log of any other DC.

Advantages of this approach:
  • Caters dynamically for the scenario when the DC performing the query changes, without having to modify scripts
  • Caters dynamically when new DCs are added, the DC running the script will have access
  • There is no need to create/maintain a new security group

Disadvantages:

  • Potential security risk - anyone with unauthorised access to a domain controller computer context can make changes to security logs and configure object access auditing on DCs. This is mitigated somewhat by the fact that if someone can run something as a DC computer account context then by default they have the rights to make any changes in the domain anyway...

Possible Improvements

  • Have each Domain Controller export local events and passing the information to a central server. If a large number of remote DCs across slow links were used (for example, more than 50 or 100) the current process would be unmanageable.

This is the CSV file used to define the group, the event ID and a description of the event, used by the batch file to determine which events to dump:

AccountManagementEvents.txt

--

Computer,645,A computer account was created.
Computer,647,A computer account was deleted.
Policy,643,A domain policy was modified.

Account,624,A user account was created.
Account,630,A user account was deleted.
Account,685,Name of an account was changed.
Account,684,Set the security descriptor of members of administrative groups, Every 60 minutes on a domain controller a background thread searches all members of administrative groups (such as domain, enterprise, and schema administrators) and applies a fixed security descriptor on them. This event is logged.

AccountPwd,627,A user password was changed.
AccountPwd,628,A user password was set.
AccountPwd,644,A user account was auto locked.

Group,631,A global group was created.
Group,634,A global group was deleted.
Group,635,A new local group was created.
Group,668,A group type was changed.
Group,639,A local group account was changed.
Group,638,A local group was deleted.
Group,649,A local security group with security disabled was changed.
Group,648,A local security group with security disabled was created, SECURITY_DISABLED in the formal name means that this group cannot be used to grant permissions in access checks.

GroupMembership,632,A member was added to a global group.
GroupMembership,636,A member was added to a local group.
GroupMembership,633,A member was removed from a global group.
GroupMembership,637,A member was removed from a local group.

SecDisGroupMem,656,A member was removed from a security-disabled global group.
SecDisGroupMem,651,A member was removed from a security-disabled local security group.
SecDisGroupMem,666,A member was removed from a security-disabled universal group.
SecDisGroupMem,661,A member was removed from a security-enabled universal group.
SecDisGroupMem,655,A member was added to a security-disabled global group.
SecDisGroupMem,650,A member was added to a security-disabled local security group.
SecDisGroupMem,665,A member was added to a security-disabled universal group.
SecDisGroupMem,660,A member was added to a security-enabled universal group.

SecDisGroup,654,A security-disabled global group was changed.
SecDisGroup,653,A security-disabled global group was created.
SecDisGroup,657,A security-disabled global group was deleted.
SecDisGroup,652,A security-disabled local group was deleted.
SecDisUniGroup,664,A security-disabled universal group was changed.
SecDisUniGroup,663,A security-disabled universal group was created.
SecDisUniGroup,667,A security-disabled universal group was deleted.
SecDisUniGroup,659,A security-enabled universal group was changed.
SecDisUniGroup,658,A security-enabled universal group was created.
SecDisUniGroup,662,A security-enabled universal group was deleted.


--

ADExportEvents.bat

--
@echo off
for /f "tokens=1,2" %%i in ('date /t') do @for /f "tokens=1,2,3 delims=/" %%m in ('echo %%j') do @set LOGDATE=%%o%%n%%m
Set Log=%temp%\%~n0_%logdate%.log
Set LogDir=c:\Logs\Daily
Set MonthlyLogDir=c:\Logs\Monthly
Set Events=AccountManagementEvents.txt
Set UniqueGroups=%Temp%\AccManUnique.txt
Set DCList=%Temp%\DCList.txt
Set NoOfDays=1

:Start
Echo Started %Date% %Time%
Echo Started %Date% %Time% > %log%

If Not Exist %Events% (
Echo Error: %Events% could not be found
Echo Error: %Events% could not be found > %log%
Goto End
)

If Exist %UniqueGroups% Del %UniqueGroups%
If Exist %DCList% Del %DCList%

:: Find the domain controllers for the local domain
dsquery.exe server -o rdn > %DCList%

:: Find the unique groups from the events we are going to process
for /f "tokens=1-3 delims=," %%i in (%Events%) do @Find /i "%%i" %UniqueGroups% 1>nul 2>nul & If errorlevel 1 echo %%i >> %UniqueGroups%

:: For each group of events, call the sub
For /f %%i in (%UniqueGroups%) do Call :ProcessEventGroup %%i

Echo Collating monthly logs
For /f %%p in (%UniqueGroups%) do for /f "tokens=3,4 delims=/ " %%i in ('echo %date%') do if exist %LogDir%\AcctMgmt_%%p_%%j%%i??.txt copy %LogDir%\AcctMgmt_%%p_%%j%%i??.txt %MonthlyLogDir%\AcctMgmt_%%p_%%j%%i.txt /y 1>nul

Echo Finished %Date% %Time%
Echo Finished %Date% %Time% > %log%
Goto End

:ProcessEventGroup
Set EventList=

:: For Each event in the event file, add the ID if it belongs to this group (calling a sub because for /f doesn't work with repeated inline references to variables
For /f "tokens=1-3 delims=," %%m in (%Events%) do if /i _%1==_%%m Call :AddEvent %%n

Set OutputFile=%logdir%\AcctMgmt_%1_%LogDate%.txt
Echo Dumping %1 events IDs: %EventList% to %OutputFile%

:: For each DC in the domain, dump the events
For /f %%p in (%DCList%) do Echo Processing %%p & dumpel.exe -d %NoOfDays% -e %EventList% -l Security -m Security -s %%p -c >> %OutputFile%
Goto End

:AddEvent
:: Concatenate the latest ID
Set EventList=%EventList% %1
Goto End
:End

--


References:
Information on the 'Manage Auditing and Security Log' Right:
http://technet2.microsoft.com/WindowsServer/en/Library/4e1fa44d-d283-4709-a8ef-460b3611f4031033.mspx?mfr=true http://www.microsoft.com/technet/security/prodtech/windows2000/w2kccscg/w2kscgcb.mspx http://www.microsoft.com/technet/prodtechnol/winxppro/reskit/z02b621675.mspx




Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Thursday, April 3, 2008

Running scheduled tasks as a non-administrator

This post contains information on creating and running a scheduled task on a Windows Server 2003 system with a non-administrative account, following the Principle of Least Privilege methodology.

By default, running a task as a non-administrative poses several problems, but overcoming these problems can help reduce the attack surface and adhere to the Principles of Least Privilege.

To ensure the task will run successfully:

  1. Create the user account, either locally or in a domain.
  2. Ensure the user is only a member of the users group and any groups required for local and remote resource access (eg. Data fileshares, application access)
  3. Ensure the user has local access to the files required to run the command, eg. By default cscript.exe has ACLs requiring either administrative or system/service/batch/interactive access, but the account or NT Authority\Batch will also need access to the script file, and possibly temp and/or log directories. Note that this should be recorded in security templates, allowing for automatic reapplication of security.
  4. Create the task and set the task to be run as the newly created account. Note that doing this will automatically grant the 'log on as a batch job' (SeBatchLogonRight) right to allow the task to start.
  5. Ensure that the user account has at a minimum, Read, Execute and Write permissions to the schedule .job file
  6. Run the task, checking the Scheduled Task log if a result other than success is returned (0x0). Note that if account auditing is enabled, the Security event log should show a Logon Event 528, of Type 4 (LOGON32_LOGON_BATCH) for the newly created account.
Notes:

  • While developing this process, the Service principal (S-1-5-6) was tested, which was unsuccessful, as the scheduled task is started as a batch job, rather than the schedule (or any other) service.
  • IMPORTANT: Ensure that the shell executable (cmd.exe, cscript.exe, powershell.exe etc.) is accessible to the 'NT Authority\Batch' security principle eg. when running the command cscript d:\admin\local\scripts\test.wsf, the 'NT Authority\Batch' security principle must have access to cscript.exe as well as the .wsf script file. Access can also be granted to an account/group rather than batch if this is too permissive.
  • When a task starts, the command is created under the security context of the specified user, and the user token has the Batch SID (S-1-5-3) attached. This is a well-known security principal, commonly displayed as 'NT Authority\Batch'

References:

Well-known Security Identifiers:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/well_known_sids.asp

Security Identifier Types:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/well_known_sid_type.asp

SECURITY_LOGON_TYPE Enumeration:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthn/security/security_logon_type.asp

Audit Logon Events:

http://technet2.microsoft.com/WindowsServer/en/Library/e104c96f-e243-41c5-aaea-d046555a079d1033.mspx




Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

Friday, March 7, 2008

SDDL syntax in secedit security templates

My summary of the SDDL syntax and security templates with regards to inheritance:

  • The second column in a security template entry dictates the action on existing explicit ACE's, 0 will merge, 2 will overwrite (and 1 is used during OS install).
  • DACL flags, P - Protected against inheriting from above, AI - Automatically propagate the ACL to child objects (assuming P not set deeper), AR - same as AR but checks if the file system supports automatic propagation of inheritable ACE's (eg. NT4)
  • ACE OI - Object Inherit, subordinate files will inherit the ACE - including files deeper in the tree (unless NP is set). Equivalent to 'This folder and files' in the GUI.
  • ACE CI - Container Inherit, subordinate containers will inherit the ACE - including directories deeper in the tree (unless NP is set). Direct children will inherit the ACE. Equivalent to 'This folder and subfolders' in the GUI.
  • ACE OICI - Combination of OI an CI above. Equivalent to 'This folder, subfolders, and files' in the GUI
  • ACE NP - Non-propagate, subordinate objects will not propagate the inherited ACE any further

For example:
SDDL:

"C:\Test\",0,"D:PAR(A;OICI;FA;;;BA)(A;OICINP;0x1200a9;;;BU)(A;OICI;FA;;;SY)"

"C:\Test\AAAA",0,"D:AR(A;OICI;FA;;;BA)(A;OICI;0x1200a9;;;BU)(A;OICI;FA;;;SY)"

"C:\Test\BBBB",0,"D:PAR(A;OICI;FA;;;BA)(A;OI;0x1301bf;;;BU)(A;OICI;FA;;;SY)"

"C:\Test\CCCC",2,"D:(A;OICI;FA;;;BA)(A;CI;0x1200a9;;;BU)(A;OICI;FA;;;SY)"

Explanation:

  • C:\Test - Protected from above, Auto-inherit below, merge with explicit ACL, Users:R for 'This folder, subfolders, and files' and non-propagate on the ACE. This will ensure access to the root, sub-folders and files in the root for all users, except for any secured sub-folders not inherit this ACE.
  • C:\Test\AAAA - Allow inherit from above (not protected), auto-inherit below, merge with explicit ACL, Users:R.
  • C:\Test\BBBB - Protected from above, auto-inherit below, merge with explicit ACL, Users:C to subordinate files, but not containers - 'This folder and files'
  • C:\Test\CCCC - Allow inherit from above (not protected), do not automatically propagate deeper (no AR), overwrite explicit ACL, container inherit - 'This folder and subfolders'

Note that to apply such a security template on a remote machine, you could run (assuming the security template location):

  • psexec \\%server% secedit /configure /db c:\windows\temp\%random%.sdb /cfg c:\windows\security\templates\%template%.inf /log c:\windows\temp\Configure.log

References:

Win32_SecurityDescriptor Class

Security Descriptor String Format

Understanding Container Access Inheritance Flags in Windows 2000

Unexpected Results Occur If You Set File Security by Using Either Group Policy or Security Templates



Wayne's World of IT (WWoIT), Copyright 2008 Wayne Martin.


Read more!

All Posts

printQueue AD objects for 2003 ClusterVirtualCenter Physical to VirtualVirtual 2003 MSCS Cluster in ESX VI3
Finding duplicate DNS recordsCommand-line automation – Echo and macrosCommand-line automation – set
Command-line automation - errorlevels and ifCommand-line automation - find and findstrBuilding blocks of command-line automation - FOR
Useful PowerShell command-line operationsMSCS 2003 Cluster Virtual Server ComponentsServer-side process for simple file access
OpsMgr 2007 performance script - VMware datastores...Enumerating URLs in Internet ExplorerNTLM Trusts between 2003 and NT4
2003 Servers with Hibernation enabledReading Shortcuts with PowerShell and VBSModifying DLL Resources
Automatically mapping printersSimple string encryption with PowerShellUseful NTFS and security command-line operations
Useful Windows Printer command-line operationsUseful Windows MSCS Cluster command-line operation...Useful VMware ESX and VC command-line operations
Useful general command-line operationsUseful DNS, DHCP and WINS command-line operationsUseful Active Directory command-line operations
Useful command-linesCreating secedit templates with PowerShellFixing Permissions with NTFS intra-volume moves
Converting filetime with vbs and PowerShellDifference between bat and cmdReplica Domain for Authentication
Troubleshooting Windows PrintingRenaming a user account in ADOpsMgr 2007 Reports - Sorting, Filtering, Charting...
WMIC XSL CSV output formattingEnumerating File Server ResourcesWMIC Custom Alias and Format
AD site discoveryPassing Parameters between OpsMgr and SSRSAnalyzing Windows Kernel Dumps
Process list with command-line argumentsOpsMgr 2007 Customized Reporting - SQL QueriesPreventing accidental NTFS data moves
FSRM and NTFS Quotas in 2003 R2PowerShell Deleting NTFS Alternate Data StreamsNTFS links - reparse, symbolic, hard, junction
IE Warnings when files are executedPowerShell Low-level keyboard hookCross-forest authentication and GP processing
Deleting Invalid SMS 2003 Distribution PointsCross-forest authentication and site synchronizati...Determining AD attribute replication
AD Security vs Distribution GroupsTroubleshooting cross-forest trust secure channels...RIS cross-domain access
Large SMS Web Reports return Error 500Troubleshooting SMS 2003 MP and SLPRemotely determine physical memory
VMware SDK with PowershellSpinning Excel Pie ChartPoke-Info PowerShell script
Reading web content with PowerShellAutomated Cluster File Security and PurgingManaging printers at the command-line
File System Filters and minifiltersOpsMgr 2007 SSRS Reports using SQL 2005 XMLAccess Based Enumeration in 2003 and MSCS
Find VM snapshots in ESX/VCComparing MSCS/VMware/DFS File & PrintModifying Exchange mailbox permissions
Nested 'for /f' catch-allPowerShell FindFirstFileW bypassing MAX_PATHRunning PowerSell Scripts from ASP.Net
Binary <-> Hex String files with PowershellOpsMgr 2007 Current Performance InstancesImpersonating a user without passwords
Running a process in the secure winlogon desktopShadow an XP Terminal Services sessionFind where a user is logged on from
Active Directory _msdcs DNS zonesUnlocking XP/2003 without passwords2003 Cluster-enabled scheduled tasks
Purging aged files from the filesystemFinding customised ADM templates in ADDomain local security groups for cross-forest secu...
Account Management eventlog auditingVMware cluster/Virtual Center StatisticsRunning scheduled tasks as a non-administrator
Audit Windows 2003 print server usageActive Directory DiagnosticsViewing NTFS information with nfi and diskedit
Performance Tuning for 2003 File ServersChecking ESX/VC VMs for snapshotsShowing non-persistent devices in device manager
Implementing an MSCS 2003 server clusterFinding users on a subnetWMI filter for subnet filtered Group Policy
Testing DNS records for scavengingRefreshing Computer Account AD Group MembershipTesting Network Ports from Windows
Using Recovery Console with RISPAE Boot.ini Switch for DEP or 4GB+ memoryUsing 32-bit COM objects on x64 platforms
Active Directory Organizational Unit (OU) DesignTroubleshooting computer accounts in an Active Dir...260+ character MAX_PATH limitations in filenames
Create or modify a security template for NTFS perm...Find where a user is connecting from through WMISDDL syntax in secedit security templates

About Me

I’ve worked in IT for over 20 years, and I know just about enough to realise that I don’t know very much.