我被委托将我们域中的一些日常任务委托给一组没有Domain Admins
成员资格的技术人员。其中一项任务是创建新的基于域的 Dfs 根 (Server 2008 R2 Enterprise DC)。这就是我陷入困境的地方。
代码
这基本上只是尝试创建一个基于域的 Dfs 根,使用任意(列表中的第一个)域控制器作为第一个命名空间服务器:
$DfsnRootName="test"
$DCList = Get-ADDomainController -Filter * | ForEach-Object { ,$_.HostName }
New-DfsnRoot -Path "\\domain.contoso.com\$DfsnRootName" -TargetPath "\\$($DCList[0])\$dfsnRootName" `
-Description "Dfs-Root für $DfsnRootName" -EnableAccessBasedEnumeration $true -Type DomainV2
$DCList | ForEach-Object {
New-DfsnRootTarget -Path "\\domain.contoso.com\$DfsnRootName" `
-TargetPath "\\$_\$dfsnRootName" -State Online
}
错误
上述代码抛出异常,指出缺少对 CIM 资源的访问权限ROOT\Microsoft\Windows\DFSN\MSFT_DFSNamespace
。分类信息看起来像一个 WMI 路径:
New-DfsnRoot : Access to a CIM resource was not available to the client.
At line:1 char:1
+ New-DfsnRoot -Path "\\domain.contoso.com\$DfsnRootName" -TargetPath "\\$($DCList ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (MSFT_DFSNamespace:ROOT\Microsoft\...FT_DFSNamespace) [New-DfsnRoot], CimException
+ FullyQualifiedErrorId : MI RESULT 2,New-DfsnRoot
PS Z:\> $Error[0].CategoryInfo
Category : PermissionDenied
Activity : New-DfsnRoot
Reason : CimException
TargetName : MSFT_DFSNamespace
TargetType : ROOT\Microsoft\Windows\DFSN\MSFT_DFSNamespace
无助的解决办法:
这实际上只是向 AD 容器中添加了对所添加主体的“完全控制”ACE CN=Dfs-Configuration,CN=System
。
当我收到一条错误消息,指出使用服务控制管理器时缺少权限“添加 Dfs 根”向导中dfsmgmt.msc
,我用来sc sdset scmanager
操作 SDDL 字符串,添加具有“KA”(密钥访问)权限的相应组,类似于BUILTIN\Administrators
默认存在的 ACE。
这样,我可以使用“添加 Dfs 根”向导完成所有步骤,但根目录本身的创建仍然失败 - “无法添加命名空间服务器 \ADSRV0\Test。访问被拒绝”
哇喔?
答案1
适度管理(JEA)端点非常适合您的任务。设计 JEA 端点需要做出三个主要决定:
- 谁可以调用 JEA 端点?
- 呼叫者可以做什么?
- 谁将担任通话主持人?
PS 5.1 中的 PowerShell 端点从技术上来说不是 JEA 端点,但机制本质上是相同的。
获取 PSSession 配置
名称:microsoft.powershell PSVersion:5.1
StartupScript:
RunAsUser:
权限:NT AUTHORITY\INTERACTIVE AccessAllowed、BUILTIN\Administrators AccessAllowed、BUILTIN\Remote Management Users AccessAllowed
由此,权限组定义了谁可以调用。PowerShell 端点可以执行的操作没有限制,因此您拥有完整的语言能力。最后,如果 RunAsUser 为空 - 代码将以提供的用户或凭据身份运行。
在此基础上,查看Register-PSSessionConfiguration
, 和JEA 概述。
为了获得加分,请考虑使用群组管理服务帐户 (GMSA)作为解决方案的一部分,特别是作为呼叫者。
就你的情况而言: 您可以限制仅由有限权限用户调用该端点。
然后定义您希望他们使用的特定 cmdlet。这些命令可以内置,也可以从您指定的自定义模块中公开。将这些命令保留为您的任务专用,以避免使用复杂参数的特权提升攻击或公开过多可以利用以特权用户身份运行的低级命令。
您可以使用RunAsUser
域管理员或其他具有足够权限的帐户。
答案2
要创建全域 DFS 命名空间,执行此操作的帐户应在命名空间服务器上具有本地管理员权限,就ADSRV0
您而言就是这样。您的最后一条错误消息告诉我,就您而言并非如此。
答案3
为了给 Matthew Wetmore 的灵感添加一些实施细节,我们创建了一个根据我们的要求设置 Dfs 命名空间的函数,将其公开在 Powershell 模块中LT-DFSManagement
,并创建了一个在“虚拟帐户”(获取本地管理员权限)中运行的 Powershell 会话配置在域控制器上仅限于调用此功能,并可供技术人员安全组的成员访问。
我们使用的dfsutil
代码是在 Server 2008 R2 机器上运行的,其中德福森-cmdlet 不可用。请注意,代码正在使用一些全局变量,默认情况下这些变量不会在您的环境中定义,但对于正确执行代码至关重要。
Function Add-DfsNamespace() {
<#
.SYNOPSIS
Creates a new Dfs namespace
#>
Param(
# Name of the namespace to create
[string]$Name,
# name of the security group to delegate management permissions to
[string]$DelegationTo = "ACL-$Name-Dfs-management",
# list of the servers to set up as namespace servers
$NamespaceServerList = $global:DomainControllersList
)
$ErrorActionPreference = "Stop"
Try {
$DelegationIdentity = (Get-ADGroup $DelegationTo -Server $global:THKDomainControllerToUse).SID
} Catch {
Throw "Unable to set up delegation permissions for $DelegationTo: $_"
}
$NamespaceServerList | ForEach-Object {
Try {
$NamespaceServer = $_
Write-Debug "Create a directory for the namespace: \\$NamespaceServer\c$\DfsRoots\$Name"
New-Item -Type Directory "\\$NamespaceServer\c$\DfsRoots\$Name" | Out-Null
} Catch {
Write-Warning "Creation of \\$NamespaceServer\c$\DfsRoots\$Name failed: $_"
}
# Create a new share through WMI
$share = [wmiclass]"\\$_\root\CimV2:Win32_Share"
Write-Debug 'WMI call to create the share `"$Name`" on $_'
$result=$share.Create( "c:\DfsRoots\$Name", $Name, 0)
Switch ($result.returnValue) {
0 { Write-Debug "\\$_\$Name share created successfully" }
22 { Write-Warning "Share \\$_\$Name already present" }
default { Throw "Share creation failed, return value of Win32_Share.Create: $result.returnValue" }
}
}
Write-Verbose "Creating Domain Dfs namespace $Name on namespace servers $($NamespaceServerList -join "; ")"
dfsutil root addDom "\\$($NamespaceServerList[0])\$Name"
$NamespaceServerList | ForEach-Object {
If($_ -ne $NamespaceServerList[0]) {
dfsutil target add "\\$_\$Name"
}
}
Write-Debug "Enabling Access-Based Enumeration"
dfsutil property abde enable "\\$global:sADDomainFQDN\$Name"
Write-Debug "Granting delegation rights for Namespace $Name to $DelegatedTo"
$adsiDfsNamespace = $null
$adsiDfsNamespace = [adsi]"LDAP://$global:THKDomainControllerToUse/CN=$Name,CN=Dfs-Configuration,CN=System,$sADDomainDN"
# Query ADSI for the ACL of the namespace AD object until we get a response
$retries = 0
Do {
$namespaceACL = $adsiDfsNamespace.PSBase.ObjectSecurity
If ($namespaceACL) {
# here we've got the ACL, loop will end hereafter
} Else {
Write-Debug "Waiting another round ($retries/$ADSImaxRetries) as ADSI has not yet provided a security descriptor for $($adsiDfsNamespace)"
Start-Sleep 1
}
$retries+=1
} Until (($retries -gt $ADSImaxRetries) -or ($null -ne $namespaceACL))
Write-Debug "Creating a new ACE for $DelegationTo ($DelegationIdentity)"
# Construct a new Full Control ACE for $DelegationIdentity
$newAce =
New-Object System.DirectoryServices.ActiveDirectoryAccessRule(
$DelegationIdentity,
[System.DirectoryServices.ActiveDirectoryRights]::GenericAll,
[System.Security.AccessControl.AccessControlType]::Allow,
[System.DirectoryServices.ActiveDirectorySecurityInheritance]::All
)
Write-Verbose "Updating the ACL of the Namespace $Name"
$namespaceAcl.AddAccessRule($newAce)
$adsiDfsNamespace.PSBase.CommitChanges()
}
PSSessionConfiguration 文件定义此会话配置可用的安全组:
@{
'Author' = 'the-wabbit';
'RunAsVirtualAccount' = $true;
'GUID' = 'cfe0ea5f-9d19-406d-90aa-d26df4bc840f';
'TranscriptDirectory' = 'C:\ProgramData\JEAConfiguration\Transcripts';
'SchemaVersion' = '2.0.0.0';
'RoleDefinitions' = @{
'DOMAIN\ACL-DFS-Technicians-AD-JEA-Remoting' = @{
'RoleCapabilities' = 'AD-JEA-DFS' }
};
'SessionType' = 'RestrictedRemoteServer' }
并且AD-JEA-DFS
角色功能文件将端点限制为仅 Add-DfsNamespace 功能:
@{
GUID = 'b17b282d-a656-41c8-a7d4-cc6a1fbc17e4'
Author = 'the-wabbit'
CompanyName = 'Looney Tunes'
Copyright = '(c) 2017 the-wabbit. All rights reserved.'
ModulesToImport = 'LT-DFSManagement'
VisibleFunctions='Add-DfsNamespace'
}
最后注册配置使一切就绪:
Register-PSSessionConfiguration -Name "DFS" -Path "C:\ProgramData\JEAConfiguration\DFS.pssc"