Storing Sensitive Data in Active Directory

Introduction

Active Directory often acts as the primary data provider for connected systems and for this to be possible across a large amount of IT systems, a system-wide unique identifier for each identity is needed. Enter the Social Security Number (SSN) or CPR-Number in Denmark. This number is unique for each person, many systems already use it as the primary unique identifier, and it’s easy to work with. What’s not to like?

The problem

Well, it becomes a problem the day it is fed into Active Directory, without being careful. Per default, every authenticated (logged in) user, can read almost any attribute in Active Directory.

When confidential or sensitive data such as social security numbers or civil registration numbers are used by AD administrators without changing the default configurations, they are putting their users at risk of identity fraud. They are also putting the company at risk of violating data privacy regulations.

To demonstrate exactly what can be accessed as a regular user in Active Directory, the user “peha” who is only a member of the default group “Domain Users” is utilized:

Any LDAP browser will be sufficient, alternatively, PowerShell from a machine with Remote Server Administration Tools (RSAT) installed can be used to easily view the properties of a user or any other object in Active Directory. Below, the PowerShell RSAT cmdlets was chosen. The contents of all the attributes “peha” have permissions to read on a random user, “joda” is shown. Some of the interesting ones have been marked with red star (*):

As seen above, any authenticated user can access an awful lot of information about any given user. If we look solely at the problem of storing confidential or sensitive data in Active Directory, the attributes marked with a red star (*) are the ones that is seen misused most often. The attributes can be read by anyone, and especially the “EmployeeID” and “EmployeeNumber” are often used to store the social security number of the employee and some of the attributes even contain clear-text passwords for systems and service accounts.

Additionally, if the Active Directory currently has, or previously had an Exchange installation in the domain, the schema has been extended with “extentionAttibute1” to “extentionAttribute15” and can be read by everyone. These are often widely misused and contain information that should not be accessible to everyone.

Proposed solutions

Do not store it at all. Is the data still used? If not, consider removing it completely from Active Directory.

If it is required, such as social security numbers often are to be able to integrate with other systems, mark the attribute as “Confidential”. When an attribute is marked confidential, per default only members of the “Administrators” group can read it. You can and should however add specific access to read the attribute. Beware that some attributes cannot be marked as confidential. EmployeeID is an example of this. The attribute is a base schema attribute and can therefore not be marked as confidential. If the attribute required to be marked as confidential is a base schema attribute, the data must be moved to another non-base schema attribute, which in turn is marked as confidential.

To mark an attribute confidential and add read access to it, do the following:

1.   Make sure to know exactly what accounts require permission to read the attribute. Functionality might break if care is not taken

2.   Create a group in Active Directory that will be granted access to read the attribute:

3.   Add the accounts that require access to the attribute to the group:

4. Give the group permissions to read the attribute: On a Domain Controller, as a member of the “Administrators” group, open “Ldp.exe”. Click on “Connection” and click “Bind” and choose “Bind as currently logged on user”:

5. In the top bar, click on “View” then on “Tree”:

6.  On the windows that appears, leave the field empty and just click “OK”:

7. Inheriting the permissions from the top of the domain is preferred. Depending on where the permissions should inherit from, right click on that OU and choose “Advanced” and “Security Descriptor”:

8.   Click “OK” in the popup:

9. In the window that appears, click on “Add…” to the right of the DACL part:

10. In the window that appears, add the name of the group in the “Trustee” field. Make sure to add the domain shortname in front of the group name, in this case “TEST\”. Also, check the following:

  • ACE type: “Allow”

  • Access mask: “Read property” and “Control access”

  • ACE flags: “Inherit”

  • Object type: The name of the attribute

  • Inherit object type: The object type relevant for the attribute, in this case “User”

11.   Click “OK”.

12.   In the Security descriptor window, click “Update”:

13.   Permissions are now set for the attribute. Next, set the attribute as confidential.

14.   First, open “ADSI Edit” while being logged into the Domain Controller with the “Schema Master” role as a member of the “Schema Admins” group.

15.    Right click on “ADSI Edit” and click on “Connect to…”. Under “Select a well known Naming Context:” choose “Schema”. Click “OK”.

16.   In the list of attributes, locale the attribute to mark as confidential (in this case Employee-Number) and double-click on it.

17.    Change the searchFlags attribute to value “128” and click “OK”.

18.   It should now have the following value: “0x80 = (CONFIDENTIAL)”. Click “OK” again. The attribute is now marked as confidential.

19.   The permissions should take effect immediately.

20.   Test that a user who is a member of the group can read the attribute:

21. Test that a user who is not a member of the group cannot read the attribute: