Getting an audit of your IT environment is incredibly useful. When you consider an audit from a security perspective – in the Windows NT domain or Active Directory model – there are a few items of significant importance: domains, users, groups, computers, and services.
The first step in conducting an audit is discovery – find out what’s out there. Fortunately, we have a great scripting tool for this: ADSI (Active Directory Services Interface). ADSI can pull the information for us, but to utilize it, we need to store it somewhere – such as in a SQL database.
To save you the trouble of figuring this out, below is a (rather long) script which uses ADSI to poll your network and store data into text files. To run it successfully, you must have at least query access to your entire directory. (The script has been tested on an NT 4.0 domain and on an Active Directory site.) The script queries each domain, obtaining all users, groups (including group memberships), and computers; and for each computer, obtains all local users, groups (and group memberships), and services. The output is saved into pipe-delimited text files for easy import into a database.
The script, which I save as netquery.vbs, has the following syntax:
cscript.exe netquery.vbs [nodomainusers] [nodomaingroups] [nocomputers] [nolocalusers] [nolocalgroups] [noservices] nodomainusers Suppresses querying of domain users and groups nodomaingroups Suppresses querying of domain groups nocomputers Suppresses querying of computers, local users and groups, and services nolocalusers Suppresses querying of local users and groups nolocalgroups Suppresses querying of local groups noservices Suppresses querying of services
The script generates text files in the current directory. Note that existing files will be overwritten! Each text file has a header as its first row. Import each text file into a database table with the exact same name. References between tables is logical if you look at the column names. Each object has an ADSPath
, which is unique. Objects may reference an ADSOwner
, which is the object’s parent (such as the domain or computer for which a user or group belongs, or the computer which a service is installed on). One special file exists – the groupmembers file. This has only two fields – ADSOwner
and ADSMember
– which are used to correlate the group (ADSOwner
) with its many members (ADSMember
).
Play around with it and it’ll make sense. If your network is huge, this will take a long time to run! You can tell things are working if data is being added to the output files.
And now, with no further delays, is the master script: netquery.vbs
!
Option Explicit On Error Resume Next Const ForWriting = 2 'ARGUMENTS Dim blnDomainUsers, blnDomainGroups, blnComputers, blnLocalUsers, blnLocalGroups, blnServices blnDomainUsers = True blnDomainGroups = True blnComputers = True blnLocalUsers = True blnLocalGroups = True blnServices = True For Each item In WScript.Arguments Select Case LCase(item) Case "nodomainusers" blnDomainUsers = False blnDomainGroups = False Case "nodomaingroups" blnDomainGroups = False Case "nocomputers" blnComputers = False blnLocalUsers = False blnLocalGroups = False blnServices = False Case "nolocalusers" blnLocalUsers = False blnLocalGroups = False Case "nolocalgroups" blnLocalGroups = False Case "noservices" blnServices = False End Select Next 'CREATE FILESYSTEMOBJECT Dim objFSO Set objFSO = CreateObject("Scripting.FileSystemObject") Dim objDomainsFile, objUsersFile, objGroupsFile, objGroupMembersFile, objComputersFile, objServicesFile Set objDomainsFile = objFSO.OpenTextFile("domains.txt", ForWriting, True) Set objUsersFile = objFSO.OpenTextFile("users.txt", ForWriting, True) Set objGroupsFile = objFSO.OpenTextFile("groups.txt", ForWriting, True) Set objGroupMembersFile = objFSO.OpenTextFile("groupmembers.txt", ForWriting, True) Set objComputersFile = objFSO.OpenTextFile("computers.txt", ForWriting, True) Set objServicesFile = objFSO.OpenTextFile("services.txt", ForWriting, True) objDomainsFile.WriteLine "adspath|name" objUsersFile.WriteLine "adspath|adsowner|name|fullname|description|passwordage|lastlogin|lastlogoff|raspermissions|accountdisabled" objGroupsFile.WriteLine "adspath|adsowner|name" objGroupMembersFile.WriteLine "adsowner|adsmember" objComputersFile.WriteLine "adspath|adsowner|name|passwordage|owner|division|operatingsystem|osversion|processor|processorcount" objServicesFile.WriteLine "adspath|adsowner|name|displayname|account" Dim objDomains, objDomain, objUsers, objUser, objGroups, objGroup Dim objComputers, objComputer, objComputerAccount, objServices, objService Dim s1, s2, s3, s4, s5, s6, s7, obj, cls, op, item Set objDomains = GetObject("WinNT:") For Each objDomain in objDomains objDomainsFile.Write objDomain.AdsPath objDomainsFile.Write "|" objDomainsFile.Write objDomain.Name objDomainsFile.WriteLine 'DOMAIN USERS If blnDomainUsers Then Set objUsers = Nothing Set objUser = Nothing Set objUsers = GetObject(objDomain.AdsPath) objUsers.Filter = Array("User") For Each objUser in objUsers objUsersFile.Write objUser.AdsPath objUsersFile.Write "|" objUsersFile.Write objDomain.AdsPath objUsersFile.Write "|" objUsersFile.Write objUser.Name objUsersFile.Write "|" objUsersFile.Write objUser.FullName objUsersFile.Write "|" objUsersFile.Write objUser.Description objUsersFile.Write "|" objUsersFile.Write objUser.PasswordAge objUsersFile.Write "|" objUsersFile.Write objUser.LastLogin objUsersFile.Write "|" objUsersFile.Write objUser.LastLogoff objUsersFile.Write "|" objUsersFile.Write objUser.RasPermissions objUsersFile.Write "|" If objUser.UserFlags And &H0002 Then objUsersFile.Write "1" Else objUsersFile.Write "0" End If objUsersFile.WriteLine Next End If 'DOMAIN GROUPS If blnDomainGroups Then Set objGroups = Nothing Set objGroup = Nothing Set objGroups = GetObject(objDomain.AdsPath) objGroups.Filter = Array("Group") For Each objGroup in objGroups objGroupsFile.Write objGroup.AdsPath objGroupsFile.Write "|" objGroupsFile.Write objDomain.AdsPath objGroupsFile.Write "|" objGroupsFile.Write objGroup.Name objGroupsFile.WriteLine For Each objUser In objGroup.Members If Right(objUser.Name, 1) <> "$" Then objGroupMembersFile.Write objGroup.AdsPath objGroupMembersFile.Write "|" objGroupMembersFile.Write objUser.AdsPath objGroupMembersFile.WriteLine End If Next Next End If 'COMPUTERS If blnComputers Then Set objComputers = Nothing Set objComputer = Nothing Set objComputers = GetObject(objDomain.AdsPath) objComputers.Filter = Array("Computer") For Each objComputer in objComputers Set objComputerAccount = GetObject(objComputer.AdsPath & "$,user") objComputersFile.Write objComputer.AdsPath objComputersFile.Write "|" objComputersFile.Write objDomain.AdsPath objComputersFile.Write "|" objComputersFile.Write objComputer.Name objComputersFile.Write "|" objComputersFile.Write objComputerAccount.PasswordAge objComputersFile.Write "|" objComputersFile.Write objComputer.Owner objComputersFile.Write "|" objComputersFile.Write objComputer.Division objComputersFile.Write "|" objComputersFile.Write objComputer.OperatingSystem objComputersFile.Write "|" objComputersFile.Write objComputer.OperatingSystemVersion objComputersFile.Write "|" objComputersFile.Write objComputer.Processor objComputersFile.Write "|" objComputersFile.Write objComputer.ProcessorCount objComputersFile.WriteLine 'COMPUTER USERS If blnLocalUsers Then Set objUsers = Nothing Set objUser = Nothing Set objUsers = GetObject(objComputer.AdsPath & ",computer") objUsers.Filter = Array("User") For Each objUser in objUsers objUsersFile.Write objUser.AdsPath objUsersFile.Write "|" objUsersFile.Write objComputer.AdsPath objUsersFile.Write "|" objUsersFile.Write objUser.Name objUsersFile.Write "|" objUsersFile.Write objUser.FullName objUsersFile.Write "|" objUsersFile.Write objUser.Description objUsersFile.Write "|" objUsersFile.Write objUser.PasswordAge objUsersFile.Write "|" objUsersFile.Write objUser.LastLogin objUsersFile.Write "|" objUsersFile.Write objUser.LastLogoff objUsersFile.Write "|" objUsersFile.Write objUser.RasPermissions objUsersFile.Write "|" If objUser.UserFlags And &H0002 Then objUsersFile.Write "1" Else objUsersFile.Write "0" End If objUsersFile.WriteLine Next End If 'COMPUTER GROUPS If blnLocalGroups Then Set objGroups = Nothing Set objGroup = Nothing Set objGroups = GetObject(objComputer.AdsPath & ",computer") objGroups.Filter = Array("Group") For Each objGroup in objGroups objGroupsFile.Write objGroup.AdsPath objGroupsFile.Write "|" objGroupsFile.Write objComputer.AdsPath objGroupsFile.Write "|" objGroupsFile.Write objGroup.Name objGroupsFile.WriteLine For Each objUser In objGroup.Members If Right(objUser.Name, 1) <> "$" Then objGroupMembersFile.Write objGroup.AdsPath objGroupMembersFile.Write "|" objGroupMembersFile.Write objUser.AdsPath objGroupMembersFile.WriteLine End If Next Next End If 'SERVICES If blnServices Then Set objServices = Nothing Set objService = Nothing Set objServices = GetObject(objComputer.AdsPath & ",computer") objServices.Filter = Array("Services") For Each objService In objServices objServicesFile.Write objService.AdsPath objServicesFile.Write "|" objServicesFile.Write objComputer.AdsPath objServicesFile.Write "|" objServicesFile.Write objService.Name objServicesFile.Write "|" objServicesFile.Write objService.DisplayName objServicesFile.Write "|" objServicesFile.Write objService.ServiceAccountName objServicesFile.WriteLine Next End If Next End If Next objServicesFile.Close objComputersFile.Close objGroupMembersFile.Close objGroupsFile.Close objUsersFile.Close objDomainsFile.Close Set objServicesFile = Nothing Set objComputersFile = Nothing Set objGroupMembersFile = Nothing Set objGroupsFile = Nothing Set objUsersFile = Nothing Set objDomainsFile = Nothing