• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 275
  • Last Modified:

Registry Security

What security issues are involved with writing to the registry in an app (on NT4)? My RegCreateKey call fails when a user without administrative rights runs my app. I'm sure I need to do something with a security descriptor object, but I'd appreciate if someone could point me in the right direction.
0
cdickerson
Asked:
cdickerson
  • 3
  • 3
1 Solution
 
jkrCommented:
When these keys were created by an admin, only members of the admin group are allowed to access them. Use the following code to set access for a certain group on a registry key:

/*------------------------------------------------------------------
| Name: CreateSDForRegKey
| Desc: creates SD with access for up to MAX_LIST users or groups
|   passed into function:
|    SID from the group or user
|    permission access requested
------------------------------------------------------------------*/
DWORD CreateSDForRegKey ( LPTSTR pszGroupName[], DWORD dwAccessMask)
{
#define MAX_LIST 10

 PSID        pGroupSID [MAX_LIST];
 DWORD       dwGroupSIDCount = 0;
 DWORD       cbSID;

 SID_NAME_USE snuGroup;

 DWORD       dwDomainSize = 80;
 TCHAR       szDomainName[80];

 PSECURITY_DESCRIPTOR pAbsSD = NULL;

 PACL        pDACL;

 DWORD       dwSDRevision;
 DWORD       dwDACLLength = sizeof ( ACL);

 SECURITY_DESCRIPTOR_CONTROL sdcSDControl;

 PACL        pNewDACL  = NULL;

 BOOL        fAceFound = 0;

 BOOL        fHasDACL  = FALSE;
 BOOL        fDACLDefaulted = FALSE;

 ACCESS_ALLOWED_ACE  *pDACLAce;

 DWORD       dwError = 0;

 DWORD       i;

 // handle for security registry key
 HKEY  hSecurityRegKey = ( HKEY) 0;


 // inits
 for ( i = 0; i < MAX_LIST; i++)
  pGroupSID[i] = NULL;

 // count number of groups or users to be added; list ends in NULL
 for ( i = 0; pszGroupName[i] != NULL; i++);

 if ( i > MAX_LIST)
  return ( ERROR_TOO_MANY_NAMES);
 else
  dwGroupSIDCount = i;

 // get SIDs for each group or user passed in
 for ( i = 0; i < dwGroupSIDCount; i++)
 {
  cbSID = GetSidLengthRequired (2);

  pGroupSID[i] = ( PSID) malloc ( cbSID);

  // loop if not enough room for SID; otherwise set to NULL
  while ( ! LookupAccountName ( NULL, pszGroupName[i], pGroupSID[i],
     &cbSID, szDomain, &dwDomainSize, &snuGroup) )
  {
   dwError = GetLastError();

   if ( dwError == ERROR_INSUFFICIENT_BUFFER)
    pGroupSID[i] = ( PSID) realloc ( pGroupSID[i], cbSID);
   else
   {
    pGroupSID[i] = NULL;

    break;
   }
  }




  // check if found group or user
  if ( pGroupSID[i])
  {
   // add to DACL length
   dwDACLLength += ( sizeof ( ACCESS_ALLOWED_ACE) -
        sizeof ( DWORD) + GetLengthSid ( pGroupSID[i]);
  }
 }

 // get memory needed for new DACL
 if ( ! ( pNewDACL = ( PACL) malloc ( dwDACLLength) ) )
  return ( GetLastError());

 // get memory for new SD
 if ( ! ( pAbsSD = ( PSECURITY_DESCRIPTOR)
      malloc ( SECURITY_DESCRIPTOR_MIN_LENGTH + dwDACLLength) ) )
 {
  dwError = GetLastError();

  goto ErrorExit;
 }

 // init new SD
 if ( ! InitializeSecurityDescriptor ( pAbsSD,
            SECURITY_DESCRIPTOR_REVISION) )
 {
  dwError = GetLastError();

  goto ErrorExit;
 }

 // init new DACL
 if ( ! InitializeAcl ( pNewDACL, dwDACLLength, ACL_REVISION) )
 {
  dwError = GetLastError();

  goto ErrorExit;
 }

 // now add new ACEs to new DACL
 for ( i = 0; i < dwGroupSIDCount; i++)
 {
  // if there is a valid SID, then attach to the ACE and add to the DACL
  if ( pGroupSID[i])
  {
   if ( ! AddAccessAllowedAce ( pNewDACL, ACL_REVISION, dwAccessMask,
               pGroupSID[i]) )
   {
    dwError = GetLastError();

    goto ErrorExit;
   }
  }
 }

 // check if everything went ok
 if ( ! IsValidAcl ( pNewDACL) )
 {
  dwError = GetLastError();

  goto ErrorExit;
 }

 // now set DACL to the SD
 if ( ! SetSecurityDescriptorDacl ( pAbsSD, TRUE, pNewDACL,
              fDACLDefaulted) )
 {
  dwError = GetLastError();

  goto ErrorExit;
 }

 // check if everything went ok
 if ( ! IsValidSecurityDescriptor ( pAbsSD) )
 {
  dwError = GetLastError();

  goto ErrorExit;
 }

 // now open reg key to set security
 // note: pzsRegKeyName is a global
 if ( ( dwError = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, pszRegKeyName, 0,
          KEY_ALL_ACCESS, &hSecurityRegKey) ) )
  goto ErrorExit;


 // now set the reg key security (this will overwrite any existing security)
 dwError = RegSetKeySecurity (
      hSecurityRegKey,
      (SECURITY_INFORMATION)( DACL_SECURITY_INFORMATION),
      pAbsSD);

 // close reg key
 RegCloseKey ( hSecurityRegKey);


ErrorExit:

 // free memory
 if ( pAbsSD)
  free ( ( VOID *) pAbsSD);
 if ( pNewDACL)
  free ( ( VOID *) pNewDACL);

 return ( dwError);
}
/* eof - CreateSDForRegKey */

Feel free to ask if you need more information!


0
 
cdickersonAuthor Commented:
Can you further summarize what this code is doing? I'm adding the user himself to an access list??

Also, I'm not sure I understand what you mean by "When these keys were created by an admin, only members of the admin group are allowed to access them". The key is created at run-time.

Thanks for your response.
0
 
jkrCommented:
The above code adds an 'access allowed ACE' for a certain group to the security descriptor of a registry, causing this group to be able to access the key.

I assumed that your 'runtime-created' keys were created by a process running under the 'admin' account, thus setting the default 'admin' access rights on these keys...
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
cdickersonAuthor Commented:
Ok, perhaps I'm going about this wrong. With each run of the application, I create a key (in case it wasn't there), and write to it.

Should I instead create that key with the install program (running under admin), and at *that* time grant the current user permission to write to it (which is what your code is doing)??
0
 
jkrCommented:
>>and at *that* time grant the current user permission to
>>write to it

That's the idea - however, you could change the access rights later, also, but the program changing the rights must have access to these keys (i.e. run under the admin account also)

An alternative would be to use 'RegCreateKeyEx()' supplying an appropriate 'SECURITY_ATTRIBUTES' struct, e.g.

SECURITY_ATTRIBUTES sa;
PSID psidWorldSid; // a SID representing "everyone"
SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;

psidWorldSid = (PSID) LocalAlloc(LPTR, GetSidLengthRequired(1));
InitializeSid(psidWorldSid, &siaWorldSidAuthority, 1);
*(GetSidSubAuthority(psidWorldSid, 0)) = SECURITY_WORLD_RID;

SECURITY_DESCRIPTOR         sd;

if  (   !InitializeSecurityDescriptor   (   &sd,    SECURITY_DESCRIPTOR_REVISION)
    )
    {
        //  error
    }

// here I set the _group_ to 'world', but you could also use
// 'owner'...
if  (   !SetSecurityDescriptorGroup (   &sd,    psidWorldSid,   TRUE)
    )
    {
        //  error
    }

sa.nLength = sizeof ( SECURITY_ATTRIBUTES );
sa.lpSecurityDescriptor = & sd;
sa.bInheritHandle = FALSE;
0
 
cdickersonAuthor Commented:
Thanks a lot.
0

Featured Post

Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

  • 3
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now