Latest Stories
M1 Max MacBook Pro and External Display: When Productivity Becomes Frustration Social Media Limbo kamshin.com on hiatus Some thoughts on the new MacBook Pro Opportunities And Challenges With Personal Health Data – Looking at Garmin Data

kamshin

  • Home
  • All Posts
  • Categories
    • General
    • Tech Field Day
    • Storage
    • Nutanix
    • Certifications
    • Conferences
    • Worth reading
    • Design
    • Rants
    • Active Directory
  • Media & Press
  • Podcast
  • About me
    • About me
    • Where is Max?
    • Disclosure & Policies

Identifying nested group membership in Active Directory for audit reports and security access reviews

May 11, 2010

FacebookTwitter

Hello,

I'm back with an Active Directory / VBS article for a change. Many of those who work in a corporate environment may be challenged by business entities and folder/share/application owners to deliver a report of who has access to a folder/share/application.

In simple Active Directory implementations, group membership is granted directly to an user and therefore it is merely a matter of minutes for the administrator to log into the ADUC console through dsa.msc plugin (Active Directory Users and Computers) and export the contents of a security group through a few screenshots or by running a simple enumeration script.

In corporate environments, it is more than likely that you will encounter more sophisticated access rights delegation schemes due to the increased complexity of the firm (various business units, large filesystems, complexity of everyday management..). There's an extremely high chance that you will be facing an AGDLP-based permission schema. If you aren't familiar with AGDLP, I would recommend you to look up on google, but to make it short I will quote the relevant wikipedia article that states the following :

"AGDLP is the acronym used to describe the practice of taking Accounts (A) and placing them into Global Groups (G) often for organizational purposes, such as grouping all sales people together. Then the Global Group is placed inside or nested within the Domain Local Group (DL) which will be used on the NTFS or share Access Control List (ACL) to provide permission. So Accounts go into Global Groups, Global Groups go into Domain Local Groups and the permission is assigned to the Domain Local Group: AGDLP. The main thrust of this technique is to focus a single permission set on a single group at the ACL level (Read only, read/write, etc) and then populate that single group in Active Directory whenever and as often as the assigned permission is needed."

Basically, if you have AGDLP, this means that you have users into groups, these groups are into other groups, and so on. You can have several levels of nested membership until you actually get to the group that grants permission to an application, share or folder.

Having been confronted to this problem, and willing to spend as few time as possible on tedious, repetitive tasks, I started searching on the net, as it is well known that there is no point in reinventing the wheel. If found a script that I adapted for my own use. I would like to send million blessings to its author, however I haven't been able to find out who the creator was. Whoever you are, you deserve a million thanks and due credit for your work!

My adaptations to the existing script were as follows :

– specify a filename as parameter to automatize the processing. The files are plain text files containing the list of security groups to be scanned.

– branch instructions to generate the proper output string

– add functions to write the output to a CSV file

In practice …

Let's see a typical usage example. Say we work for ACME and have an application called GIZMO, whose access is granted through Active Directory membership. The GIZMO Application is accessed by people located in France, Germany and Sweden. There are therefore three AD groups granting access :

FR-APPS-GIZMO

DE-APPS-GIZMO

SE-APPS-GIZMO

I will create a file called GIZMO.grp with the following content :

FR-APPS-GIZMO

DE-APPS-GIZMO

SE-APPS-GIZMO

Then I will call the VBS script with GIZMO.grp as parameter :

nested gizmo.grp

this will start processing all the groups contained in the GIZMO.grp file, it will process all of the subgroups and will indicate the various membership levels, what group is part of which group and the output will be stored in the gizmo.csv file. It is recommended to run the VBS from the command line straight from the folder where you plan to store your VBS file and your various GRP files, the command line parameter (input file) being used as a variable to store the application name. If you launch it from explorer, you will have the full path instead of just GIZMO.

As you browse the CSV file, you will find some interesting details about the group nested memberships, for example :

FR-APPS-GIZMO

+++ FR-APPS-GIZMO-CONTRIBUTOR

+++FR-APPS-GIZMO-VIEWER

++++++BE-MARKETING-DEPT

++++++LU-MARKETING-DEPT

DE-APPS-GIZMO

+++ DE-APPS-GIZMO-ADMINS

++++++DE-COMMERCIAL-MGMT

+++ DE-APPS-GIZMO-CONTRIBUTOR

+++ DE-APPS-GIZMO-VIEWER

SE-APPS-GIZMO

+++ SE-APPS-GIZMO-CONTRIBUTOR

+++SE-APPS-GIZMO-VIEWER

You will find out a more interesting and varied reality than what you had initially seen without an in-depth searching. Providing such a list to a business unit/application owner will allow them a full insight on who has access to their work, and will prevent both unnecessary info disclosure as well as conflicts of interest.

Feel free to try the script for yourself, on your own Active Directory structure. I am sure you will enjoy it! I have limited the script to 4 sub-levels, which currently suits my business needs. However it will take 5 minutes to any decent admin to adapt it to your needs.

Give me code!

Here is the script content below :

Option Explicit

Dim Iteration

Dim objGroup, InputFile, InputString, StrInheritedFrom, StrGroupName,

OutText

Dim oFSO, sFile, oFile, wFSO, wsFile, woFile

Dim Level2,Level3,Level4

If wscript.arguments.count <> 1 Then

wscript.echo "NO FILENAME PASSED"

wscript.echo "Usage: nested <filename.grp>"

wscript.quit

End If

Iteration = 0

Set oFSO = CreateObject("Scripting.FileSystemObject")

sFile = wscript.Arguments(0)

If oFSO.FileExists(sFile) Then

Set oFile = oFSO.OpenTextFile(sFile, 1)

OutText = Left(sFile,Len(sFile)-4)

Set wFSO = CreateObject("Scripting.FileSystemObject")

wsFile = OutText & ".csv"

Set woFile = oFSO.CreateTextFile(wsFile, true)

woFile.WriteLine "Application,Username,LogonName,Primary Group,Level 2

Group, Level 3 Group, Level 4 Group"

Do While Not oFile.AtEndOfStream

InputString = oFile.Readline

enumMembers getGroup(InputString), ""

Iteration=1

Loop

End If

Function getGroup(strGroupName)

Dim objConn, objRecSet, strQueryString, objRootDSE, strQueryFrom

Const adsOpenStatic = 3

Set objRootDSE = GetObject("LDAP://RootDSE")

strQueryFrom = "LDAP://" & objRootDSE.get("defaultNamingContext")

Set objConn = wscript.CreateObject("ADODB.Connection")

objConn.Provider = "ADsDSOObject"

objConn.Open

strQueryString = "SELECT AdsPath FROM '" & strQueryFrom & "' " & "WHERE

sAMAccountName = '" & strGroupName & "'"

Set objRecSet = wscript.CreateObject("ADODB.Recordset")

objRecSet.Open strQueryString, objConn, adsOpenStatic

If objRecSet.recordCount = 1 Then

Set getGroup = GetObject(objRecSet("AdsPath"))

End If

End Function

Sub enumMembers(byRef objGroup, strInheritedFrom)

Dim objMember,strRecord,SubscanDepth

SubScanDepth = 0

For Each objMember In objGroup.Members

If lcase(objMember.class) = "group" Then

Select Case Iteration

Case 2

Level2=objMember.CN

Case 3

Level3=objMember.CN

Case 4

Level4=objMember.CN

Case Else

End Select

enumMembers objMember,

objMember.samAccountName

Else

If objMember.displayname <> "" Then

If strInheritedFrom <> "" Then

SubscanDepth = 1

End If

If Level2 <> "" Then

SubscanDepth = 2

End If

If Level3 <> "" Then

SubscanDepth = 3

End If

If Level4 <> "" Then

SubscanDepth = 4

End If

Select Case SubscanDepth

Case 4

strRecord=OutText &","&

objMember.displayname &","& objMember.samAccountName &","& InputString

&","& strInheritedFrom &","& Level2 &","& Level3 &","& Level4

Case 3

strRecord=OutText &","&

objMember.displayname &","& objMember.samAccountName &","& InputString

&","& strInheritedFrom &","& Level2 &","& Level3

Case 2

strRecord=OutText &","&

objMember.displayname &","& objMember.samAccountName &","& InputString

&","& strInheritedFrom &","& Level2

Case 1

strRecord=OutText &","&

objMember.displayname &","& objMember.samAccountName &","& InputString

&","& strInheritedFrom

Case Else

strRecord=OutText &","&

objMember.displayname &","& objMember.samAccountName &","& InputString

End Select

End If

End If

If strRecord <> "" Then

woFile.WriteLine strRecord

End If

Iteration=Iteration+1

Next

End Sub

Hints for the lazy ones

Because I am lazy efficient, I like to automatize things. I have also made a batch file that runs all the grp files in the folder then concatenates the various csv files. Just make a bat file with the various command lines and a COPY concatenation of the CSV output files e.g. :

nested GROUP1.grp

nested GROUP2.grp
nested GROUP3.grp
..
nested GROUP20.grp
COPY GROUP1.csv+GROUP2.csv+GROUP3.csv+...+GROUP20.csv AccessReview.csv

This will give you a full CSV file almost ready to work with.

I have a bulk version of nested, nestedblk.vbs, that removes the woFile.WriteLine "Application,Username,LogonName,Primary Group,Level 2 Group, Level 3 Group, Level 4 Group" line.

I use the nested for the first batch command, then nestedblk for all the others, so that I don't have to remove the headers when concatenating all the CSV files.

Anyways, I hope this article wasn't boring, although it was long, painful and verbose!

Take care and see you soon for another article!

Share this:

  • Click to share on Facebook (Opens in new window)
  • Click to share on LinkedIn (Opens in new window)
  • Click to share on Twitter (Opens in new window)
  • Click to share on Reddit (Opens in new window)

Related

A note to our readers

kamshin.com has a strict no advertisement policy. If you enjoy this website, please consider making a donation to one of these non-profit organizations that I personally support:


People in Need - Czech Republic

A Czech-based non-governmental, non-profit organization founded on the ideals of humanism, freedom, equality and solidarity, helping people in the Czech Republic and in the entire world.

People In Need Logo

Greenpeace

Hopefully this one doesn't requires any explanation. Act for our planet. Act now.

Greenpeace Logo

826 National

US-based charity. An international proof point for writing as a tool for young people to ignite and channel their creativity, explore identity, advocate for themselves and their community, and achieve academic and professional success.

826 National Logo

 


Electronic Frontier Foundation

The leading nonprofit defending digital privacy, free speech, and innovation.

EFF Logo

 


Thank you!

RSS Latest Podcast Episodes

  • EP 30 -Rose Ross Chief Tech Trailblazer on the Tech Trailblazer awards
  • EP29 – Imagine the possibilities to manage your data with Data Dynamics StorageX – with Piyush Mehta
  • EP28 – Introducing Clumio, A Cloud-Based Data Platform Launching With Data Protection As A Service – with Poojan Kumar
  • EP27 – VAST Data – A Revolutionary Storage Platform For The Next Decade – with Howard Marks

Categories

  • Active Directory (5)
  • Certifications (8)
  • Conferences (22)
  • Design (1)
  • Featured (1)
  • General (89)
  • Nutanix (4)
  • Rants (2)
  • Storage (38)
  • Tech Field Day (44)
  • Worth reading (4)

Latest Tweets

My Tweets

Popular posts this week

  • Using Virtual Machine custom attributes with PowerCLI for snapshotting
  • My move from Gmail to ProtonMail: a comprehensive report on gaining back my privacy
  • Is the 16-Inch MacBook Pro Crippled By Thermal Issues?

Categories

  • Active Directory
  • Certifications
  • Conferences
  • Design
  • Featured
  • General
  • Nutanix
  • Rants
  • Storage
  • Tech Field Day
  • Worth reading

Pages

  • Blog
  • Disclosure & Policies
  • Home
  • Media & Press
  • VCAP5-DCD Resources
  • VCP5 Certification Resources
  • About me

Archives

Copyright ©2016 kamshin