Day Three of our series of posts in preparation for the Windows Server 2008 Launch and the countdown continues. If it’s a weekend for you, I hope you are enjoying yourself. Only twenty-four more days to go till Launch Day. Today’s post – Windows Service Hardening.
Windows Service Hardening restricts critical Windows services from doing abnormal activities in the file system, registry, network or other areas that could be exploited by malware. From the perspective of "always-on" code on the operating system, Windows services represent a large percentage of the overall attack surface on the system, especially if you consider the privilege level of that code. Windows Server 2008 limits the number of services that are running and operational by default. Windows Service Hardening reduces the damage potential of a compromised service by introducing several changes to Windows Services on both Windows Vista and Windows Server 2008:
Introduction of a per-service security identifier (SID): A per-service SID creates, in essence, an identity for each service which enables access control using the existing Windows access control model. Services can now apply explicit access control lists (ACL’s) to resources that are private to the service – preventing other services as well as the user from accessing that resource. A per-service SID may be assigned during the service installation via the ChangeServiceConfig2 API or by using the SC.EXE command with the sidtype verb. There are three possible values:
- None (0x0) – the service will not have a per-service SID. This is the default configuration for a service
- Unrestricted (0x1) – the service has a per-service SID
- Restricted (0x3) – the service has a per-service SID and a write-restricted token.
So if you wanted to create a per-service you could use the following command syntax: sc sidtype <service name> <restricted | unrestricted>. If you want to view the configuration of a service you could use the following command: sc qsidtype <service name>. The screenshot below shows an example of an unrestricted and a restricted service.
If a service is configured to have a per-service SID (whether the service is Restricted or Unrestricted), then the service SID is computed using a SHA-1 hash. To view the SID for a service,use the sc showsid <service name> command as shown below:
A service configured to have a per-service SID can be granted access to resources needed by the service. Prior to Windows Vista, if a service running in the context of a built-in account such as Local Service or Network Service needed access to a resource, that meant that all of the other services running in that context also had access to that resource. To work around that problem, administrators started using dedicated service accounts which added considerable administrative overhead. With the per-service SID mechanism, the built-in service accounts can be used with the additional benefit of having more granular control via the per-service SID and being able to set ACL’s on resources specific to the service. When using the ACL editor for the file system or registry, you can use the following syntax to identify a service SID and add it to a resource: NT SERVICE\<service name>. Let’s now move on to another new security feature dealing with services:
Removal of unnecessary Windows privileges on a per-service basis: In Windows Vista and Windows Server 2008, a new registry value was introduced to specify the privileges that a service should execute with. The new value is RequiredPrivileges. The process hosting the service has only the privileges specified in the registry value. Something important to note here – you cannot use the RequiredPrivilege mechanism to augment a service’s privileges – only to reduce them. If RequiredPrivileges refers to a privilege that the service does not already have, then those privileges are ignored. The RequiredPrivilege value is stored in the specific service configuration key for the individual service under HKLM\System\CurrentControlSet\Services. The ChangeServiceConfig2 API or the sc command can be used to modify and view the privileges. To configure the privileges for a service, use the following syntax: sc privs <service name> <privileges>. Privileges are specified by their string. For example, the string for the Impersonate privilege is SeImpersonatePrivilege. To query the current configuration for a service, use the following syntax: sc qprivs <service name> as shown below.
Determining what privileges are needed by a service is not an easy task – in some cases, you may have to use trial and error. The Windows SDK documentation discusses the privileges needed when working with particular API’s and whether those privileges should be enabled before calling the API. That having been said – do not start making changes to the Service Privileges without thorough testing in an isolated environment. Finally, there are still some situations where a dedicated domain wide user account will be necessary, for example where a service needs to be trusted, or needs access to remote resources such as allowing the Performance Logs and Alerts service to query a remote machine.
The last change we’re going to look at today is Applying a write-restricted access token to the service process. This access token can be used when the set of objects written to by the service is bounded and can be configured. An attempt to write to resources that do not explicitly grant the Service SID access will fail. The important thing to note here is that a write-restricted token is only restricted from write operations. It is less restrictive than a restricted token that is restricted for all types of access. The write-restricted token for a "Restricted" service will have the following restricting SID’s: the per-service SID, the logon SID, the Everyone SID, and the new write-restricted SID (S-1-5-33 or NT AUTHORITY\WRITE RESTRICTED). The per-service SID and the write-restricted SID are also added to the Group SID’s. Write-restricted SID’s provide the following functionality:
- Writes are only possible by virtue of the service SID, the logon SID, Everyone SID, or write-restricted SID, and not the service account nor its groups.
- The write-restricted SID allows for granting access to write-restricted service as a class – without knowing beforehand which services will be write-restricted
- By default, the write-restricted service loses write access to many resources that it would normally have access to. You have to grant write-access to the service SID, the logon SID, the write-restricted class or the Everyone group in order to write to these resources
The drawback to using write-restricted SID’s is the time to implement. You have to determine all of the write accesses that the service will need and explicitly grant access. Within Windows Vista and Windows Server 2008, there are only a few services that are defined as write-restricted by default. One such service is the Windows Firewall service (the short name for which is MPSSVC). Since the Firewall service is write-restricted, the only resources to which it can write are resources to which it has access based on the rules listed above. One such location is the folder hosting the log files for the Firewall (c:\Windows\Ssytem32\LogFiles\Firewall). If you view the security tab for this folder, you can see that the MpsSvc account has been explicitly granted rights to this folder as shown below:
And that wraps up Day Three. Tomorrow we’ll look at Service Shutdown and Crash Handling. Until next time …
- MSDN: Authorization Constants
- Technet: Windows Vista Security and Data Protection Improvements – Windows Service Hardening
- Technet Magazine Security Watch (January 2007) article on Services Hardening
- Cyril Voisin’s Technet Blog: Five Posts on Service Hardening