Catalin
Posts: 6724
Joined: Wed Jun 13, 2018 7:49 am

How to set a Windows Service's permissions using ServiceControl and SDDL

Hello guys,

Scenario:

Recently, one of our users asked how to provide permissions for a specific user account (in our case, the Network Service Account) to a service installed by the setup.

I found this to be an interesting scenario and therefore I started investigating further.

Unfortunately, Advanced Installer does not offer predefined support for this task. However, that does not mean it is impossible to achieve it.

If this can not be achieved through our predefined support, it means that we can try through a custom action.

To do so, the first thing we need to do is investigate how this can be achieved outside of Advanced Installer.

There are multiple ways of setting permissions for a service, but unfortunately almost all of them require either third party tools or third party modules (for PowerShell).

The only way to achieve this through a built-in tool is with the help of the sc.exe tool.

This tool comes by default with the Windows OS and you can find it in either:

Code: Select all

C:\Windows\System32
or

Code: Select all

C:\Windows\SysWOW64
SC stands for ServiceControl and with the help of this tool you can perform a lot of operations to a service (such as create, delete, etc.).

SC.exe has the following two commands, which we will be using today:

sdshow --> Display a service's security descriptor using SDDL

sdset --> Sets a service's security descriptor using SDDL

SDDL stands for "Security Descriptor Definition Language". This defines the string format that is used to describe a security descriptor as a text string.

Let's work with an example so we can better understand this. Let's consider we have the following service installed on our machine: winservicesample.exe.

If we want to get a list of the permissions for that service, we can open a command prompt (if possible, elevated) and run the following command:

Code: Select all

sc.exe sdshow winservicesample.exe
It will return something as it follows:
sdshow.png
sdshow.png (30.55 KiB) Viewed 336412 times
D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWRPWPDTLOCRRC;;;NS)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
Well, at a first glance, we can both agree that this doesn't make any sense, but please bear with me as I will try to "decrypt" that.

Let's start with the fact that there are only two letters outside of the parentheses, namely D: and S:.
  • D: comes from discretionary access control list (DACL)
  • S: comes from system access control list (SACL)
For more information about this, please refer to the "Access Control Lists" article.

Now, inside the parantheses, we can see three strings separated by the ";" character.

The first letter can have one of two possible values: allow (A) or deny (D).

The next string represents the assignable permissions on that specific service.

  • CC — SERVICE_QUERY_CONFIG (request service settings)
  • LC — SERVICE_QUERY_STATUS (service status polling)
  • SW — SERVICE_ENUMERATE_DEPENDENTS
  • LO — SERVICE_INTERROGATE
  • CR — SERVICE_USER_DEFINED_CONTROL
  • RC — READ_CONTROL
  • RP — SERVICE_START
  • WP — SERVICE_STOP
  • DT — SERVICE_PAUSE_CONTINUE
The last two characters represent the objects (user, group or SID) that are granted permissions. Please find below a list of the predefined groups:
  • AU --> Authenticated Users
  • AO --> Account operators
  • AN --> Anonymous logon
  • AU --> Authenticated users
  • BA --> Built-in administrators
  • BG --> Built-in guests
  • BO --> Backup operators
  • BU --> Built-in users
  • CA --> Certificate server administrators
  • CG --> Creator group
  • CO --> Creator owner
  • DA --> Domain administrators
  • DC --> Domain computers
  • DD --> Domain controllers
  • DG --> Domain guests
  • DU --> Domain users
  • EA --> Enterprise administrators
  • ED --> Enterprise domain controllers
  • WD --> Everyone
  • PA --> Group Policy administrators
  • IU --> Interactively logged-on user
  • LA --> Local administrator
  • LG --> Local guest
  • LS --> Local service account
  • SY --> Local system
  • NU --> Network logon user
  • NO --> Network configuration operators
  • NS --> Network service account
  • PO --> Printer operators
  • PS --> Personal self
  • PU --> Power users
  • RS --> RAS servers group
  • RD --> Terminal server users
  • SA --> Schema administrators
  • SU --> Service logon user
In the above list of predefined groups, I have highlighted the one we need for today's request, namely the "Network Service Account".

By default, a service installed by your setup under the LocalSystem account will have the following permissions:

Code: Select all

D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)
If we want to add full permissions for the Network Service Account to our service, we can proceed as it follows:

- open an elevated command prompt

- use the sdset command, as it follows:

Code: Select all

sc.exe sdset winservicesample.exe "list of permissions"
e.g.:

Code: Select all

sc.exe sdset winservicesample.exe "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWLOCRRCRPWPDT;;;NS)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"
As you can see, we have added full permissions for the Network Service Account:

Code: Select all

(A;;CCLCSWLOCRRCRPWPDT;;;NS)
How to implement the above in Advanced Installer

Basically, what we need to do is to launch the sc.exe tool with the specific command line as above.

For this, we can use our predefined "Launch EXE with working directory" custom action. To be honest, here you can basically use any custom action that launches a file, not necessarily the one I mentioned.

As the "working directory", we can select the "System" folder, since that is where the sc.exe tool resides.

The custom action can look something as it follows:

LaunchFile.png
LaunchFile.png (129.62 KiB) Viewed 336412 times

File path: sc.exe
Command line:

Code: Select all

sdset winservicesample.exe "D:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)(A;;CCLCSWLOCRRCRPWPDT;;;NS)S:(AU;FA;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;WD)"
Working directory: SystemFolder


Regarding the schedule of the custom action, we should of course schedule it after the setup installs the service.

We can do so by scheduling it after the "Add Resources" action group with its "Execution Time" set to "When the system is being modified (deferred)".

In addition to that, we would like to check the "Run under the LocalSystem account with full privileges (no impersonation)", so the custom action will run elevated.

After installation, in order to check whether the permissions were set or not, you can open a command prompt and use the "sdshow" command, as I have already showcased above.

Additionally, please find attached a sample project including a custom action that sets service permissions for the Network Service account.
AISampleWin32ServiceApp.zip
(107.29 KiB) Downloaded 2847 times
Hope you will find this article helpful.

Best regards,
Catalin
Catalin Gheorghe - Advanced Installer Team
Follow us: Twitter - Facebook - YouTube

Return to “Sample Projects”