Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get-ADComputer doesn't return nTSecurityDescriptor content #21540

Closed
5 tasks done
PhidarkMM opened this issue Apr 26, 2024 · 4 comments
Closed
5 tasks done

Get-ADComputer doesn't return nTSecurityDescriptor content #21540

PhidarkMM opened this issue Apr 26, 2024 · 4 comments

Comments

@PhidarkMM
Copy link

Prerequisites

Steps to reproduce

PS > pwsh
PowerShell 7.4.2
PS > import-module activedirectory
PS > get-module
ModuleType Version PreRelease Name ExportedCommands


Manifest 1.0.1.0 activedirectory {Add-ADCentralAccessPolicyMember, Add-ADComputerS…
Script 2.3.5 PSReadLine {Get-PSReadLineKeyHandler, Get-PSReadLineOption, …
PS > (Get-ADComputer -Filter * -Properties nTSecurityDescriptor).nTSecurityDescriptor |fl
Path :
Owner :
Group :
Access :
Audit :
Sddl :

Path :
Owner :
Group :
Access :
Audit :
Sddl :
...

Expected behavior

PS > powershell
PS > $($PSVersionTable.PSVersion)
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      20348  2400
> import-module activedirectory
PS > get-module
ModuleType Version    Name                                ExportedCommands
---------- -------    ----                                ----------------
Manifest   1.0.1.0    activedirectory                     {Add-ADCentralAccessPolicyMember, Add-ADComputerServiceAcc...
Script     2.0.0      PSReadline                          {Get-PSReadLineKeyHandler, Get-PSReadLineOption, Remove-PS...
PS > (Get-ADComputer -Filter * -Properties nTSecurityDescriptor).nTSecurityDescriptor |fl
Path   :
Owner  : MESSAGERIE\Admins du domaine
Group  : MESSAGERIE\Admins du domaine
Access : NT AUTHORITY\SELF Allow
         NT AUTHORITY\Authenticated Users Allow
         ...
Audit  :
Sddl   : O:DAG:DAD:AI(A;;CCDC;;;PS)(A;;LCRPLORC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO
...

Actual behavior

No content returned

Error details

PS > Get-Error
PS >

Environment data

PS > $PSVersionTable

Name                           Value
----                           -----
PSVersion                      7.4.2
PSEdition                      Core
GitCommitId                    7.4.2
OS                             Microsoft Windows 10.0.20348
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Visuals

No response

@PhidarkMM PhidarkMM added the Needs-Triage The issue is new and needs to be triaged by a work group. label Apr 26, 2024
@mklement0
Copy link
Contributor

The ActiveDirectory module isn't being maintained in this repo, so the standard advice applies (taken from the now obsolete PowerShellModuleCoverage repo, emphasis added):

NOTE To report problems with modules that ship in Windows, use the Windows Feedback Hub. For more information, see Send feedback to Microsoft with the Feedback Hub app.

@jborean93
Copy link
Collaborator

TLDR: Run Import-Module Microsoft.PowerShell.Security to ensure the ETS members for the ObjectSecurity type is loaded first.

I've had a look into this and it looks like there is an actual value there for nTSecurityDescriptor the default formatting for that type uses properties that are not set. These properties Path, Owner, and Access are all ETS properties added by the PowerShell type system but at the point in which you got this value the ETS metadata for that type has not been loaded and thus the format definition is shown as empty values.

For example we can see through Get-Member that it contains no ETS properties added by PowerShell like Path, Owner, Group, and Audit.

PS C:\Users\vagrant-domain> (Get-ADComputer -Identity $env:COMPUTERNAME -Properties nTSecurityDescriptor).nTSecurityDescriptor | Get-Member *

   TypeName: System.DirectoryServices.ActiveDirectorySecurity

Name                            MemberType Definition
----                            ---------- ----------
AccessRuleFactory               Method     System.Security.AccessControl.AccessRule AccessRuleFactory(System.Security.…
AddAccessRule                   Method     void AddAccessRule(System.DirectoryServices.ActiveDirectoryAccessRule rule)
AddAuditRule                    Method     void AddAuditRule(System.DirectoryServices.ActiveDirectoryAuditRule rule)
AuditRuleFactory                Method     System.Security.AccessControl.AuditRule AuditRuleFactory(System.Security.Pr…
Equals                          Method     bool Equals(System.Object obj)
GetAccessRules                  Method     System.Security.AccessControl.AuthorizationRuleCollection GetAccessRules(bo…
GetAuditRules                   Method     System.Security.AccessControl.AuthorizationRuleCollection GetAuditRules(boo…
GetGroup                        Method     System.Security.Principal.IdentityReference GetGroup(type targetType)
GetHashCode                     Method     int GetHashCode()
GetOwner                        Method     System.Security.Principal.IdentityReference GetOwner(type targetType)
GetSecurityDescriptorBinaryForm Method     byte[] GetSecurityDescriptorBinaryForm()
GetSecurityDescriptorSddlForm   Method     string GetSecurityDescriptorSddlForm(System.Security.AccessControl.AccessCo…
GetType                         Method     type GetType()
ModifyAccessRule                Method     bool ModifyAccessRule(System.Security.AccessControl.AccessControlModificati…
ModifyAuditRule                 Method     bool ModifyAuditRule(System.Security.AccessControl.AccessControlModificatio…
PurgeAccessRules                Method     void PurgeAccessRules(System.Security.Principal.IdentityReference identity)
PurgeAuditRules                 Method     void PurgeAuditRules(System.Security.Principal.IdentityReference identity)
RemoveAccess                    Method     void RemoveAccess(System.Security.Principal.IdentityReference identity, Sys…
RemoveAccessRule                Method     bool RemoveAccessRule(System.DirectoryServices.ActiveDirectoryAccessRule ru…
RemoveAccessRuleSpecific        Method     void RemoveAccessRuleSpecific(System.DirectoryServices.ActiveDirectoryAcces…
RemoveAudit                     Method     void RemoveAudit(System.Security.Principal.IdentityReference identity)
RemoveAuditRule                 Method     bool RemoveAuditRule(System.DirectoryServices.ActiveDirectoryAuditRule rule)
RemoveAuditRuleSpecific         Method     void RemoveAuditRuleSpecific(System.DirectoryServices.ActiveDirectoryAuditR…
ResetAccessRule                 Method     void ResetAccessRule(System.DirectoryServices.ActiveDirectoryAccessRule rul…
SetAccessRule                   Method     void SetAccessRule(System.DirectoryServices.ActiveDirectoryAccessRule rule)
SetAccessRuleProtection         Method     void SetAccessRuleProtection(bool isProtected, bool preserveInheritance)
SetAuditRule                    Method     void SetAuditRule(System.DirectoryServices.ActiveDirectoryAuditRule rule)
SetAuditRuleProtection          Method     void SetAuditRuleProtection(bool isProtected, bool preserveInheritance)
SetGroup                        Method     void SetGroup(System.Security.Principal.IdentityReference identity)
SetOwner                        Method     void SetOwner(System.Security.Principal.IdentityReference identity)
SetSecurityDescriptorBinaryForm Method     void SetSecurityDescriptorBinaryForm(byte[] binaryForm), void SetSecurityDe…
SetSecurityDescriptorSddlForm   Method     void SetSecurityDescriptorSddlForm(string sddlForm), void SetSecurityDescri…
ToString                        Method     string ToString()
AccessRightType                 Property   type AccessRightType {get;}
AccessRuleType                  Property   type AccessRuleType {get;}
AreAccessRulesCanonical         Property   bool AreAccessRulesCanonical {get;}
AreAccessRulesProtected         Property   bool AreAccessRulesProtected {get;}
AreAuditRulesCanonical          Property   bool AreAuditRulesCanonical {get;}
AreAuditRulesProtected          Property   bool AreAuditRulesProtected {get;}
AuditRuleType                   Property   type AuditRuleType {get;}

The ActiveDirectorySecurity type inherits from ObjectSecurity which is why the default format is to show those three properties:

Get-FormatData -TypeName System.Security.AccessControl.ObjectSecurity | Export-FormatData -Path ob.ps1xml
Get-Content ob.ps1xml
Remove-Item ob.ps1xml
<?xml version="1.0" encoding="utf-8"?>
<Configuration>
  <ViewDefinitions>
    <View>
      <Name>System.Security.AccessControl.ObjectSecurity</Name>
      <ViewSelectedBy>
        <TypeName>System.Security.AccessControl.ObjectSecurity</TypeName>
      </ViewSelectedBy>
      <TableControl>
        <TableHeaders>
          <TableColumnHeader />
          <TableColumnHeader />
          <TableColumnHeader>
            <Label>Access</Label>
          </TableColumnHeader>
        </TableHeaders>
        <TableRowEntries>
          <TableRowEntry>
            <TableColumnItems>
              <TableColumnItem>
                <PropertyName>Path</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>Owner</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>AccessToString</PropertyName>
              </TableColumnItem>
            </TableColumnItems>
          </TableRowEntry>
        </TableRowEntries>
      </TableControl>
    </View>
    <View>
      <Name>System.Security.AccessControl.ObjectSecurity</Name>
      <ViewSelectedBy>
        <TypeName>System.Security.AccessControl.ObjectSecurity</TypeName>
      </ViewSelectedBy>
      <ListControl>
        <ListEntries>
          <ListEntry>
            <ListItems>
              <ListItem>
                <PropertyName>Path</PropertyName>
              </ListItem>
              <ListItem>
                <PropertyName>Owner</PropertyName>
              </ListItem>
              <ListItem>
                <PropertyName>Group</PropertyName>
              </ListItem>
              <ListItem>
                <Label>Access</Label>
                <PropertyName>AccessToString</PropertyName>
              </ListItem>
              <ListItem>
                <Label>Audit</Label>
                <PropertyName>AuditToString</PropertyName>
              </ListItem>
              <ListItem>
                <PropertyName>Sddl</PropertyName>
              </ListItem>
            </ListItems>
          </ListEntry>
        </ListEntries>
      </ListControl>
    </View>
  </ViewDefinitions>
</Configuration>

The default format is a table format which the above format definition is retrieved through the Path, Owner, and Group definition which as the ETS properties aren't applied to the object won't be there and thus the object looks empty.

You can manually get these values through the normal .NET methods like $sd.GetOwner([System.Security.Principal.NTAccount]) and $sd.GetAccessRules($true, $true, [System.Security.Principal.NTAccount]).

Luckily the simpler solution is to import the module that contains the ETS definitions for the ObjectSecurity type which is included in the Microsoft.PowerShell.Security module:

(Get-ADComputer -Identity $env:COMPUTERNAME -Properties nTSecurityDescriptor).nTSecurityDescriptor

Path Owner Access
---- ----- ------

Import-Module Microsoft.PowerShell.Security

(Get-ADComputer -Identity $env:COMPUTERNAME -Properties nTSecurityDescriptor).nTSecurityDescriptor

Path Owner                Access
---- -----                ------
     DOMAIN\Domain Admins NT AUTHORITY\SELF Allow  …

The reason why this works automatically in WinPS is the ETS data had not been separated into it's own module so was already present when WinPS had started. Now with PS moving to separate modules for core subsystems the ETS members will only be defined when that module is also imported. Technically the fix for the ActiveDirectory module is to import Microsoft.PowerShell.Security as part of it's psm1 but as mklement0 says above that module is not maintained in this repo and needs to go through the feedback hub.

@PhidarkMM
Copy link
Author

Thx jborean93 it works perfectly

Copy link
Contributor

microsoft-github-policy-service bot commented May 6, 2024

📣 Hey @PhidarkMM, how did we do? We would love to hear your feedback with the link below! 🗣️

🔗 https://aka.ms/PSRepoFeedback

@microsoft-github-policy-service microsoft-github-policy-service bot removed the Needs-Triage The issue is new and needs to be triaged by a work group. label May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants