Return to HomePage



Protect Data in the Registry Using Key Permissions (VB.NET)


Applies To

* .NET Framework 2.0
* VB.NET

Summary

The purpose of this code snippet is to illustrate how to secure data stored in the Windows registry through the use of registry access control list (ACL) permissions. By using these permissions, a user
can programmatically control who can and cannot access data stored in the registry.

Objectives

* Creating an applying a registry kep security context to control which users can access data from the registry


Solution Example

		    Sub [ControlledRegistryStore(ByVal] keyName As String, [ByVal] valueName As String, [ByVal] data As String)
		        ' Create a security context for a new key that we will use to store our data.
		        ' The security context will restrict access to only our user.
		        Dim user As String = [Environment.UserDomainName] + "\" + [Environment.UserName]
		        Dim security As New [RegistrySecurity()]
		        Dim rule As New [RegistryAccessRule(user,] [RegistryRights.FullControl,] [InheritanceFlags.ContainerInherit,] [PropagationFlags.None,] [AccessControlType.Allow)]
		        [security.AddAccessRule(rule)]
	

		        ' Actually create the new registry key and apply the security context we just came up with.
		        Dim key As [RegistryKey] = [Registry.CurrentUser.CreateSubKey(keyName,] [RegistryKeyPermissionCheck.ReadWriteSubTree,] security)
	

		        ' Write the data into the registry
		        [key.SetValue(valueName,] data)
		    End Sub
	


Problem Example

' Write an unprotected key and value into the registry. Default
' permissions allow all other users to access this key
Dim key As RegistryKey = Registry.CurrentUser.CreateSubKey(keyName)
key.SetValue(valueName, data)* Any other user on the system can access this key because no security
		  	context has been applied
	


Test Case

The following classes must be included in any project making use of the sample code provided above:

Imports System.Security
Imports System.Security.AccessControl
Imports Microsoft.Win32

Furthermore, two distinct users must be defined on the test system. These users will be referred to in the following example as User A and User B.

This test cases illustrates how a registry key secured using access control permissions by one user cannot be access by another user in the following 3 steps:

1) Store a key as "User A" (in this example, "User A" = Administrator) using the following code:

'Entry point which delegates to C-style main Private Function
Sub Main(args() As String)
		   		Dim keyName As String = "AdminSecuredKey"
		   		Dim valueName As String = "AdminSecuredValue"
	

		   		[ControlledRegistryStore(keyName,] valueName, "sensitive data")
	
End Sub

Sub ControlledRegistryStore(keyName As String, valueName As String, data As String)
		   		' Create a security context for a new key that we will use to store our data.
		   		' The security context will restrict access to only our user.
		   		Dim user As String = [Environment.UserDomainName] + "\" + [Environment.UserName]
		   		Dim security As New [RegistrySecurity()]
		   		Dim rule As New [RegistryAccessRule(user,] [RegistryRights.FullControl,] 		[InheritanceFlags.ContainerInherit,] [PropagationFlags.None,] [AccessControlType.Allow)]
		   [security.AddAccessRule(rule)]
	

		   		' Actually create the new registry key and apply the security context we just came up with.
		   		Dim key As [RegistryKey] = [Registry.CurrentUser.CreateSubKey(keyName,] [RegistryKeyPermissionCheck.ReadWriteSubTree,] security)
	

		   		' Write the data into the registry
		   		[key.SetValue(valueName,] data)
	
End Sub

2) Attempt to retrieve the previously stored key as User A using the following code:

Sub Main(args() As String)
		   		Dim keyName As String = "AdminSecuredKey"
		   		Dim valueName As String = "AdminSecuredValue"
	

		   		Dim data As String = [RegistryRetrieve(Registry.Users,] "\" + keyName, valueName)
		   		If Not (data Is Nothing) Then
		      			[Console.WriteLine(data)]
		   		Else
		      			Console.WriteLine("*** Inaccessible key ***")
		   		End If
	
End Sub

Function RegistryRetrieve(parent As RegistryKey, keyName As String, valueName As String) As String
		   		' Recursively search through each subkey of a parent key
		   		' checking to see if a match for the keyname exist and if
		   		' the data can be obtained from that key. Returns data upon
		   		' match and an error message otherwise. 
		   		Dim childName As String
		   		For Each childName In  [parent.GetSubKeyNames()]
		      			Try
		         			Dim child As [RegistryKey] = [parent.OpenSubKey(childName)]
		         			Dim data As String = Nothing
		         			If [child.Name.EndsWith(keyName)] Then
		            			' We found the name, try to pull out key data
		            			data = [child.GetValue(valueName)]
		         			Else
		            			' No luck finding the name, try a depth-first recursive search
		            			data = [RegistryRetrieve(child,] keyName, valueName)
		         			End If
		         			If Not (data Is Nothing) Then
		            			Return data
		         			End If
		      			Catch ex As Exception
		         			' Print out a message whenever we come across a 
		         			' key we don't have permissions to open
		         			[Console.WriteLine((childName] + ": " + ex.Message))
		      			End Try
		   		Next childName
	

		   		Return Nothing
	
End Function

3) Repeat Step 2 while logged in as User B. Compare results.


Expected Result

--------------------------------
"User A" (Administrator) output:
--------------------------------
C:\temp>whoami
vm-win2003\administrator

C:\temp>RegistrySnippet.exe
S-1-5-21-2537879503-2075122368-204042655-1006: Requested registry access is not
allowed.
sensitive data

---------------------------
"User B" (Joe User) output:
---------------------------
C:\temp>whoami
vm-win2003\joeuser

C:\temp>RegistrySnippet.exe
NetDDE: Requested registry access is not allowed.
S-1-5-19: Requested registry access is not allowed.
S-1-5-19_Classes: Requested registry access is not allowed.
S-1-5-20: Requested registry access is not allowed.
S-1-5-20_Classes: Requested registry access is not allowed.
S-1-5-21-2537879503-2075122368-204042655-1006: Requested registry access is not
allowed.
S-1-5-21-2537879503-2075122368-204042655-500: Requested registry access is not a
llowed.
S-1-5-21-2537879503-2075122368-204042655-500_Classes: Requested registry access
is not allowed.
NetDDE: Requested registry access is not allowed.
*** Inaccessible key ***


Scenarios

* Application comprised of multiple components that to access the same key material for secret encryption keys
* Application needs to store data configuration data to be retrieved on startup, such as database connection strings
* Application consists of a client tier that needs to store runtime credentials to connect to other application tiers


More Information

* Developers should not rely alone or registry permissions to control access to highly sensitive data. Consider encrypting certain data using the Data Protection API (DPAPI) in conjunction with registry access controls to add additional safeguards to more sensitive data stored in the registry. See Additional Resources section for links to encrypting data with the


Additional Resources

* Registry Security Guidelines (.NET): http://msdn.microsoft.com/library/en-us/dnpag2/html/PAGGuidelines0003.asp?frame=true#pagguidelines0003_registry
* Working with Permissions (.NET): http://blogs.msdn.com/asanto/archive/2006/01/22/516009.aspx


Attributes

* Applies To: .NET Framework 2.0, VB
* Category: Registry
* Author: Jonathan Bailey



Return to HomePage
Microsoft Communities