I apologize for my presumption,  but thought it was a cool title 😉

Some days ago, I was reflecting on the SeRestorePrivilege and wondering if a user with this privilege could alter a Service Access, for example: grant to everyone the right to stop/start the service,  during a “restore” task.  (don’t expect some cool bypass or exploit here)

As you probably know, each object in Windows has DACL’s & SACL’s which can be configured. The most “intuitive” are obviously files and folder permissions but there are a plenty of other securable objects (https://docs.microsoft.com/en-us/windows/desktop/secauthz/securable-objects)

Given that  our goal is Service permissions, first we will  try to understand how they work and how we can manipulate them.

Service security can be split into 2 parts:

  • Access Rights for the Service Control Manager
  • Access Rights for a Service

We will focus on  Access Rights for the service, which means who can start/stop/pause service and so on. For detailed explanation take a look at this article from Microsoft: https://docs.microsoft.com/it-it/windows/desktop/Services/service-security-and-access-rights

 

How can we  change the service security settings?

Configuring Service Security and Access Rights is not so an immediate task like, for example, changing DACL’s of file or folder objects. Keep also in mind that it is limited only to privileged users like Administrators and SYSTEM account.

There are some built-in and third party tools which permits changing the DACL’s of a service, for example:

Windows “sc.exe”.  This program has a lot of options and with “sdset” it is possible to modifiy the security setting of a service, but you have to specify it in the cryptic SDDL (Security Description Definition Language). The opposite command “sdshow” will list the SDDL:

sddl2

Note that interactive user (IU) cannot start or stop the BITS service because the necessary rights (RP,WP) are missing. I’m not going to explain in deep this stuff, if interested look here: https://support.microsoft.com/en-us/help/914392/best-practices-and-guidance-for-writers-of-service-discretionary-acces

subinacl.exe from Windows Resource Kit.  This one is much more easier to use. In this example we will grant to everyone the right to start the BITS (Backgound intelligent transfer service)

subinacl

Service Security Editor , a free GUI Utility to set permissions for any Windows Service:

servicesec

And of course, via Group Policy, powershell, etc..

All these tools and utilities relies on this Windows API call, accessible only to high privileged users:

BOOL SetServiceObjectSecurity(
SC_HANDLE hService, 
SECURITY_INFORMATION dwSecurityInformation, 
PSECURITY_DESCRIPTOR lpSecurityDescriptor 
);

Where are the service security settings stored?

Good question! First of all, we have to keep in mind that services have a “default” configuration: Administrators have full control, standard users can only interrogate the service, etc..  Services with non default configuration have their settings stored in the registry under this subkey:

HKLM\System\CurrentControlSet\Services\<servicename>\security

This subkey hosts a REG_BINARY key which is the binary value of the security settings:

regsec.JPG

These “non default” registry settings are read when the Service Control Manager starts (upon boot) and stored in memory.  If we change the service security settings with one of the tools we mentioned before, changes are immediately applied and  stored in memory. During the shutdown process, the new registry values are written.

And the Restore Privilege?

You got it! With the SeRestorePrivilege, even if  we cannot use the  SetServiceObjectSecurity API call, we can restore registry keys, including the security subkey…

Let’s make an example:  we want to grant to everyone full control over BITS service

On our Windows test machine, we just modify the settings with one of the tools:

newbitssec.JPG

 

After that, we restart our box and copy the new  binary value of the security key:

bitsfull

Now that we have the right values, we just need to “restore” the security key with these.  For this purpose we are going to use a small “C” program, here the relevant part:

byte data[] = { 0x01, 0x00, 0x14, 0x80, 0xa4, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x02, 
0x00, 0x20, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 
0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x02, 0x14, 0x00, 0xff, 0x01, 0x0f, 0x00, 0x01, 0x01, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x05, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xff, 0x01, 0x0f, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 
0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0xff, 0x01, 0x0f, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x8d, 0x01, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x14, 0x00, 0x8d, 0x01, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x20, 0x00, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00 };
LSTATUS stat = RegCreateKeyExA(HKEY_LOCAL_MACHINE,
               "SYSTEM\\CurrentControlSet\\Services\\BITS\\Security",
               0,
               NULL,
               REG_OPTION_BACKUP_RESTORE,
               KEY_SET_VALUE,
               NULL,
               &hk,
               NULL);
stat = RegSetValueExA(hk, "security", 0, 
       REG_BINARY, (const BYTE*)data,sizeof(data));
if (stat != ERROR_SUCCESS) {
     printf("[-] Failed writing!", stat);
     exit(EXIT_FAILURE);
}
printf("Setting registry OK\n");

 

We need of course to enable  the SE_RESTORE_NAME privilege before in our process token.

In an elevated shell, we execute the binary on the victim machine:

restorebits1

and after the reboot we are able to start BITS even with a low privileged user:

restorebits2

And the Take Onwer Privilege?

The concept is the same, we need to take the ownership of the registry key before, grant the necessary access rights (SetNamedSecuityInfo() API calls) on the key and then do the same trick we have seen before.

But wait, one moment! What if we take the onwersip of the service?

dwRes = SetNamedSecurityInfoW(
        L"BITS", 
        SE_SERVICE, 
        OWNER_SECURITY_INFORMATION,
        takeownerboss_sid, 
        NULL,
        NULL,
        NULL);

Yes, this works, but when we set the permissions on the object (again with SetNamedSecurityInfo) we get an error. If we do this with admin rights, it works…

Probably the function will call the underlying SetServiceObjectSecurity which modifies the permissions of the service stored “in memory” and this is precluded to non admins.

 

Final thoughts

So we were able to change the Service Access Rights with our “restoreboss” user. Nothing really useful i think, but sometimes it’s  just fun  to try to understand some parts of the Windows internal mechanism, do you agree?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s