7

I'm on a domain joined Windows 10 Computer and want to query the attributes of my own user account. Are there any built-in tools for that?

It is not an admin computer and I don't have RSAT installed. My computer does not seem to have:

  • dsget
  • dsquery
  • ldapsearch
  • ldp
  • PowerShell ActiveDirectory module

Are there any other tools built-in? I mean, there must be something, because at least my computer is able to query the AD, but are there tools that I can also use as a user?

3 Answers3

9

Windows has the ADSI interface available to programs, which supports general LDAP access.

PowerShell has access to ADSI via System.DirectoryServices types:

  • The [System.DirectoryServices.DirectoryEntry] type (aliased to [ADSI]) represents a specific entry – when given an LDAP object, its attributes directly correspond to the LDAP entry's attributes:

    $obj = [adsi] "LDAP://CN=foo,OU=bar,DC=example,DC=com"
    echo $obj.displayName
    $obj | fl *
    

    You don't need to specify a server – Windows will use the AD directory by default. (The LDAP:// part is case-sensitive; this is an ADSI binding string, not a URL.)

  • The [System.DirectoryServices.DirectorySearcher] type (aliased to [ADSISearcher]) represents an LDAP search query which can be used to find your user DN if you don't already know it:

    $qry = [adsisearcher] "(sAMAccountName=stackprotector)"
    $qry.FindAll().Path
    

    More verbose example copied from some-or-other MSDN docs page (in AD, searching for the anr pseudo-attribute is how GUI tools resolve names):

    $qry = New-Object DirectoryServices.DirectorySearcher
    $qry.Filter = '(&(objectCategory=person)(anr=Stack))'
    $qry.SearchRoot = 'LDAP://OU=Laptops,OU=Computers,DC=contoso,DC=com'
    $qry.FindAll()
    

But ADSI is originally a COM+ API that predates PowerShell and even .NET in general, so of course Microsoft has examples for using it from VBScript and from ADODB (and even from ASP, not that it helps here).


You should also be able to install and use some RSAT tools without needing any special privileges (aside from local Windows admin to do the installation). By default, the directory is wide open to any authenticated client.

You can use third-party LDAP clients with AD – the domain controllers will accept authentication using your user credentials, which is how most Windows GUI tools look up data in AD in the first place (with the machine join account being needed only for some tasks). However, it's best to use clients which support Kerberos authentication via GSSAPI or GSS-SPNEGO, as that's guaranteed to work with any AD setup. Tools which use NTLM or "simple bind" (password authentication) may or may not work depending on domain configuration.

For example, SysInternals ADExplorer comes from Microsoft and works without installation. (When prompted for server details, leave all fields blank and just click "Connect".)

(The RSAT tools "ADSIEdit" and "dsa.msc" can technically be used without a full installation, indeed even official Microsoft instructions used to say "extract these files from the .cab and regsvr32 them", but you do need Windows local admin access for the regsvr32 part.

grawity
  • 501,077
3

From user1686's excellent answer, I derived the following line to display the attributes of the currently logged on user account:

[adsi] ([adsisearcher] "(sAMAccountName=$env:USERNAME)").FindAll().Path | Format-List *

Further useful queries

  1. Get all members of a group (given by sAMAccountName):

    ([adsisearcher] "(&(objectClass=person)(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=$(([adsisearcher] "(sAMAccountName=REPLACE_ME)").FindOne().GetDirectoryEntry().distinguishedName)))").FindAll().GetDirectoryEntry() | Select-Object -ExpandProperty sAMAccountName | Sort-Object
    
  2. Get all groups of a user (given by sAMAccountName):

    ([adsisearcher] "(sAMAccountName=REPLACE_ME)").FindOne().GetDirectoryEntry().memberOf
    
  3. Check if a user (given by sAMAccountName) is a member of a group (given by sAMAccountName):

    ([adsisearcher] "(&(sAMAccountName=REPLACE_ME_WITH_USERNAME)(memberOf:1.2.840.113556.1.4.1941:=$(([adsisearcher] "(sAMAccountName=REPLACE_ME_WITH_GROUPNAME)").FindOne().GetDirectoryEntry().distinguishedName)))").FindAll().Count -gt 0
    
  4. Get the state of an account given by sAMAccountName:

    $as = [adsisearcher] "(sAMAccountName=REPLACE_ME)"
    $as.PropertiesToLoad.Add('msds-user-account-control-computed') | Out-Null
    $as.PropertiesToLoad.Add('pwdlastset') | Out-Null
    $account = $as.FindOne()
    $uac = $account.Properties['msds-user-account-control-computed'][0]
    $pwdLastSet = $account.Properties['pwdlastset'][0]
    [PSCustomObject]@{
        AccountDisabled  =      [bool] ($uac -band 2)
        AccountLockedOut =      [bool] ($uac -band 16)
        PasswordExpires  = -not [bool] ($uac -band 65536)
        PasswordExpired  =      [bool] ($uac -band 8388608)
        PasswordLastSet  = [DateTime]::FromFileTime($pwdLastSet)
    }
    

    Example output for a healthy active account:

    AccountDisabled  : False
    AccountLockedOut : False
    PasswordExpires  : True
    PasswordExpired  : False
    PasswordLastSet  : 23.07.2024 13:27:15
    
  5. Get all objects by a sAMAccountName pattern:

    ([adsisearcher] "(sAMAccountName=REPLACE_ME*)").FindAll().GetDirectoryEntry() | Select-Object -Property distinguishedName, sAMAccountName
    
0

net.exe with the /domain switch queries the AD:

REM Show account details, like password metadata and group memberships 
net user %USERNAME% /domain

REM Show members of a group net group "domain users" /domain

REM Show password policy net accounts /domain

REM List all usernames net user /domain

REM List all groups net group /domain

net config workstation net stats workstation

More info on parameters is available at ss64.com, output examples at René Nyffenegger's site and historic background on Wikipedia. The official docs of Microsoft are incomplete, switching between versions might help.

cachius
  • 859