Windows PowerShell for Administration: The Personal Trainer (2015)
Chapter 6. Managing and Securing the Registry
The Windows registry stores configuration settings. Using the Registry provider built into Windows PowerShell, you can view, add, delete, compare, and copy registry entries. Because the Windows registry is essential to the proper operation of the operating system, make changes to the registry only when you know how these changes will affect the system. You should perform all registry changes within the context of a transaction. Transactions were discussed in the “Creating Transactions” section in Chapter 1, “Managing Computers with Commands and Scripts.” With transactions, you can do the following:
1. Use Start-Transaction to start a transaction before you modify the registry.
2. Make changes and then verify your changes.
3. Use Stop-Transaction to finalize your changes or Undo-Transaction to roll back your changes.
After you finalize a transaction using Stop-Transaction, you can no longer undo your changes. Additionally, transactions won’t help you identify changes that will cause problems with the computer and its installed components and applications. Therefore, before you edit the registry in any way, you should create a system restore point. This way, if you make a mistake, you can recover the registry and the system.
CAUTION Improperly modifying the Windows registry can cause serious problems. If the registry becomes corrupted, you might have to reinstall the operating system. Double-check the commands you use. Make sure that they do exactly what you intend.
Understanding Registry Keys and Values
The Windows registry stores configuration settings for the operating system, applications, users, and hardware. Registry settings are stored as keys and values, which are placed under a specific root key controlling when and how the keys and values are used.
Table 6-1 lists the registry root keys you can work with in PowerShell as well as a description and the reference name you use to refer to the root key when working with the Registry provider. Under the root keys, you’ll find the main keys that control system, user, application, and hardware settings. These keys are organized into a tree structure, with folders representing keys. Within these folders are the registry keys that store important service configuration settings and their subkeys.
TABLE 6-1 Keys in the Windows Registry
ROOT KEY |
REFERENCE NAME |
DESCRIPTION |
HKEY_CURRENT_USER |
HKCU |
Stores configuration settings for the current user. |
HKEY_LOCAL_MACHINE |
HKLM |
Stores system-level configuration settings. |
HKEY_CLASSES_ROOT |
HKCR |
Stores configuration settings for applications and files. It also ensures that the correct application is opened when a file is accessed. |
HKEY_USERS |
HKU |
Stores default-user and other-user settings by profile. |
HKEY_CURRENT_CONFIG |
HKCC |
Stores information about the hardware profile being used. |
Keys that you want to work with must be designated by their folder path. For example, under HKLM\SYSTEM\CurrentControlSet\Services, you’ll find folders for all services installed on the system. Values associated with the DNS key in this folder path allow you to work with the Domain Name System (DNS) service and its configuration settings.
Key values are stored as a specific data type. Table 6-2 provides a summary of the main data types used with keys.
TABLE 6-2 Registry Key Values and Data Types
DATA TYPE |
DESCRIPTION |
REFERENCE NAME |
EXAMPLE |
REG_BINARY |
Identifies a binary value. Binary values are stored using base2 (0 or 1 only) but are displayed and entered in hexadecimal (base16) format. |
Binary |
01 00 14 80 90 00 00 9C 00 |
REG_DWORD |
Identifies a binary data type in which 32-bit integer values are stored as four byte-length values in hexadecimal. |
Dword |
0x00000002 |
REG_EXPAND_SZ |
Identifies an expandable string value, which is usually used with directory paths. |
Expandstring |
%SystemRoot%\dns.exe |
REG_MULTI_SZ |
Identifies a multiple-string value. |
Multistring |
Tcpip Afd RpcSc |
REG_NONE |
Identifies data without a particular type. This data is written as binary values but is displayed and entered in hexadecimal (base16) format. |
None |
23 45 67 80 |
REG_QWORD |
Identifies a binary data type in which 64-bit integer values are stored as eight byte-length values in hexadecimal. |
Qword |
0x0000EA3FC |
REG_SZ |
Identifies a string value containing a sequence of characters. |
String |
DNS Server |
Navigating the Registry
The core set of features for performing related procedures was discussed previously in Windows PowerShell: The Personal Trainer, and include the Registry provider, the cmdlets for working with data stores, and the cmdlets for working with provider drives. As long as you know the key path and understand the available key data types, you can use the Registry provider to view and manipulate keys in a variety of ways.
By default, only the HKLM and HKCU root keys are available in PowerShell. To make other root keys available, you can register them as new PowerShell drives. The following example shows how to register HKCR, HKU, and HKCC:
new-psdrive –name hkcr –psprovider registry –root hkey_classes_root
new-psdrive –name hku –psprovider registry –root hkey_users
new-psdrive –name hkcc –psprovider registry –root hkey_current_config
Now you can directly access these additional root keys. For example, if you want to access HKCC, you type
set-location hkcc:
You can access keys and values in any Registry location using Set-Location. For example, if you want to change the location to HKLM, you type
set-location hklm:
You can then work with registry keys and values in HKLM. Locations under HKLM (or any other root key) are navigated in the same way you navigate directory paths. If you are working with HKLM, for example, you can use Set-Location (or CD) to change to HKLM\SYSTEM\CurrentControlSet\Services by typing
set-location system\currentcontrolset\services
Alternatively, to access HKLM and start in this location in the first place, you can type
set-location hklm:\system\currentcontrolset\services
NOTE If you specify a nonexistent path, key, or value, an error message is displayed. Typically, it reads: Cannot find _________ because it does not exist.
When you are working with a Registry location and want to view the available keys, type get-childitem (or dir) as shown in the following example and sample output:
set-location hklm:\system\currentcontrolset\services
get-childitem
Hive: HKEY_LOCAL_MACHINE\system\currentcontrolset\services
Name Property
---- --------
.NET CLR Data
.NET CLR Networking
.NETFramework
1394ohci ImagePath :
\SystemRoot\System32\drivers\1394ohci.sys
Type : 1
Start : 3
ErrorControl : 1
DisplayName :
@1394.inf,%PCI\CC_0C0010.DeviceDesc%;
1394 OHCI Compliant Host Controller
Owners : {1394.inf}
Group :
ACPI ImagePath : System32\drivers\ACPI.sys
Type : 1
Start : 0
ErrorControl : 3
DisplayName :
@acpi.inf,%ACPI.SvcDesc%;
Microsoft ACPI Driver
Owners : {acpi.inf}
Tag : 2
Group : Core
The following information is provided in this output:
· SKC shows the subkey count under the named key.
· VC shows the value count, which is the number of values under the named key.
· Name shows the name of the subkey.
· Property lists the names of properties for the named key.
To learn more about navigating the registry, let’s focus on the APCI key. In this example, you know ACPI has a number of named property values. You can list these property values by typing get-itemproperty as shown in the following example and sample output:
set-location hklm:\system\currentcontrolset\services\acpi
get-itemproperty .
ImagePath : System32\drivers\ACPI.sys
Type : 1
Start : 0
ErrorControl : 3
DisplayName : @acpi.inf,%ACPI.SvcDesc%;Microsoft ACPI Driver
Owners : {acpi.inf}
Tag : 2
Group : Core
PSPath : Microsoft.PowerShell.Core\Registry:
:HKEY_LOCAL_MACHINE\system\currentcontrolset\services\acpi
PSParentPath : Microsoft.PowerShell.Core\Registry:
:HKEY_LOCAL_MACHINE\system\currentcontrolset\services
PSChildName : acpi
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
You don’t have to access a location to view its properties. The value you provide to Get-Item Property is a path. In the previous example, the dot (.) refers to the current working location. If you were working with another drive or location, you could enter the full path to the key to get the same results, as shown in this example:
get-itemproperty hklm:\system\currentcontrolset\services\acpi
Continuing this example, you know there are two source keys and seven key values under ACPI. If you access ACPI, you can list the two source keys by typing get-childitem (or dir) as shown in this example and sample output:
set-location hklm:\system\currentcontrolset\services\acpi
get-childitem
Hive: HKEY_LOCAL_MACHINE\system\currentcontrolset\services\acpi
Name Property
---- --------
Parameters WHEAOSCImplemented : {0, 0, 0, 0}
APEIOSCGranted : {0, 0, 0, 0}
Enum 0 : ACPI_HAL\PNP0C08\0
Count : 1
NextInstance : 1
As with Get-ItemProperty, Get-ChildItem also accepts a path. This means you can use Get-ChildItem and enter the full path to the key to get the same results shown in the previous example:
get-childitem hklm:\system\currentcontrolset\services\acpi
If you access the enum key under ACPI, you’ll find several properties, including Count and NextInstance. Although you can use Get-ChildItem to view the values of all related properties, you’ll more typically want to view and work with individual property values. To do this, get the properties and store the results in a variable. This allows you to then view and work with properties individually as shown in the following example and sample output:
$p = get-itemproperty hklm:\system\currentcontrolset\services\acpi\enum
$p.count
1
Alternatively, you can read registry values by referencing the full path and name of the property value that you want to examine. The basic syntax is
get-itemproperty [–path] KeyPath [–name] ValueName
where KeyPath is the path of the key you want to examine and ValueName is an optional parameter that specifies a specific key value. Here is an example with sample output:
get-itemproperty hklm:\system\currentcontrolset\services\acpi\enum count
Count : 1
PSPath : Microsoft.PowerShell.Core\Registry:
:HKEY_LOCAL_MACHINE\system\currentcontrolset\services\acpi\enum
PSParentPath : Microsoft.PowerShell.Core\Registry:
:HKEY_LOCAL_MACHINE\system\currentcontrolset\services\acpi
PSChildName : enum
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
As you can see, the output includes path, drive, and provider values as well as the value of the property you are examining. You can filter the output so that you see only the property value using Format-List, as shown in the following example:
get-itemproperty hklm:\system\currentcontrolset\services\acpi\enum `
count | format-list –property count
Count : 1
NOTE To work with the registry on remote computers, use the Invoke-Command cmdlet as discussed in Windows PowerShell: The Personal Trainer. Here is an example:
invoke-command -computername Server43, Server27, Server82 `
-scriptblock { get-itemproperty `
hklm:\system\currentcontrolset\services\acpi\enum }
Alternatively, you can establish remote sessions using the New-PSSession cmdlet and then run individual commands against each computer automatically. Here is an example:
$s = new-PSSession –computername Server43, Server27, Server82
invoke-command –session $s -scriptblock {get-itemproperty `
hklm:\system\currentcontrolset\services\acpi\enum}
Managing Registry Keys and Values
When you are working with the Registry provider, you have many Item and ItemProperty cmdlets available for managing registry keys and values. You’ll use these cmdlets to create, copy, move, rename, and delete registry items.
Creating Registry Keys and Values
You can easily add subkeys and values to the Windows registry using PowerShell. To create keys, you use the New-Item cmdlet. To create key values, you use the New-ItemProperty cmdlet. The basic syntax for creating a key is
new-item [–type registrykey] [–path] Path
where you can optionally specify the type of item you are creating as Registrykey and then use Path to specify where the key should be created. When you create a registry key, New-Item displays results that confirm the creation process. In the following example, you create an HKCU:\Software\Test key, and the resulting output confirms that the key was successfully created:
new-item -type registrykey -path hkcu:\software\test
Hive: HKEY_CURRENT_USER\software
Name Property
---- --------
test
NOTE To create keys and set key values on remote computers, use the Invoke-Command cmdlet as discussed in Windows PowerShell: The Personal Trainer. Here is an example:
invoke-command -computername Server43, Server27, Server82 `
-scriptblock { new-item hkcu:\software\test }
As long as you have the appropriate permissions to create the key in the specified location, the creation process should be successful. If the key already exists, however, you’ll see an error stating the following: “A key at this path already exists.”
The basic syntax for creating a key value is
new-itemproperty [–path] Path [-name] Name [-type Type]
[-value Value]
where Path is the path to an existing registry key, Name is the name of the value, Type is the value type, and Value is the value to assign. Permitted value types are listed by their reference name in Table 6-2. As the table shows, valid types include Binary, Dword, Expandstring, Multistring, None, and String.
When you create a key value, New-ItemProperty displays results that confirm the creation process. In the following example, you create a string value called Data under the HKCU:\Software\Test key, and the resulting output confirms that the key value was successfully created:
new-itemproperty -path hkcu:\software\test Data –type "string" `
–value "Current"
Data : Current
PSPath : Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software\test
PSParentPath : Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software
PSChildName : test
PSDrive : HKCU
PSProvider : Microsoft.PowerShell.Core\Registry
As long as you have the appropriate permissions to create the key in the specified location, the creation process should be successful. If the key value already exists, however, you’ll see an error stating the following: “The property already exists.”
Copying Registry Keys and Values
You can copy registry keys using Copy-Item. The basic syntax is
copy-item SourcePath DestinationPath
where SourcePath is the path to the registry key to copy and DestinationPath is where you’d like to create a copy of the registry. In the following example, you copy the HKCU:\Software\Test key (and all its contents) to HKLM:\Software\Dev:
copy-item hkcu:\software\test hklm:\software\dev
As long as you have the appropriate permissions, you should be able to copy registry keys. When you copy a key, Copy-ItemProperty displays an error that indicates failure but doesn’t display any output to indicate success.
You can copy registry values using Copy-ItemProperty. The basic syntax is
copy-itemproperty [–path] SourcePath [-destination] DestinationPath [–name] KeyValueToCopy
where SourcePath is the current path to the key value, DestinationPath is the new path for the copy of the key value, and KeyValueToCopy identifies the key value you want to copy. In the following example, you copy the Data value from the HKCU:\Software\Test key to the HKLM:\Software\Dev key:
copy-itemproperty -path hkcu:\software\test -destination `
hklm:\software\dev -name data
As long as you have the appropriate permissions and the source value exists, you should be able to copy the key value. You can use Copy-ItemProperty to copy multiple key values. Use comma-separated values or wildcard characters as appropriate.
Moving Registry Keys and Values
You can move keys and their associated values using Move-Item. The basic syntax is
move-item SourcePath DestinationPath
where SourcePath is the current path to the key and DestinationPath is the new path to the key. When you move a key, Move-Item displays an error that indicates failure but doesn’t display any output to indicate success. In the following example, you move the HKCU:\Software\Test key (and all its contents) to the HKCU:\Software\Test2 key:
move-item hkcu:\software\test hkcu:\software\test2
As long as you have the appropriate permissions, you should be able to move keys. You can use Move-Item to move keys from one root to another. For example, you can move HKCU:\Software\Test to HKLM:\Software\Test.
You can move key values using Move-ItemProperty. The basic syntax is
move-itemproperty [–path] SourcePath [-destination] DestinationPath [–name] KeyValueToMove
where SourcePath is the current path to the key value, DestinationPath is the new path to the key value, and KeyValueToMove identifies the key value you want to move. When you move a key value, Move-ItemProperty displays an error that indicates failure but doesn’t display any output to indicate success. In the following example, you move the Data value from the HKCU:\Software\Test key to the HKLM:\Software\Test key:
move-itemproperty -path hkcu:\software\test -destination `
hklm:\software\test2 -name data
As long as you have the appropriate permissions and the source and destination keys exist, you should be able to move the key value. You can use Move-ItemProperty to move multiple key values. Use comma-separated values or wildcard characters as appropriate.
Renaming Registry Keys and Values
To rename keys, you use the Rename-Item cmdlet. Rename-Item has the following syntax
rename-item OriginalNamePath NewName
where OriginalNamePath is the full path to the key and NewName is the new name for the key. In the following example, you rename Test under HKCU:\Software as Test2:
rename-item hkcu:\software\test test2
As long as you have the appropriate permissions, you should be able to rename keys.
To rename key values, you use the Rename-ItemProperty cmdlet. Rename-ItemProperty has the following syntax
rename-item [-path] OriginalNamePath [-name] CurrentName [–newname] NewName
where OriginalNamePath is the full path to the key value and NewName is the new name for the key value. In the following example, you rename Data under the HKCU:\Software\Test key as EntryType:
rename-itemproperty –path hkcu:\software\test2 –name data `
–newname entrytype
As long as you have the appropriate permissions, you should be able to rename keys.
Deleting Registry Keys and Values
You can delete registry keys using the Remove-Item cmdlet. Remove-Item has the following syntax
remove-item NamePath [-Force]
where NamePath is the full path to the registry key that you want to remove, and –Force is an optional parameter to force the removal of the key. In the following example, you delete the HKCU:\Software\Test2 key (and all its contents):
remove-item hkcu:\software\test2
As long as you have the appropriate permissions, you should be able to remove registry keys.
You can delete key values using the Remove-ItemProperty cmdlet. Remove-ItemProperty has the following syntax
remove-itemproperty [-Path] KeyPath [-Name] ValueName [-Force]
where KeyPath is the full path to the registry key that contains the value you want to remove, ValueName is the name of the value to remove, and –Force is an optional parameter to force the removal of the key value. In the following example, you delete the Data value for the HKCU:\Software\Test key:
remove-itemproperty –path hkcu:\software\test –name data
As long as you have the appropriate permissions, you should be able to remove key values.
Comparing Registry Keys
You can compare registry entries and values between and among computers or between two different keys on the same system. Performing registry comparisons is useful in the following situations:
· When you are trying to troubleshoot service and application configuration issues.
At such times, it is useful to compare the registry configurations between two different systems. Ideally, these systems include one registry that appears to be configured properly and one that you suspect is misconfigured. You can then perform a comparison of the configuration areas that you suspect are causing problems.
· When you want to ensure that an application or service is configured the same way on multiple systems.
Here you use one system as the basis for testing the other system configurations. Ideally, the basis system is configured exactly as expected before you start comparing its configuration with other systems.
To see how you can compare registry values across computers, consider the following example and sample output:
$c1 = "techpc18"
$c2 = "engpc25"
$p = invoke-command -computername $c1 -scriptblock {
get-itemproperty `
hklm:\system\currentcontrolset\services\acpi\enum }
$h = invoke-command -computername $c2 -scriptblock {
get-itemproperty `
hklm:\system\currentcontrolset\services\acpi\enum }
if ($p = $h) {write-host $True} else {
write-host "Computer: $c1"
write-host $p
write-host "Computer: $c2"
write-host $h}
True
When you run these commands at an elevated administrator PowerShell prompt and the remote computers are configured for remoting, you get a comparison of the specified keys on both computers. If the keys have the same values, PowerShell writes True to the output as shown. Otherwise, PowerShell writes the values associated with each key on each computer, allowing you to see where there are differences.
You can easily extend this comparison technique so that you can compare the values on a computer you know is configured correctly with multiple computers in the enterprise that you want to check. An example and sample output follow:
$clist = "techpc18", "techpc25", "techpc36"
$src = "engpc25"
$ps = invoke-command -computername $clist -scriptblock {
get-itemproperty `
hklm:\system\currentcontrolset\services\acpi\enum }
$h = invoke-command -computername $src -scriptblock {
get-itemproperty `
hklm:\system\currentcontrolset\services\acpi\enum }
$index = 0
foreach ($p in $ps) {
if ($p = $h) {write-host $clist[$index] "same as $src" } else {
write-host "Computer:" $clist[$index]
write-host $p
write-host "Computer: $src"
write-host $h
$index++}
}
techpc18 same as engpc25
techpc25 same as engpc25
techpc36 same as engpc25
Here, you check the registry on multiple target computers and compare key values with a source computer. If a target computer has different values for the key compared, you list the target computer’s values followed by the source computer’s values. This allows you to see where there are differences.
Viewing and Managing Registry Security Settings
As an administrator, you’ll sometimes need to view and manage security settings in the registry. In PowerShell, these tasks are accomplished using Get-Acl and Set-Acl. The syntax for these commands is as follows:
· Get-Acl Gets objects that represent the security descriptor of registry keys. Use –Audit to get the audit data for the security descriptor from the access control list.
Get-Acl [-Path] KeyPaths {AddtlParams}
AddtlParams=
[-Audit] [-Exclude KeysToExclude] [-Include KeysToInclude]
· Set-Acl Changes the security descriptor of registry keys. Use –Aclobject to specify the desired security settings.
Set-Acl [-Path] KeyPaths [-Aclobject] Security {AddtlParams}
AddtlParams=
[-Exclude KeysToExclude] [-Include KeysToInclude]
Whenever you are working with registry keys, you might want to view or modify the security descriptor. Use Get-Acl with the –Path parameter to specify the path to resources you want to work with. You can use wildcard characters in the path, and you can also include or exclude keys using the –Include and –Exclude parameters.
Getting and Setting Registry Security Descriptors
Get-Acl returns a separate object containing the security information for each matching key. By default, Get-Acl displays the path to the resource, the owner of the resource, and a list of the access control entries on the resource. The access control list is controlled by the resource owner. To get additional information, including the security group of the owner, a list of auditing entries, and the full security descriptor as an SDDL (Security Descriptor Definition Language) string, format the output as a list as shown in the following example and sample output:
get-acl hklm:\software\test | format-list
Path : Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software\test
Owner : BUILTIN\Administrators
Group : IMAGINEDLANDS\Domain Users
Access : IMAGINEDLANDS\williams Allow FullControl
NT AUTHORITY\SYSTEM Allow FullControl
BUILTIN\Administrators Allow FullControl
NT AUTHORITY\RESTRICTED Allow ReadKey
Audit :
Sddl : O:BAG:DUD:(A;OICIID;KA;;;S-1-5-21-3359847396-
3574526683-113705776-1107)(A;OICIID;KA;;;SY)
(A;OICIID;KA;;;BA)(A;OICIID;KR;;;RC)
NOTE You can view and manage registry security on remote computers using any of the remoting techniques discussed in Windows PowerShell: The Personal Trainer. Here is an example:
invoke-command -computername Server16, Server12, Server18 `
-scriptblock { get-acl hklm:\software\test | format-list }
Here, Get-Acl returns a RegistrySecurity object representing the security descriptor of the HKLM:\Software\Test key. The result is then sent to the Format-List cmdlet. You can work with any properties of security objects separately, including the following:
· Owner Shows the owner of the resource
· Group Shows the primary group the owner is a member of
· Access Shows the access control rules on the resource
· Audit Shows the auditing rules on the resource
· Sddl Shows the full security descriptor as an SDDL string
NOTE RegistrySecurity objects have additional properties that aren’t displayed as part of the standard output. To see these properties, send the output to Format-List *. You’ll then see the following note and script properties: PSPath (the PowerShell path to the resource), PSParentPath (the PowerShell path to the parent resource), PSChildName (the name of the resource), PSDrive (the PowerShell drive on which the resource is located), AccessToString (an alternate representation of the access rules on the resource), and AuditToString (an alternate representation of the audit rules on the resource).
You can use the objects that Get-Acl returns to set the security descriptors on registry keys. To do this, open an elevated administrator PowerShell prompt, obtain a single security descriptor object for a registry key that has the security settings you want to use, and then use the security descriptor object to establish the desired security settings for another registry key. An example and sample output follow:
set-acl –path hkcu:\software\dev -aclobject (get-acl hklm:\software\test)
Here you use the security descriptor on HKLM:\Software\Test to set the security descriptor for HKCU:\Software\Dev.
You can easily extend this technique. In this example, you use the security descriptor on HKLM:\Software\Test to set the security descriptor for subkeys directly under the HKCU:\Software\Dev key:
$secd = get-acl hklm:\software\test
set-acl –path hkcu:\software\dev\* -aclobject $secd
To include keys in subpaths, you need to use Get-ChildItem to obtain reference objects for all the keys you want to work with. Here is an example:
$s = get-acl hklm:\software\test
gci hkcu:\software\dev -recurse -force | set-acl -aclobject $s
Here, gci is an alias for Get-ChildItem. You obtain the security descriptor for HKLM:\Software\Test. Next you get a reference to all subpaths of HKCU:\Software\Dev. Finally, you use the security descriptor on HKLM:\Software\Test to set the security descriptor for these subkeys.
Working with Registry Access Rules
To create your own security descriptors, you need to work with access control rules. The Access property of security objects is defined as a collection of authorization rules. With registry keys, these rules have the following object type:
System.Security.AccessControl.RegistryAccessRule
One way to view the individual access control objects that apply to a registry key is shown in this example and sample output:
$s = get-acl hklm:\software\test
$s.access
RegistryRights : FullControl
AccessControlType : Allow
IdentityReference : IMAGINEDLANDS\williams
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
RegistryRights : FullControl
AccessControlType : Allow
IdentityReference : NT AUTHORITY\SYSTEM
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
RegistryRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
RegistryRights : ReadKey
AccessControlType : Allow
IdentityReference : NT AUTHORITY\RESTRICTED
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
Here you get the RegistrySecurity object for the HKLM:\Software\Test key and then display the contents of its Access property. Although each value listed is an access rule object, you cannot work with each access rule object separately. Note the following in the output:
· RegistryRights Shows the registry rights being applied
· AccessControlType Shows the access control type as Allow or Deny
· IdentityReference Shows the user or group to which the rule applies
· IsInherited Specifies whether the access rule is inherited
· InheritanceFlags Shows the way inheritance is being applied
· PropagationFlags Specifies whether the access rule will be inherited
Another way to work with each access rule object separately is to use a ForEach loop as shown in this example:
$s = get-acl hklm:\software\test
foreach($a in $s.access) {
#work with each access control object
if ($a.identityreference -like "*administrator*") {$a | format-list *}
}
RegistryRights : FullControl
AccessControlType : Allow
IdentityReference : BUILTIN\Administrators
IsInherited : True
InheritanceFlags : ContainerInherit, ObjectInherit
PropagationFlags : None
Here, you examine each access rule object separately, which allows you to take action on specific access rules. In this example, you look for access rules that apply to administrators.
Configuring Registry Permissions
You can assign two types of access permissions to registry keys: basic and special. These permissions grant or deny access to users and groups.
The basic permissions you can assign to registry keys are shown in Table 6-3. The basic permissions are made up of multiple special permissions. Note the rule flag for each permission, because this is the value you must reference when creating an access rule.
TABLE 6-3 Basic Registry Permissions
PERMISSION |
DESCRIPTION |
RULE FLAG |
Full Control |
This permission permits reading, writing, changing, and deleting registry keys and values. |
FullControl |
Read |
This permission permits reading registry keys and their values. |
ReadKey, ExecuteKey |
Write |
This permission permits reading and writing registry keys and their values. |
WriteKey |
When you are configuring basic permissions for users and groups, you can specify the access control type as either Allowed or Denied. If a user or group should be granted an access permission, you allow the permission. If a user or group should be denied an access permission, you deny the permission.
You configure basic permissions for resources using access rules. Access rules contain collections of arrays that define:
· The user or group to which the rule applies.
· The access permission that applies.
· The Allow or Deny status.
This means regardless of whether you are adding or modifying rules, the basic syntax for an individual access rule is
"UserOrGroupName", "ApplicablePermission", "ControlType"
where UserOrGroupName is the name of the user or group to which the access rule applies, ApplicablePermission is the basic permission you are applying, and ControlType specifies the Allow or Deny status. User and group names are specified in COMPUTER\Name or DOMAIN\Name format. In the following example, you grant full control to DeploymentTesters:
"DeploymentTesters", "FullControl", "Allow"
The expanded syntax for an access rule is
"UserOrGroupName", "ApplicablePermission", "InheritanceFlag", "PropagationFlag", "ControlType"
where UserOrGroupName is the name of the user or group to which the access rule applies, ApplicablePermission is the basic permission you are applying, InheritanceFlag controls inheritance, PropagationFlag controls propagation of inherited rules, and ControlType specifies the type of access control. In the following example, you grant full control to DeploymentTesters and apply inheritance to the key and all its subkeys:
"DeploymentTesters", "FullControl", "ContainerInherit", "None", "Allow"
With the inheritance flag, you can specify one of the following flag values:
· None The access rule is not inherited by subkeys of the current key.
· ContainerInherit The access rule is inherited by child container objects.
· ObjectInherit The access rule is inherited by child leaf objects.
Because all registry keys are containers, the only inheritance flag that is meaningful for registry keys is the ContainerInherit flag for InheritanceFlags. If this flag is not used, the propagation flags are ignored, and only the key you are working with is affected. If you use the ContainerInherit flag, the rule is propagated according to the propagation flags.
With the propagation flag, you can specify the following flag values:
· None The access rule is propagated without modification. This means the rule applies to subkeys, subkeys with child keys, and subkeys of child keys.
· InheritOnly The access rule is propagated to container and leaf child objects. This means the rule applies to subkeys with child keys and subkeys of child keys; the rule does not apply to subkeys of the key.
· NoPropagateInherit The access rule applies to its child objects. This means the rule applies to subkeys of the key and subkeys with child keys but not to subkeys of child keys.
· NoPropagateInherit, InheritOnly The access rule applies to containers. This means the rule applies to subkeys with child keys but not to subkeys of child keys or to subkeys of the key.
You add access rules to a resource using either the SetAccessRule() method or the AddAccessRule() method of the access control object. You remove access rules from a resource using the RemoveAccessRule() method of the access control object. As discussed previously, access rules are defined as having the System.Security.AccessControl.RegistryAccessRule type.
The easiest way to add and remove access rules is to follow these steps:
1. Get an access control object. This object can be the one that applies to the registry key you want to work with or one that applies to a registry key that has the closest access control permissions to those you want to use.
2. Create one or more instances of the System.Security.AccessControl.RegistryAccessRule type, and store the desired permissions in these object instances.
3. Call AddAccessRule() or RemoveAccessRule() to add or remove access rules as necessary. These methods operate on the access control object you retrieved in the first step.
4. To apply the changes you’ve made to an actual registry key, you must apply the access control object to a specified resource.
Consider the following example:
set-alias no new-object
$acl = get-acl hklm:\software\test
$perm = "imaginedlands\deploymenttesters","fullcontrol","allow"
$r = no system.security.accesscontrol.registryaccessrule $perm
$acl.addaccessrule($r)
$acl | set-acl hkcu:\software\dev
Here, you get the access control object on HKLM:\Software\Test. You store the values for an access rule in a variable called $perm and then create a new instance of the RegistryAccessRule type for this access rule. To add the permission to the access control object you retrieved previously, you call its AddAccessRule() method. Although you could have created additional permissions and added or removed these, you didn’t in this example. Finally, you applied the access control object to a specific resource using Set-Acl.
You can easily extend the previous examples to apply to multiple registry keys as shown in the following example:
set-alias no new-object
$acl = get-acl hklm:\software\test
$perm = "imaginedlands\devtesters","fullcontrol","allow"
$r = no system.security.accesscontrol.registryaccessrule $perm
$acl.addaccessrule($r)
$resc = gci hkcu:\software\test -force
foreach($f in $resc) {
write-host $f.pspath
$acl | set-acl $f.pspath
}
Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software\test\Dt\IO
Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software\test\Queue
Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software\test\Stats
Here, you apply an access control list with a modified permission set to every subkey of HKCU:\Software\Test. In the output, you list the names of the keys you’ve modified. This helps you keep track of the changes.
The special permissions you can assign to registry keys are shown in Table 6-4. As with basic permissions, note the rule flag for each permission, because this is the value you must reference when creating an access rule.
TABLE 6-4 Special Permissions
PERMISSION |
DESCRIPTION |
RULE FLAG |
Query Values |
Allows the user or group to read the values within a key. |
QueryValues |
Set Value |
Allows the user or group to set the values within a key. |
SetValue |
Create Subkey |
Allows the user or group to create subkeys under the selected key. |
CreateSubKey |
Enumerate Subkeys |
Allows the user or group to list the subkeys under a key. |
EnumerateSubKeys |
Notify |
Allows the user or group to get notifications for changes that occur in a key. |
Notify |
Create Link |
Allows the user or group to create links from one key to another key. |
CreateLink |
Delete |
Allows the user or group to delete the key, subkeys, and values associated with the key. Delete permission must apply on the key and on all the key’s subkeys in order for a user or group to delete a registry key. |
Delete |
Write DAC |
Allows the user or group to change the key’s security permissions. |
ChangePermissions |
Take Ownership |
Allows the user or group to modify ownership of a key. |
TakeOwnership |
Read Control |
Allows the user or group to read the key’s security permissions. |
ReadPermissions |
Table 6-5 shows how special permissions are combined to make the basic permissions for registry keys.
TABLE 6-5 Combining Special Permissions
PERMISSION |
FULL CONTROL |
READ |
WRITE |
Query Values |
X |
X |
|
Set Value |
X |
X |
|
Create Subkey |
X |
X |
|
Enumerate Subkeys |
X |
X |
|
Notify |
X |
X |
|
Create Link |
X |
||
Delete |
X |
||
Write DAC |
X |
||
Write Owner |
X |
||
Read Control |
X |
X |
X |
You configure special permissions for registry keys in the same way as basic permissions. You add access rules to a resource using either the SetAccessRule() method or the AddAccessRule() method of the access control object. You remove access rules from a resource using the RemoveAccessRule() method of the access control object.
Consider the following example:
set-alias no new-object
$acl = get-acl hklm:\software\test
$p1 = "imaginedlands\dev","queryvalues","allow"
$r1 = no system.security.accesscontrol.registryaccessrule $p1
$acl.addaccessrule($r1)
$p2 = "imaginedlands\dev","enumeratesubkeys","allow"
$r2 = no system.security.accesscontrol.registryaccessrule $p2
$acl.addaccessrule($r2)
$acl | set-acl hklm:\software\test
Here, you get the access control object on the HKLM:\Software\Test key. This key must exist for the example to work. After you define an access rule and store the related values in $p1, you create a new instance of the RegistryAccessRule type and add the permission to the access control object by calling the AddAccessRule() method. After you define a second access rule and store the related values in $p2, you create a new instance of the RegistryAccessRule type and add the permission to the access control object by calling the AddAccessRule() method. Finally, you apply the access control object to a specific resource.
Taking Ownership of Registry Keys
You can take ownership using a registry key using the SetOwner() method of the access control object. The easiest way to take ownership is to complete the following steps:
1. Get an access control object for the registry you want to work with.
2. Get the IdentityReference for the user or group that will take ownership. This user or group must already have permission on the registry key.
3. Call SetOwner to specify that you want the user or group to be the owner.
4. Apply the changes you’ve made to the registry key.
Consider the following example:
$acl = get-acl hklm:\software\test
$found = $false
foreach($rule in $acl.access) {
if ($rule.identityreference -like "*administrators*") {
$global:ref = $rule.identityreference; $found = $true; break}
}
if ($found) {
$acl.setowner($ref)
$acl | set-acl hklm:\software\test
}
Here, you get the access control object on HKLM:\Software\Test. You then examine each access rule on this object, looking for the one that applies to the group you want to work with. If you find a match, you set $ref to the IdentityReference for this group, change $found to $true, and then break out of the ForEach loop. After you break out of the loop, you check to see if $found is True. If it is, you set the ownership permission on the access control object you retrieved previously and then apply the access control object to HKLM:\Software\Test using Set-Acl.
Auditing the Registry
Access to the registry can be audited, as can access to other areas of the operating system. Auditing allows you to track which users access the registry and what they’re doing. All the permissions listed previously in Tables 6-1 and 6-2 can be audited. However, you usually limit what you audit to only the essentials to reduce the amount of data that is written to the security logs and to reduce the resources used to track registry usage.
Before you can enable auditing of the registry, you must enable the auditing function on the computer you are working with. You can do this either through the server’s local policy or through the appropriate Group Policy object. The policy that controls auditing is Computer Configuration\Windows Settings\Security Settings\Local Policies\Audit Policy.
After auditing is enabled for a computer, you can configure how you want auditing to work for the registry. This means configuring auditing for each key you want to track. Thanks to inheritance, this doesn’t mean you have to go through every key in the registry and enable auditing for it. Instead, you can select a root key or any subkey to designate the start of the branch for which you want to track access, and then ensure the auditing settings are inherited for all subkeys below it. (Inheritance is the default setting.)
You can set auditing policies for registry keys using auditing rules. Auditing rules contain collections of arrays that define the following:
· The user or group to which the rule applies
· The permission usage that is audited
· The inheritance flag specifying whether the audit rule applies to subkeys of the current key
· The propagation flag specifying how an inherited audit rule is propagated to subkeys of the current key
· The type of auditing
This means regardless of whether you are adding or modifying rules, the basic syntax for an individual audit rule is
"UserOrGroupName", "PermissionAudited", "InheritanceFlag", "PropagationFlag", "AuditType"
where UserOrGroupName is the name of the user or group to which the audit rule applies, PermissionAudited is the basic or special permission you are tracking,
InheritanceFlag controls inheritance, PropagationFlag controls propagation of inherited rules, and AuditType specifies the type of auditing.
With the inheritance flag, you can specify one of the following flag values:
· None The audit rule is not inherited by subkeys of the current key.
· ContainerInherit The audit rule is inherited by child container objects.
· ObjectInherit The audit rule is inherited by child leaf objects.
Because all registry keys are containers, the only inheritance flag that is meaningful for registry keys is the ContainerInherit flag for InheritanceFlags. If this flag is not used, the propagation flags are ignored, and only the key you are working with is affected. If you use the ContainerInherit flag, the rule is propagated according to the propagation flags.
With the propagation flag, you can specify the following flag values:
· None The audit rule is propagated without modification. This means the rule applies to subkeys, subkeys with child keys, and subkeys of child keys.
· InheritOnly The audit rule is propagated to container and leaf child objects. This means the rule applies to subkeys with child keys and subkeys of child keys; the rule does not apply to subkeys of the key.
· NoPropagateInherit The audit rule applies to its child objects. This means the rule applies to subkeys of the key and subkeys with child keys but not to subkeys of child keys.
· NoPropagateInherit, InheritOnly The audit rule applies to containers. This means the rule applies to subkeys with child keys but not to subkeys of child keys or to subkeys of the key.
With audit type, use Success to track successful use of a specified permission, Failure to track failed use of a specified permission, and None to turn off auditing of the specified permission. Use Both to track success and failure.
As with security permissions, user and group names are specified in COMPUTER
\Name or DOMAIN\Name format. In the following example, you track users in the IMAGINEDLANDS domain who are trying to query key values but fail to do so because they don’t have sufficient access permissions:
"IMAGINEDLANDS\USERS", "QueryValues", "ContainerInherit", "None", "Failure"
You add audit rules to a resource using either the SetAuditRule() method or the AddAuditRule() method of the access control object. You remove audit rules from a resource using the RemoveAuditRule() method of the access control object. Audit rules are defined as having the System.Security.AuditControl.RegistryAuditRule type.
The easiest way to add and remove audit rules is to complete these steps:
1. Get an access control object. This object can be the one that applies to the registry key you want to work with or one that applies to a registry key that has the closest audit control permissions to those you want to use.
2. Create one or more instances of the System.Security.AuditControl
.RegistryAuditRule type, and store the desired auditing settings in these object instances.
3. Call AddAuditRule() or RemoveAuditRule() to add or remove audit rules as necessary. These methods operate on the access control object you retrieved in the first step.
4. Apply the changes you’ve made to an actual resource.
Consider the following example:
set-alias no new-object
$acl = get-acl hklm:\software\test
$audit = "imaginedlands\users","queryvalues","containerinherit",
"none","failure"
$r = no system.security.accesscontrol.registryauditrule $audit
$acl.addauditrule($r)
$acl | set-acl hklm:\software\test
Here, you get the access control object on HKLM:\Software\Test. You store the values for an audit rule in a variable called $audit, and then you create a new instance of the RegistryAuditRule type with this auditing rule. To add the auditing setting to the access control object you retrieved previously, you call its AddAuditRule() method. Although you could have created additional auditing rules and added or removed these, you didn’t in this example. Finally, you applied the access control object to a registry key using Set-Acl.
You can easily extend the previous examples to apply to multiple registry keys as shown in the following example:
set-alias no new-object
$acl = get-acl hklm:\software\test
$audit = "imaginedlands\users","queryvalues","containerinherit",
"none","failure"
$r = no system.security.accesscontrol.registryauditrule $audit
$acl.addauditrule($r)
$resc = gci hkcu:\software\test -recurse -force
foreach($f in $resc) {
write-host $f.pspath
$acl | set-acl $f.pspath
}
Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software\test\Dt\IO
Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software\test\Queue
Microsoft.PowerShell.Core\Registry:
:HKEY_CURRENT_USER\software\test\Stats
Here, you apply an auditing rule to every subkey of HKCU:\Software\Test. In the output, you list the names of the registry keys you’ve modified. This helps you keep track of the changes.