注册表值类型

PowerShell注册表(五)注册表权限 1


PowerShell管理注册表之系列文章:

  1. 操作注册表的几条重要命令
  2. “提供程序”文件系统以外的位置
  3. 搜索注册表
  4. 创建和删除键值
  5. 注册表权限

在第十五章,我们详细的学习了怎样使用PowerShell来控制文件和文件夹的权限。同样的机制也可以在注册表中使用,使用Get-Acl查看键的当前权限:

PS> md HKCU:\Software\Testkey


    Hive: HKEY_CURRENT_USER\Software


Name                           Property
----                           --------
Testkey
PS> Get-Acl HKCU:\Software\Testkey

Path                                    Owner   Access
----                                    -----   ------
Microsoft.PowerShell.Core\Registry::... mosser  mosser Allow  FullControl...

因为注册表权限管理基本和文件系统的权限管理类似,所以你可能需要在给注册表键分配权限前再看看第15章,或者重温一下基础知识。注册表中所需的权限在.NET中的类和与文件系统稍微有点区别。此时需要使用的不再是FilesystemAccessRule,而是RegistryAccessRule,两者的根本区别在于可以设置不同的访问权限。在注册表访问规则(RegistryAccessRule)中,权限的枚举值并不和文件系统访问规则(FilesystemAccessRule)中的枚举值对应:

PS> [System.Enum]::GetNames([System.Security.AccessControl.RegistryRights]
QueryValues
SetValue
CreateSubKey
EnumerateSubKeys
Notify
CreateLink
Delete
ReadPermissions
WriteKey
ExecuteKey
ReadKey
ChangePermissions
TakeOwnership
FullControl

接管所有权

在尝试更改注册表的权限前,请先测试以确保你是该键的“所有者”。除非你是所有者,才能够撤销可能存在的错误。下面的示例会演示怎样接管一个注册表键(当然你还是得先有权限访问)的所有权。

$acl = Get-Acl HKCU:\Software\Testkey
$acl.Owner

mosser
$me = [System.Security.Principal.NTAccount]"$env:userdomain\$env:username"
$acl.SetOwner($me)

设置新的访问权限

下面的步骤会给这个键分配新的权限,让“所有人”组禁止更改此键。

$acl = Get-Acl HKCU:\Software\Testkey
$person = [System.Security.Principal.NTAccount]"Everyone"
$access = [System.Security.AccessControl.RegistryRights]"WriteKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Deny"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.AddAccessRule($rule)
Set-Acl HKCU:\Software\Testkey $acl

更改会立刻生效,当你尝试通过注册表编辑器或者在PowerShell中创建子键时,会得到错误信息:

md HKCU:\Software\Testkey\subkey

md : 不允许所请求的注册表访问权。
At line:1 char:34
+ param([string[]]$paths); New-Item <<<< -type directory -path $paths

小技巧:你可能会问,为什么连我自己都限制,我是管理员啊,我应当拥有完全的访问权啊。这是因为在访问权限中,“拒绝”的优先权比“允许”高。哪怕你是管理员,你也是人,既然所有人都被拒绝,你自然也会被拒绝,除非你不是人。

移除一条访问规则

给所有人的访问权限完全是在浪费时间,也经不起考验。怎样删除这条规则呢?你可以使用RemoveAccessRule()方法来移除特定的权限,还可以使用RemoveAccessRuleAll()方法来移除指定用户的在某条规则中的所有权限(包括授权和拒绝),ModifyAccessRule()方法更新已存在的规则,PurgeAccessRules(),异常特定用户的所有权限。

要移除刚才创建的规则,可以这样处理:

$acl = Get-Acl HKCU:\Software\Testkey
$person = [System.Security.Principal.NTAccount]"Everyone"
$access = [System.Security.AccessControl.RegistryRights]"WriteKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Deny"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.RemoveAccessRule($rule)
Set-Acl HKCU:\Software\Testkey $acl -force

但是这样移除自己的访问规则后,并不是期望的结果。因为你把自己锁在了门外,因为你不在有权去更新这个键,本来是可以更改自己的安全设置的。此时如果你接管了所有权后。还是可以纠正遇到的这个问题的。此类情况发生后,你可以打开注册表编辑器,定位到这个键,右键鼠标选择权限,打开安全设置对话框,手动删除“所有人”组。

重要:刚才已经看到了,把自己锁在门外有多容易。所以在操作“所有人”这个组时,一定要格外小心。如果可以,尽量不要给这个组分配“拒绝”规则,因为它通常可能引入超出你预期的恶劣影响。

控制子键的访问

下面的例子,使用“允许”规则,而非“拒绝”规则,可以让世界稍微变得美好一点。在下面的测试键中,只有管理员才能更改这个键的值,而其它闲杂人等,只能读取和创建子键。

md HKCU:\Software\Testkey2
$acl = Get-Acl HKCU:\Software\Testkey2
# 管理员无所不能:
$person = [System.Security.Principal.NTAccount]"Administrators"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.ResetAccessRule($rule)
# 所有人只能读取和创建子键:
$person = [System.Security.Principal.NTAccount]"Everyone"
$access = [System.Security.AccessControl.RegistryRights]"ReadKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.ResetAccessRule($rule)
Set-Acl HKCU:\Software\Testkey2 $acl

稍微注意下,这种情况下没有使用AddAccessRule()而是使用ResetAccessRule()添加规则。其结果导致删除了各个用户已存在的权限。尽管如此,结果仍旧不对,因为正常的用户还是可以创建子键和写值。

md hkcu:\software\Testkey2\Subkey
Hive: Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\software\Testkey2

SKC   VC  Name  Property
---   --  ----  --------
0     0  Subkey {}

Set-ItemProperty HKCU:\Software\Testkey2 Value1 "Here is text"

揭示继承权

查看键的当前权限,可以弄清为什么上面的设置没有如期生效:

PS> (Get-Acl HKCU:\Software\Testkey2).Access | Format-Table -wrap

     RegistryRights   AccessControlType IdentityReference           IsInherited    InheritanceFlags    PropagationFlags
     --------------   ----------------- -----------------           -----------    ----------------    ----------------
            ReadKey               Allow Everyone                          False                None                None
        FullControl               Allow BUILTIN\Administrat               False                None                None
                                        ors
        FullControl               Allow mosser                             True  ContainerInherit,                 None
                                                                                      ObjectInherit
        FullControl               Allow NT AUTHORITY\SYSTEM                True  ContainerInherit,                 None
                                                                                      ObjectInherit
        FullControl               Allow BUILTIN\Administrat                True  ContainerInherit,                 None
                                        ors                                           ObjectInherit
            ReadKey               Allow NT AUTHORITY\RESTRI                True  ContainerInherit,                 None
                                        CTED                                          ObjectInherit

该键包含的权限可不止我们设置的那两条规则,还有其它一些从父键中继承过来的阿猫阿狗规则。如果你想清理掉它们,可以使用SetAccessRuleProtection()方法。

$acl = Get-Acl HKCU:\Software\Testkey2
$acl.SetAccessRuleProtection($true, $false)
Set-Acl HKCU:\Software\Testkey2 $acl

现在再回过头来看看,该键的访问规则只有我们明确指定的两条规则,其它继承权限已不复存在。

PS> (Get-Acl HKCU:\Software\Testkey2).Access | Format-Table -wrap

     RegistryRights   AccessControlType IdentityReference           IsInherited    InheritanceFlags    PropagationFlags
     --------------   ----------------- -----------------           -----------    ----------------    ----------------
            ReadKey               Allow Everyone                          False                None                None
        FullControl               Allow BUILTIN\Administrat               False                None                None
                                        ors

此时再让普通用户尝试给该键添加子键或者设置值,应当会包错:Set-ItemProperty : 不允许所请求的注册表访问权。

控制你自己的继承权

继承权是一把双刃剑。你已经从父键中关闭了继承,但是你自己的继承权呢?使用管理员权限打开控制台,能让我们给上面受保护的测试键添加子键。

md HKCU:\Software\Testkey2\Subkey1
md HKCU:\Software\Testkey2\Subkey1\Subkey2

然后看看这些新创建的子键的权限:

PS> (Get-Acl HKCU:\Software\Testkey2\Subkey1\Subkey2).Access | Format-Table -wrap

     RegistryRights   AccessControlType IdentityReference           IsInherited    InheritanceFlags    PropagationFlags
     --------------   ----------------- -----------------           -----------    ----------------    ----------------
        FullControl               Allow NT AUTHORITY\SYSTEM               False                None                None
        FullControl               Allow BUILTIN\Administrat               False                None                None
                                        ors
CreateLink, ReadKey               Allow S-1-5-5-0-205634                  False                None                None

其结果是这些权限仍旧没有与你设置的权限对应起来。理由是:对于你的继承权你啥都没设置,如果你想把自己纯正的血统不折不扣的遗传给下一代,请更改设置:

del HKCU:\Software\Testkey2
md HKCU:\Software\Testkey2
$acl = Get-Acl HKCU:\Software\Testkey2
# Admins may do anything:
$person = [System.Security.Principal.NTAccount]"Administrators"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]`
"ObjectInherit,ContainerInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)

$acl.ResetAccessRule($rule)
# Everyone may only read and create subkeys:
$person = [System.Security.Principal.NTAccount]"Everyone"
$access = [System.Security.AccessControl.RegistryRights]"ReadKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]`
"ObjectInherit,ContainerInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.ResetAccessRule($rule)
Set-Acl HKCU:\Software\Testkey2 $acl

原文链接:Chapter 16. Managing Windows Registry

本文链接: https://www.pstips.net/permissions-in-the-registry.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注

一条评论 “PowerShell注册表(五)注册表权限