Understanding Windows Service Hardening

Windows Server and Vista security features aim to thwart malware and intruders

Executive Summary:

In Windows Server 2008 and Windows Vista, Microsoft introduced new security measures to protect services, which have long been a favored target of malware and hackers. The enhancements include Session 0 isolation, least privilege restrictions, service-specific security identifiers (SIDs), write-restricted SIDs and tokens, and restricted network access. Learn how these new features keep services safer than ever against outside threats.

Windows services have long been a favorite target of malware and hackers. This popularity is the result of a couple of factors. First, many Windows services are turned on by default and can communicate with the network. Second, quite a few services run in a highly privileged security context—for example, the local system account. If such a service is compromised, malware can do anything it wants on the system, including installing programs; viewing, changing, or deleting data; and creating new accounts.

The Blaster worm is one infamous example of malware that leveraged a highly privileged Windows service to harm IT infrastructures around the globe. Blaster exploited a vulnerability in the Windows remote procedure call (RPC) service to execute a buffer overflow that empowered the attacker to run programs and code with local system account privileges on the affected system.

Windows was designed as a multiuser system, which allows different users to use the OS in parallel and enables, among other things, simultaneous user access to file server data. Windows Session Manager (smss.exe) orchestrates this multiuser system, creating and managing terminal sessions (usually referred to as simply "sessions," but not to be confused with user logon or terminal server sessions) for users. Session Manager is one of the first processes to start when Windows boots.

Sessions offer some degree of isolation between services and applications that run in different sessions. Communication between processes that run in the same session occurs easily, but communication between sessions is more restricted and subject to certain security checks. (For details about the workings of Session Manager, see Mark E. Russinovich and David A. Solomon, Microsoft Windows Internals, Microsoft Press, 2005. A new edition is scheduled for release in November 2008.)

The first session created when the OS boots is referred to as Session 0, or the console session. In pre-Vista Windows versions, Session 0 runs services and the applications that are started by the first user who logs on to Windows interactively. However, using Session 0 for user applications is risky because it lets malicious user applications easily interfere with highly privileged services.

The Session 0 isolation feature in Server 2008 and Vista ensures that only Windows services can run in the console session. Applications that are started by the first user to log on interactively run in another session, named Session 1, and thus can't interfere with or affect highly privileged services. Figure 1 illustrates the differences between Windows XP's and Windows Server 2003's session-management architecture and that of Windows Server and Vista.

In Server 2008 and Vista, Session 0 is also marked as non-interactive, meaning that services can't directly communicate with users (e.g., services can't create dialog boxes that request user input). In the past, certain malware attacks leveraged interactive services’ user communication capabilities. Now, services—even those that are marked as interactive or have the Allow service to interact with desktop option enabled in their service properties—won't be visible to users. Although the services will be running, users won't see them in the Windows GUI.

You can see the effect of Session 0 isolation and the fact that this session is marked as non-interactive when you use the At command (at.exe) in Server 2008 or Vista to schedule interactive execution of a program. Because Task Scheduler runs in Session 0, it can't execute programs that interact with the user desktop. The scheduler informs you of this restriction when you schedule an interactive program, as Figure 2 shows.

The fact that Session 0 is marked as non-interactive doesn't mean that Session 0 services can't interact with users–some applications require this functionality. Developers can use secure interprocess communications tools such as named pipes and RPCs to let Session 0 services securely interact with the desktop. You can find more information on the effects of Session 0 isolation and how developers can deal with it in their applications, services, and driver software in the Microsoft white paper "Impact of Session 0 Isolation on Services and Drivers in Windows Vista" at www.microsoft.com/whdc/system/vista/services.mspx.

Microsoft also provides a workaround for the non-interactive nature of Session 0 for legacy services or services that your organization can't just rewrite on the fly. The workaround is the Interactive Services Detection service (ui0detect.exe). This service is turned off by default. When you turn it on (from the Services node in the Microsoft Management Console—MMC—Active Directory Users and Computer snap-in or from the command line using sc.exe), it enables legacy interactive services to interact with the user. When a service attempts to interact with a user, ui0detect generates a user approval prompt before displaying the actual service dialog box.

The Interactive Services Detection service workaround is both insecure (which explains why Microsoft turns it off by default) and temporary. Malicious software can leverage the service to interact with the user. Microsoft plans to remove the ui0detect service in the next major Windows release.

Additionally, the Interactive Services Detection service works only for Windows GUI–based services, not for console- or command prompt–based services. Turning ui0detect on doesn't re-enable the At command to execute interactive tasks.

Least-Privilege Restrictions

Server 2008 and Vista include several least-privilege mechanisms that guarantee that a service gets only the privileges it needs to do its job—nothing less and nothing more. For example, Microsoft revisited the default permissions and rights assigned to the built-in Windows services and removed several unneeded service permissions and rights. Also, many services that ran on the local system in earlier Windows versions now run as either LocalService or NetworkService—the two less-privileged service accounts introduced in XP SP2 and Windows 2003.

Additionally, a brand-new mechanism specifies and enforces the rights that are assigned to a service. You can think of this mechanism as a User Account Control (UAC)–like least-privilege solution for services. (A Server 2008 and Vista least-privilege feature, UAC ensures that, by default, user applications execute with few privileges and that all users—including administrators—have only basic user-level privileges. For an introduction to UAC, see “Windows Vista’s Take on Least Privilege,” October 2006, InstantDoc ID 93300.)

Here's how the least-privilege mechanism for services works. The Service Control Manager (SCM) component assigns service privileges according to the privilege information specified in a service’s RequiredPrivileges registry entry. The SCM ensures that only the privileges specified in the service’s RequiredPrivileges entry are enabled in the access token of the process that hosts the service. The SCM also enforces the RequiredPrivileges settings beyond system startup by ensuring that a service can't be given additional privileges while it's running. All services’ configuration information is stored in the registry's HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services key, which has a subkey for each service that runs on your system.

Suppose I create a service called MyService and set it to execute in the security context of the local system account (i.e., MyService’s service account). On Server 2008 and Vista, I can specify that MyService requires only the Backup files and directories user right by including this right in the service’s RequiredPrivileges registry entry. When the SCM starts MyService, it will enable only the Backup files and directories user right in the access token of the process that hosts MyService. In earlier Windows versions, the hosting process had an access token that enabled all the default privileges given to the local system account. Because the local system is the almighty account on a Windows machine, that approach gave the service many privileges.

To set a service’s RequiredPrivileges registry entry and specify the rights that the service should have, you can use the SC command. For the MyService example, I could restrict MyService’s rights by running the command

sc privs MyService SeBackupPrivilege

To get an overview of the required rights as they are specified in a service’s RequiredPrivileges registry entry, use the command

sc qprivs service_name

where service_name is the name of the service whose rights you want to see. Figure 3 illustrates the required rights as they are specified in the registry for the remote management (WinRM) service.

To observe the effect of the SCM’s rights-filtering actions, you can use the Windows Sysinternals Process Explorer tool. (It's available at technet.microsoft.com/en-us/sysinternals/bb896653.aspx.) Start Process Explorer and right-click a process to open its properties, then click the Security tab. Figure 4 shows the security properties of the Winlogon process as they appear in Process Explorer. Note that even though Winlogon runs in the security context of the local system account (NTAuthority\System), its access token contains several rights that are disabled, thanks to the new least-privilege restrictions.

Service-Specific SIDs

In Server 2008 and Vista, each service can have a service-specific SID. Administrators and service developers can use service-specific SID in ACLs to protect service-specific resources. In earlier Windows versions, if you use a built-in service account (e.g., the local system account, the network service account) to run a service and grant the service account access to a resource, you also implicitly allow all other services that run under the same service account to access that resource whether they need it or not. To avoid this problem, administrators typically create a custom Windows account to run their services. However, this practice creates additional account management overhead. When you create custom service accounts, you can't leverage the automated password management features Windows provides for built-in Windows accounts.

Because Server 2008 and Vista let you create a service-specific SID for services, you don't need to worry about the cumbersome process of creating and maintaining custom service accounts. The service-specific SID is linked to the service’s name (e.g., MyService), and not to the service account (e.g., LocalSystem) or to a custom Windows account. Thanks to service-specific SIDs, you can continue to use the built-in service accounts for authenticating your service while relying on the service-specific SID to set permissions on service resources.

If you want a service to have a service-specific SID, you must set the service’s SID type property to either unrestricted or restricted—I explain the difference between these two property types later in the section on write-restricted tokens. You can set a service’s SID type by using the SC command:

sc sidtype service_name unrestricted

To query the current value of a service’s SID type property, enter

sc qsidtype service_name

When your service has a service-specific SID, Windows automatically computes a SID and links it to the service. The next time the service starts, that SID is added to the access token of the process that hosts the service. Service-specific SIDs are local (i.e., machine-level as opposed to domain-level) SIDs.

The service-specific SID is constructed from the service name using the format S-1-5-80-\{SHA-1(service name in uppercase)\}. As you can see, the SID for a particular service is identical for all Vista and Server 2008 machines, which greatly facilitates resource permissioning for the service on different machines.

After you configure a service-specific SID, you can leverage the SID to restrict access to your service’s file system and registry resources. To refer to a service-specific SID when setting permissions on resources, use the syntax NT SERVICE\service_name.

Write-Restricted SIDs and Tokens

Service-specific SIDs let administrators better control access to service resources. However, a service-specific SID can't prevent a service from accessing the resources to which its service account’s SID has access. For example, let's say MyService runs in the security context of the local service account and has a service-specific SID defined. In addition to having access to objects that the service-specific SID specifically grants access to, MyService can access all objects that the local service account can access. If MyService were compromised, an attacker could access non-service–related resources.

In Server 2008 and Vista, Microsoft tackles this problem by introducing write-restricted service-specific SIDs (which I'll refer to as restricted SIDs). You can make a service-specific SID restricted by setting its SID type property to restricted:

sc sidtype MyService restricted

Developers can make a service’s SID write-restricted by including the WRITE_RESTRICTED flag in the service code. When a service has a write-restricted SID, an extra access-control check occurs when the service attempts to access a resource. The access-control check consists of two independent passes. For access to be granted, both passes must succeed.

The first pass is the typical access control pass that's always performed. During this pass, Windows evaluates whether a service should be denied or granted access to a resource according to the resource’s permissions and the information in the service’s hosting-process access token.

The second pass is an extra access control pass that normally doesn't occur. During this second pass, Windows explicitly checks whether the resource’s permissions give explicit write access to either the service-specific SID, or the predefined "Logon SID," "Everyone," or "WRITE RESTRICTED" SIDs.

You can use restricted SIDs only to restrict access to a service—not to broaden access. For example, if you enable a restricted SID for MyService, MyService cannot write to any of the objects to which the LocalService account can write unless those objects also explicitly grant write access to MyService's service SID.

Although write-restricted SIDs significantly improve security, they also require extra management. For a service to operate properly after it's been assigned a write-restricted SID, you must find all resources that the service needs write access to, then explicitly grant the service write permission to each one. (No pain, no gain!)

The Windows Firewall service (mpssvc.exe) is an example of a service whose SID is defined as write-restricted. It's hosted together with other services in a single svchost.exe process instance. The service account of the svchost.exe instance is the local system account. You can use the SysInternals Process Explorer tool to check the content of the svchost.exe instance’s access token. Open the properties of the Windows Firewall's svchost.exe instance and click the Security tab. You'll see an interface like that in Figure 5. The effect of defining the Windows Firewall’s SID as write-restricted is that only the Firewall service (not any other services that are also running in the security context of the local system account) is allowed to write to resources to which the Firewall service’s SID has been granted explicit write access. One such resource is the %System%\LogFiles\Firewall folder, which holds the Windows Firewall logs.

Restricted Network Access

The final piece of Windows Service Hardening consists of the restrictions developers can put on a service’s network access. A common misconception about the new service network access restrictions is that they are integrated with the network restrictions defined in the Windows Firewall (the personal firewall that runs on every Vista and Server 2008 platform). In fact, they are not. Network access restrictions for services

are evaluated before the Windows Firewall rules;

are enforced regardless of the status of Windows Firewall—even when Windows Firewall is turned off;

can be used only to restrict (deny) access for a service, not to grant (allow) access;

can be used for both inbound and outbound connections to services; and

can't be defined from the Windows Firewall with Advanced Security MMC snap-in or using the netsh advfirewall command—they must be defined programmatically using the INetFwServiceRestriction and INetFwRule programming interfaces.

Besides letting developers define custom network access restrictions for services, Server 2008 and Vista include a set of predefined network access restrictions for built-in services. You can't modify these predefined restrictions using the programming interfaces I mentioned above, but if you have administrator-level privileges you can modify them in the system registry. Both types of service network access restrictions are stored in the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\RestrictedServices\ registry key. The predefined restrictions are stored in the Static\System key, as Figure 6 shows; custom restrictions are stored in the Configurable key.

Security and Simplicity Rarely Go Hand In Hand

Windows Service Hardening is a big and important step in Microsoft’s crusade to make Windows a fundamentally secure platform. I think Microsoft could have made the configuration of the features simpler, but they might have intentionally chosen not to: Locking down services is something that should be left to developers and security specialists. Nevertheless, it's important for every Windows administrator to have a good understanding of the workings of Windows Service Hardening.